2 * Author: yucong xiong <yucong.xion@mediatek.com>
4 * This software is licensed under the terms of the GNU General Public
5 * License version 2, as published by the Free Software Foundation, and
6 * may be copied, distributed, and modified under those terms.
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
14 #include <linux/interrupt.h>
15 #include <linux/i2c.h>
16 #include <linux/slab.h>
17 #include <linux/irq.h>
18 #include <linux/miscdevice.h>
19 #include <asm/uaccess.h>
20 #include <linux/delay.h>
21 #include <linux/input.h>
22 #include <linux/workqueue.h>
23 #include <linux/kobject.h>
24 #include <linux/earlysuspend.h>
25 #include <linux/platform_device.h>
26 #include <asm/atomic.h>
28 //#include <mach/mt_devs.h>
29 #include <mach/mt_typedefs.h>
30 #include <mach/mt_gpio.h>
31 #include <mach/mt_pm_ldo.h>
33 #define POWER_NONE_MACRO MT65XX_POWER_NONE
35 #include <linux/hwmsensor.h>
36 #include <linux/hwmsen_dev.h>
37 #include <linux/sensors_io.h>
39 #include <cust_eint.h>
40 #include <cust_alsps.h>
42 //#include <linux/hw_module_info.h>
43 #include <linux/sched.h>
45 #include <linux/batch.h>
47 #ifdef CUSTOM_KERNEL_SENSORHUB
48 #include <SCP_sensorHub.h>
51 /******************************************************************************
53 *******************************************************************************/
54 /*----------------------------------------------------------------------------*/
56 #define CM3232_DEV_NAME "cm3232"
57 /*----------------------------------------------------------------------------*/
58 #define APS_TAG "[ALS/PS] "
59 #define APS_FUN(f) printk(KERN_INFO APS_TAG"%s\n", __FUNCTION__)
60 #define APS_ERR(fmt, args...) printk(KERN_ERR APS_TAG"%s %d : "fmt, __FUNCTION__, __LINE__, ##args)
61 #define APS_LOG(fmt, args...) printk(KERN_INFO APS_TAG fmt, ##args)
62 #define APS_DBG(fmt, args...) printk(KERN_INFO APS_TAG fmt, ##args)
63 /******************************************************************************
65 *******************************************************************************/
66 extern void mt65xx_eint_unmask(unsigned int line
);
67 extern void mt65xx_eint_mask(unsigned int line
);
68 extern void mt65xx_eint_set_polarity(unsigned int eint_num
, unsigned int pol
);
69 extern void mt65xx_eint_set_hw_debounce(unsigned int eint_num
, unsigned int ms
);
70 extern unsigned int mt65xx_eint_set_sens(unsigned int eint_num
, unsigned int sens
);
71 extern void mt65xx_eint_registration(unsigned int eint_num
, unsigned int is_deb_en
, unsigned int pol
, void (EINT_FUNC_PTR
)(void), unsigned int is_auto_umask
);
73 /*----------------------------------------------------------------------------*/
74 static int cm3232_i2c_probe(struct i2c_client
*client
, const struct i2c_device_id
*id
);
75 static int cm3232_i2c_remove(struct i2c_client
*client
);
76 static int cm3232_i2c_detect(struct i2c_client
*client
, struct i2c_board_info
*info
);
77 static int cm3232_i2c_suspend(struct i2c_client
*client
, pm_message_t msg
);
78 static int cm3232_i2c_resume(struct i2c_client
*client
);
80 static int cm3232_remove(void);
81 static int cm3232_local_init(void);
83 static int cm3232_init_flag
=-1; // 0<==>OK -1 <==> fail
84 static struct alsps_init_info cm3232_init_info
= {
86 .init
= cm3232_local_init
,
87 .uninit
= cm3232_remove
,
91 /*----------------------------------------------------------------------------*/
92 static const struct i2c_device_id cm3232_i2c_id
[] = {{CM3232_DEV_NAME
,0},{}};
93 static struct i2c_board_info __initdata i2c_cm3232
={ I2C_BOARD_INFO(CM3232_DEV_NAME
, (0x20>>1))};
94 /*----------------------------------------------------------------------------*/
96 /*static hw_module_info hw_info = {
97 .type = HW_MODULE_TYPE_ALSPS,
99 .priority = HW_MODULE_PRIORITY_ALSPS,
107 struct i2c_client
*client
;
108 struct work_struct eint_work
;
109 #ifdef CUSTOM_KERNEL_SENSORHUB
110 struct work_struct init_done_work
;
116 atomic_t als_suspend
;
117 atomic_t als_debounce
; /*debounce time after enabling als*/
118 atomic_t als_deb_on
; /*indicates if the debounce is on*/
119 atomic_t als_deb_end
; /*the jiffies representing the end of debounce*/
128 u32 als_level
[C_CUST_ALS_LEVEL
-1];
129 u32 als_value
[C_CUST_ALS_LEVEL
];
131 atomic_t als_cmd_val
; /*the cmd value can't be read, stored in ram*/
132 atomic_t als_thd_val_high
; /*the cmd value can't be read, stored in ram*/
133 atomic_t als_thd_val_low
; /*the cmd value can't be read, stored in ram*/
134 ulong enable
; /*enable mask*/
135 ulong pending_intr
; /*pending interrupt*/
138 #if defined(CONFIG_HAS_EARLYSUSPEND)
139 struct early_suspend early_drv
;
142 /*----------------------------------------------------------------------------*/
144 static struct i2c_driver cm3232_i2c_driver
= {
145 .probe
= cm3232_i2c_probe
,
146 .remove
= cm3232_i2c_remove
,
147 .detect
= cm3232_i2c_detect
,
148 .suspend
= cm3232_i2c_suspend
,
149 .resume
= cm3232_i2c_resume
,
150 .id_table
= cm3232_i2c_id
,
152 .name
= CM3232_DEV_NAME
,
155 /*----------------------------------------------------------------------------*/
156 static struct i2c_client
*cm3232_i2c_client
= NULL
;
157 //static struct cm3232_priv *g_cm3232_ptr = NULL;
158 static struct cm3232_priv
*cm3232_obj
= NULL
;
159 //static struct platform_driver cm3232_alsps_driver;
160 /*----------------------------------------------------------------------------*/
163 /*----------------------------------------------------------------------------*/
167 /*-----------------------------CMC for debugging-------------------------------*/
169 CMC_TRC_ALS_DATA
= 0x0001,
170 CMC_TRC_EINT
= 0x0004,
171 CMC_TRC_IOCTL
= 0x0008,
172 CMC_TRC_I2C
= 0x0010,
173 CMC_TRC_CVT_ALS
= 0x0020,
174 CMC_TRC_DEBUG
= 0x8000,
176 /*----------------------------------------------------------------------------*/
177 static void cm3232_power(struct alsps_hw
*hw
, unsigned int on
)
179 static unsigned int power_on
= 0;
181 APS_LOG("power %s\n", on
? "on" : "off");
183 if(hw
->power_id
!= POWER_NONE_MACRO
)
187 APS_LOG("ignore power control: %d\n", on
);
191 if(!hwPowerOn(hw
->power_id
, hw
->power_vol
, "CM3232"))
193 APS_ERR("power on fails!!\n");
198 if(!hwPowerDown(hw
->power_id
, "CM3232"))
200 APS_ERR("power off fail!!\n");
206 /********************************************************************/
207 int cm3232_enable_als(struct i2c_client
*client
, int enable
)
209 struct cm3232_priv
*obj
= i2c_get_clientdata(client
);
212 client
->addr
&=I2C_MASK_FLAG
;
213 client
->addr
|=I2C_WR_FLAG
;
214 client
->addr
|=I2C_RS_FLAG
;
217 APS_LOG("cm3232_enable_als enable_als\n");
218 #if 0//modify for cm3232 speed up report rate.131012 xgt
219 databuf
[0] = CM3232_REG_ALS_CONF
;
220 res
= i2c_master_send(client
, databuf
, 0x201);
223 APS_ERR("i2c_master_send function err\n");
224 goto ENABLE_ALS_EXIT_ERR
;
227 APS_LOG("CM3232_REG_ALS_CONF evalue value_low = %x, value_high = %x\n",databuf
[0],databuf
[1]);
229 databuf
[1] = 0x00;//databuf[0]&0xFE;
230 databuf
[0] = CM3232_REG_ALS_CONF
;
231 client
->addr
&=I2C_MASK_FLAG
;
233 res
= i2c_master_send(client
, databuf
, 0x2);
236 APS_ERR("i2c_master_send function err\n");
237 goto ENABLE_ALS_EXIT_ERR
;
239 atomic_set(&obj
->als_deb_on
, 1);
240 atomic_set(&obj
->als_deb_end
, jiffies
+atomic_read(&obj
->als_debounce
)/(1000/HZ
));
243 APS_LOG("cm3232_enable_als disable_als\n");
244 #if 0//modify for cm3232 speed up report rate.131012 xgt
245 databuf
[0] = CM3232_REG_ALS_CONF
;
246 res
= i2c_master_send(client
, databuf
, 0x201);
249 APS_ERR("i2c_master_send function err\n");
250 goto ENABLE_ALS_EXIT_ERR
;
253 APS_LOG("CM3232_REG_ALS_CONF dvalue value_low = %x, value_high = %x\n",databuf
[0],databuf
[1]);
255 databuf
[1] = 0x01;//databuf[0]|0x01;
256 databuf
[0] = CM3232_REG_ALS_CONF
;
257 client
->addr
&=I2C_MASK_FLAG
;
259 res
= i2c_master_send(client
, databuf
, 0x2);
262 APS_ERR("i2c_master_send function err\n");
263 goto ENABLE_ALS_EXIT_ERR
;
265 atomic_set(&obj
->als_deb_on
, 0);
271 /********************************************************************/
272 long cm3232_read_als(struct i2c_client
*client
, u16
*data
)
276 client
->addr
&=I2C_MASK_FLAG
;
277 client
->addr
|=I2C_WR_FLAG
;
278 client
->addr
|=I2C_RS_FLAG
;
281 databuf
[0] = CM3232_REG_ALS_DATA
;
282 res
= i2c_master_send(client
, databuf
, 0x201);
285 APS_ERR("i2c_master_send function err\n");
286 goto READ_ALS_EXIT_ERR
;
289 APS_LOG("CM3232_REG_ALS_DATA value value_low = %x, value_high = %x\n",databuf
[0],databuf
[1]);
291 *data
= ((databuf
[1]<<8)|databuf
[0]);
296 /********************************************************************/
297 static int cm3232_get_als_value(struct cm3232_priv
*obj
, u16 als
)
301 for(idx
= 0; idx
< obj
->als_level_num
; idx
++)
303 if((als
/ALS_K_VALUE
) < obj
->hw
->als_level
[idx
])
308 if(idx
>= obj
->als_value_num
)
310 APS_ERR("exceed range\n");
311 idx
= obj
->als_value_num
- 1;
314 if(1 == atomic_read(&obj
->als_deb_on
))
316 unsigned long endt
= atomic_read(&obj
->als_deb_end
);
317 if(time_after(jiffies
, endt
))
319 atomic_set(&obj
->als_deb_on
, 0);
322 if(1 == atomic_read(&obj
->als_deb_on
))
330 if (atomic_read(&obj
->trace
) & CMC_TRC_CVT_ALS
)
332 APS_DBG("ALS: %05d => %05d\n", als
, obj
->hw
->als_value
[idx
]);
335 return obj
->hw
->als_value
[idx
];
339 if(atomic_read(&obj
->trace
) & CMC_TRC_CVT_ALS
)
341 APS_DBG("ALS: %05d => %05d (-1)\n", als
, obj
->hw
->als_value
[idx
]);
349 /*-------------------------------attribute file for debugging----------------------------------*/
351 /******************************************************************************
353 *******************************************************************************/
354 static ssize_t
cm3232_show_config(struct device_driver
*ddri
, char *buf
)
360 APS_ERR("cm3232_obj is null!!\n");
364 res
= snprintf(buf
, PAGE_SIZE
, "(%d %d)\n",
365 atomic_read(&cm3232_obj
->i2c_retry
), atomic_read(&cm3232_obj
->als_debounce
));
368 /*----------------------------------------------------------------------------*/
369 static ssize_t
cm3232_store_config(struct device_driver
*ddri
, const char *buf
, size_t count
)
371 int retry
, als_deb
,mask
, thres
;
374 APS_ERR("cm3232_obj is null!!\n");
378 if(5 == sscanf(buf
, "%d %d %d %d", &retry
, &als_deb
, &mask
, &thres
))
380 atomic_set(&cm3232_obj
->i2c_retry
, retry
);
381 atomic_set(&cm3232_obj
->als_debounce
, als_deb
);
385 APS_ERR("invalid content: '%s', length = %zu\n", buf
, count
);
389 /*----------------------------------------------------------------------------*/
390 static ssize_t
cm3232_show_trace(struct device_driver
*ddri
, char *buf
)
395 APS_ERR("cm3232_obj is null!!\n");
399 res
= snprintf(buf
, PAGE_SIZE
, "0x%04X\n", atomic_read(&cm3232_obj
->trace
));
402 /*----------------------------------------------------------------------------*/
403 static ssize_t
cm3232_store_trace(struct device_driver
*ddri
, const char *buf
, size_t count
)
408 APS_ERR("cm3232_obj is null!!\n");
412 if(1 == sscanf(buf
, "0x%x", &trace
))
414 atomic_set(&cm3232_obj
->trace
, trace
);
418 APS_ERR("invalid content: '%s', length = %zu\n", buf
, count
);
422 /*----------------------------------------------------------------------------*/
423 static ssize_t
cm3232_show_als(struct device_driver
*ddri
, char *buf
)
429 APS_ERR("cm3232_obj is null!!\n");
432 if((res
= cm3232_read_als(cm3232_obj
->client
, &cm3232_obj
->als
)))
434 return snprintf(buf
, PAGE_SIZE
, "ERROR: %d\n", res
);
438 return snprintf(buf
, PAGE_SIZE
, "0x%04X\n", cm3232_obj
->als
);
441 /*----------------------------------------------------------------------------*/
442 static ssize_t
cm3232_show_reg(struct device_driver
*ddri
, char *buf
)
446 APS_ERR("cm3232_obj is null!!\n");
454 /*----------------------------------------------------------------------------*/
455 static ssize_t
cm3232_show_send(struct device_driver
*ddri
, char *buf
)
459 /*----------------------------------------------------------------------------*/
460 static ssize_t
cm3232_store_send(struct device_driver
*ddri
, const char *buf
, size_t count
)
467 APS_ERR("cm3232_obj is null!!\n");
470 else if(2 != sscanf(buf
, "%x %x", &addr
, &cmd
))
472 APS_ERR("invalid format: '%s'\n", buf
);
477 //****************************
480 /*----------------------------------------------------------------------------*/
481 static ssize_t
cm3232_show_recv(struct device_driver
*ddri
, char *buf
)
485 /*----------------------------------------------------------------------------*/
486 static ssize_t
cm3232_store_recv(struct device_driver
*ddri
, const char *buf
, size_t count
)
492 APS_ERR("cm3232_obj is null!!\n");
495 else if(1 != sscanf(buf
, "%x", &addr
))
497 APS_ERR("invalid format: '%s'\n", buf
);
501 //****************************
504 /*----------------------------------------------------------------------------*/
505 static ssize_t
cm3232_show_status(struct device_driver
*ddri
, char *buf
)
511 APS_ERR("cm3232_obj is null!!\n");
517 len
+= snprintf(buf
+len
, PAGE_SIZE
-len
, "CUST: %d, (%d %d)\n",
518 cm3232_obj
->hw
->i2c_num
, cm3232_obj
->hw
->power_id
, cm3232_obj
->hw
->power_vol
);
522 len
+= snprintf(buf
+len
, PAGE_SIZE
-len
, "CUST: NULL\n");
525 len
+= snprintf(buf
+len
, PAGE_SIZE
-len
, "REGS: %02X %02lX %02lX\n",
526 atomic_read(&cm3232_obj
->als_cmd_val
),cm3232_obj
->enable
, cm3232_obj
->pending_intr
);
528 len
+= snprintf(buf
+len
, PAGE_SIZE
-len
, "MISC: %d \n", atomic_read(&cm3232_obj
->als_suspend
));
532 /*----------------------------------------------------------------------------*/
533 /*----------------------------------------------------------------------------*/
534 #define IS_SPACE(CH) (((CH) == ' ') || ((CH) == '\n'))
535 /*----------------------------------------------------------------------------*/
536 static int read_int_from_buf(struct cm3232_priv
*obj
, const char* buf
, size_t count
, u32 data
[], int len
)
539 char *cur
= (char*)buf
, *end
= (char*)(buf
+count
);
543 while((cur
< end
) && IS_SPACE(*cur
))
548 if(1 != sscanf(cur
, "%d", &data
[idx
]))
554 while((cur
< end
) && !IS_SPACE(*cur
))
561 /*----------------------------------------------------------------------------*/
562 static ssize_t
cm3232_show_alslv(struct device_driver
*ddri
, char *buf
)
568 APS_ERR("cm3232_obj is null!!\n");
572 for(idx
= 0; idx
< cm3232_obj
->als_level_num
; idx
++)
574 len
+= snprintf(buf
+len
, PAGE_SIZE
-len
, "%d ", cm3232_obj
->hw
->als_level
[idx
]);
576 len
+= snprintf(buf
+len
, PAGE_SIZE
-len
, "\n");
579 /*----------------------------------------------------------------------------*/
580 static ssize_t
cm3232_store_alslv(struct device_driver
*ddri
, const char *buf
, size_t count
)
584 APS_ERR("cm3232_obj is null!!\n");
587 else if(!strcmp(buf
, "def"))
589 memcpy(cm3232_obj
->als_level
, cm3232_obj
->hw
->als_level
, sizeof(cm3232_obj
->als_level
));
591 else if(cm3232_obj
->als_level_num
!= read_int_from_buf(cm3232_obj
, buf
, count
,
592 cm3232_obj
->hw
->als_level
, cm3232_obj
->als_level_num
))
594 APS_ERR("invalid format: '%s'\n", buf
);
598 /*----------------------------------------------------------------------------*/
599 static ssize_t
cm3232_show_alsval(struct device_driver
*ddri
, char *buf
)
605 APS_ERR("cm3232_obj is null!!\n");
609 for(idx
= 0; idx
< cm3232_obj
->als_value_num
; idx
++)
611 len
+= snprintf(buf
+len
, PAGE_SIZE
-len
, "%d ", cm3232_obj
->hw
->als_value
[idx
]);
613 len
+= snprintf(buf
+len
, PAGE_SIZE
-len
, "\n");
616 /*----------------------------------------------------------------------------*/
617 static ssize_t
cm3232_store_alsval(struct device_driver
*ddri
, const char *buf
, size_t count
)
621 APS_ERR("cm3232_obj is null!!\n");
624 else if(!strcmp(buf
, "def"))
626 memcpy(cm3232_obj
->als_value
, cm3232_obj
->hw
->als_value
, sizeof(cm3232_obj
->als_value
));
628 else if(cm3232_obj
->als_value_num
!= read_int_from_buf(cm3232_obj
, buf
, count
,
629 cm3232_obj
->hw
->als_value
, cm3232_obj
->als_value_num
))
631 APS_ERR("invalid format: '%s'\n", buf
);
635 /*---------------------------------------------------------------------------------------*/
637 static DRIVER_ATTR(als
, S_IWUSR
| S_IRUGO
, cm3232_show_als
, NULL
);
638 static DRIVER_ATTR(config
, S_IWUSR
| S_IRUGO
, cm3232_show_config
, cm3232_store_config
);
639 static DRIVER_ATTR(alslv
, S_IWUSR
| S_IRUGO
, NULL
, NULL
);
640 static DRIVER_ATTR(alsval
, S_IWUSR
| S_IRUGO
, NULL
, NULL
);
641 static DRIVER_ATTR(trace
, S_IWUSR
| S_IRUGO
, cm3232_show_trace
, cm3232_store_trace
);
642 static DRIVER_ATTR(status
, S_IWUSR
| S_IRUGO
, NULL
, NULL
);
643 static DRIVER_ATTR(send
, S_IWUSR
| S_IRUGO
, NULL
, NULL
);
644 static DRIVER_ATTR(recv
, S_IWUSR
| S_IRUGO
, NULL
, NULL
);
645 static DRIVER_ATTR(reg
, S_IWUSR
| S_IRUGO
, cm3232_show_reg
, NULL
);
646 /*----------------------------------------------------------------------------*/
647 static struct driver_attribute
*cm3232_attr_list
[] = {
649 &driver_attr_trace
, /*trace log*/
659 /*----------------------------------------------------------------------------*/
660 static int cm3232_create_attr(struct device_driver
*driver
)
663 int num
= (int)(sizeof(cm3232_attr_list
)/sizeof(cm3232_attr_list
[0]));
669 for(idx
= 0; idx
< num
; idx
++)
671 if((err
= driver_create_file(driver
, cm3232_attr_list
[idx
])))
673 APS_ERR("driver_create_file (%s) = %d\n", cm3232_attr_list
[idx
]->attr
.name
, err
);
679 /*----------------------------------------------------------------------------*/
680 static int cm3232_delete_attr(struct device_driver
*driver
)
683 int num
= (int)(sizeof(cm3232_attr_list
)/sizeof(cm3232_attr_list
[0]));
688 for (idx
= 0; idx
< num
; idx
++)
690 driver_remove_file(driver
, cm3232_attr_list
[idx
]);
695 /*----------------------------------------------------------------------------*/
697 #if 0//modify for CM3232 polling mode.131012 xgt
698 /*----------------------------------interrupt functions--------------------------------*/
699 static int intr_flag
= 0;
700 /*----------------------------------------------------------------------------*/
701 static int cm3232_check_intr(struct i2c_client
*client
)
707 client
->addr
&=I2C_MASK_FLAG
;
708 client
->addr
|=I2C_WR_FLAG
;
709 client
->addr
|=I2C_RS_FLAG
;
711 databuf
[0] = CM3232_REG_PS_DATA
;
712 res
= i2c_master_send(client
, databuf
, 0x201);
715 APS_ERR("i2c_master_send function err res = %d\n",res
);
719 APS_LOG("CM3232_REG_PS_DATA value value_low = %x, value_reserve = %x\n",databuf
[0],databuf
[1]);
721 client
->addr
&=I2C_MASK_FLAG
;
722 client
->addr
|=I2C_WR_FLAG
;
723 client
->addr
|=I2C_RS_FLAG
;
725 databuf
[0] = CM3232_REG_INT_FLAG
;
726 res
= i2c_master_send(client
, databuf
, 0x201);
729 APS_ERR("i2c_master_send function err res = %d\n",res
);
733 APS_LOG("CM3232_REG_INT_FLAG value value_low = %x, value_high = %x\n",databuf
[0],databuf
[1]);
737 intr_flag
= 0;//for close
738 }else if(databuf
[1]&0x01)
740 intr_flag
= 1;//for away
743 APS_ERR("cm3232_check_intr fail databuf[1]&0x01: %d\n", res
);
749 APS_ERR("cm3232_check_intr dev: %d\n", res
);
752 /*----------------------------------------------------------------------------*/
753 static void cm3232_eint_work(struct work_struct
*work
)
755 struct cm3232_priv
*obj
= (struct cm3232_priv
*)container_of(work
, struct cm3232_priv
, eint_work
);
756 hwm_sensor_data sensor_data
;
758 //res = cm3232_check_intr(obj->client);
761 //res = cm3232_check_intr(obj->client);
765 sensor_data
.values
[0] = intr_flag
;
766 sensor_data
.value_divide
= 1;
767 sensor_data
.status
= SENSOR_STATUS_ACCURACY_MEDIUM
;
770 if((res
= hwmsen_get_interrupt_data(ID_PROXIMITY
, &sensor_data
)))
772 APS_ERR("call hwmsen_get_interrupt_data fail = %d\n", res
);
776 //mt65xx_eint_unmask(CUST_EINT_ALS_NUM);
779 //mt65xx_eint_unmask(CUST_EINT_ALS_NUM);
780 APS_ERR("cm3232_eint_work err: %d\n", res
);
782 /*----------------------------------------------------------------------------*/
783 static void cm3232_eint_func(void)
785 struct cm3232_priv
*obj
= g_cm3232_ptr
;
790 APS_ERR("debug cm3232_eint_func!");
791 schedule_work(&obj
->eint_work
);
794 int cm3232_setup_eint(struct i2c_client
*client
)
796 struct cm3232_priv
*obj
= i2c_get_clientdata(client
);
800 mt_set_gpio_dir(GPIO_ALS_EINT_PIN
, GPIO_DIR_IN
);
801 mt_set_gpio_mode(GPIO_ALS_EINT_PIN
, GPIO_ALS_EINT_PIN_M_EINT
);
802 mt_set_gpio_pull_enable(GPIO_ALS_EINT_PIN
, TRUE
);
803 mt_set_gpio_pull_select(GPIO_ALS_EINT_PIN
, GPIO_PULL_UP
);
806 mt65xx_eint_set_sens(CUST_EINT_ALS_NUM
, CUST_EINT_ALS_SENSITIVE
);
807 mt65xx_eint_set_polarity(CUST_EINT_ALS_NUM
, CUST_EINT_ALS_POLARITY
);
808 mt65xx_eint_set_hw_debounce(CUST_EINT_ALS_NUM
, CUST_EINT_ALS_DEBOUNCE_CN
);
809 mt65xx_eint_registration(CUST_EINT_ALS_NUM
, CUST_EINT_ALS_DEBOUNCE_EN
, CUST_EINT_ALS_POLARITY
, cm3232_eint_func
, 0);
811 mt65xx_eint_unmask(CUST_EINT_ALS_NUM
);
815 /*-------------------------------MISC device related------------------------------------------*/
818 #ifdef CUSTOM_KERNEL_SENSORHUB
819 static void cm3232_init_done_work(struct work_struct
*work
)
821 struct cm3232_priv
*obj
= cm3232_obj
;
822 CM3232_CUST_DATA
*p_cust_data
;
823 SCP_SENSOR_HUB_DATA data
;
824 int max_cust_data_size_per_packet
;
828 char *p
= (char *)obj
->hw
;
832 p_cust_data
= (CM3232_CUST_DATA
*)data
.set_cust_req
.custData
;
833 sizeOfCustData
= sizeof(*(obj
->hw
));
834 max_cust_data_size_per_packet
= sizeof(data
.set_cust_req
.custData
) - offsetof(CM3232_SET_CUST
, data
);
836 for (i
=0;sizeOfCustData
>0;i
++)
838 data
.set_cust_req
.sensorType
= ID_LIGHT
;
839 data
.set_cust_req
.action
= SENSOR_HUB_SET_CUST
;
840 p_cust_data
->setCust
.action
= CM3232_CUST_ACTION_SET_CUST
;
841 p_cust_data
->setCust
.part
= i
;
843 if (sizeOfCustData
> max_cust_data_size_per_packet
)
845 len
= max_cust_data_size_per_packet
;
849 len
= sizeOfCustData
;
852 memcpy(p_cust_data
->setCust
.data
, p
, len
);
853 sizeOfCustData
-= len
;
856 len
+= offsetof(SCP_SENSOR_HUB_SET_CUST_REQ
, custData
) + offsetof(CM3232_SET_CUST
, data
);
857 SCP_sensorHub_req_send(&data
, &len
, 1);
861 data
.set_cust_req
.sensorType
= ID_PROXIMITY
;
862 data
.set_cust_req
.action
= SENSOR_HUB_SET_CUST
;
863 p_cust_data
->setEintInfo
.action
= CM3232_CUST_ACTION_SET_EINT_INFO
;
864 p_cust_data
->setEintInfo
.gpio_mode
= GPIO_ALS_EINT_PIN_M_EINT
;
865 p_cust_data
->setEintInfo
.gpio_pin
= GPIO_ALS_EINT_PIN
;
866 p_cust_data
->setEintInfo
.eint_num
= CUST_EINT_ALS_NUM
;
867 p_cust_data
->setEintInfo
.eint_is_deb_en
= CUST_EINT_ALS_DEBOUNCE_EN
;
868 p_cust_data
->setEintInfo
.eint_type
= CUST_EINT_ALS_TYPE
;
869 len
= offsetof(SCP_SENSOR_HUB_SET_CUST_REQ
, custData
) + sizeof(p_cust_data
->setEintInfo
);
870 SCP_sensorHub_req_send(&data
, &len
, 1);
874 static int cm3232_irq_handler(void* data
, uint len
)
876 struct cm3232_priv
*obj
= cm3232_obj
;
877 SCP_SENSOR_HUB_DATA_P rsp
= (SCP_SENSOR_HUB_DATA_P
)data
;
884 APS_ERR("len = %d, type = %d, action = %d, errCode = %d\n", len
, rsp
->rsp
.sensorType
, rsp
->rsp
.action
, rsp
->rsp
.errCode
);
886 switch(rsp
->rsp
.action
)
888 case SENSOR_HUB_NOTIFY
:
889 switch(rsp
->notify_rsp
.event
)
892 schedule_work(&obj
->init_done_work
);
893 //schedule_delayed_work(&obj->init_done_work, HZ);
897 if (CM3232_NOTIFY_PROXIMITY_CHANGE
== rsp
->notify_rsp
.data
[0])
899 intr_flag
= rsp
->notify_rsp
.data
[1];
904 APS_ERR("Unknow notify");
909 APS_ERR("Error sensor hub notify");
914 APS_ERR("Error sensor hub action");
920 #endif //#ifdef CUSTOM_KERNEL_SENSORHUB
923 /************************************************************/
924 static int cm3232_open(struct inode
*inode
, struct file
*file
)
926 file
->private_data
= cm3232_i2c_client
;
928 if (!file
->private_data
)
930 APS_ERR("null pointer!!\n");
933 return nonseekable_open(inode
, file
);
935 /************************************************************/
936 static int cm3232_release(struct inode
*inode
, struct file
*file
)
938 file
->private_data
= NULL
;
941 /************************************************************/
942 static long cm3232_unlocked_ioctl(struct file
*file
, unsigned int cmd
, unsigned long arg
)
944 struct i2c_client
*client
= (struct i2c_client
*)file
->private_data
;
945 struct cm3232_priv
*obj
= i2c_get_clientdata(client
);
947 void __user
*ptr
= (void __user
*) arg
;
953 case ALSPS_SET_PS_MODE
:
954 case ALSPS_GET_PS_MODE
:
955 case ALSPS_GET_PS_DATA
:
956 case ALSPS_GET_PS_RAW_DATA
:
957 APS_LOG("ps not supported");
960 case ALSPS_SET_ALS_MODE
:
962 if(copy_from_user(&enable
, ptr
, sizeof(enable
)))
969 if((err
= cm3232_enable_als(obj
->client
, 1)))
971 APS_ERR("enable als fail: %ld\n", err
);
974 set_bit(CMC_BIT_ALS
, &obj
->enable
);
978 if((err
= cm3232_enable_als(obj
->client
, 0)))
980 APS_ERR("disable als fail: %ld\n", err
);
983 clear_bit(CMC_BIT_ALS
, &obj
->enable
);
987 case ALSPS_GET_ALS_MODE
:
988 enable
= test_bit(CMC_BIT_ALS
, &obj
->enable
) ? (1) : (0);
989 if(copy_to_user(ptr
, &enable
, sizeof(enable
)))
996 case ALSPS_GET_ALS_DATA
:
997 if((err
= cm3232_read_als(obj
->client
, &obj
->als
)))
1002 dat
= cm3232_get_als_value(obj
, obj
->als
);
1003 if(copy_to_user(ptr
, &dat
, sizeof(dat
)))
1010 case ALSPS_GET_ALS_RAW_DATA
:
1011 if((err
= cm3232_read_als(obj
->client
, &obj
->als
)))
1017 if(copy_to_user(ptr
, &dat
, sizeof(dat
)))
1023 /*------------------------------------------------------------------------------------------*/
1026 APS_ERR("%s not supported = 0x%04x", __FUNCTION__
, cmd
);
1034 /********************************************************************/
1035 /*------------------------------misc device related operation functions------------------------------------*/
1036 static struct file_operations cm3232_fops
= {
1037 .owner
= THIS_MODULE
,
1038 .open
= cm3232_open
,
1039 .release
= cm3232_release
,
1040 .unlocked_ioctl
= cm3232_unlocked_ioctl
,
1043 static struct miscdevice cm3232_device
= {
1044 .minor
= MISC_DYNAMIC_MINOR
,
1046 .fops
= &cm3232_fops
,
1049 /*--------------------------------------------------------------------------------------*/
1050 static void cm3232_early_suspend(struct early_suspend
*h
)
1052 struct cm3232_priv
*obj
= container_of(h
, struct cm3232_priv
, early_drv
);
1058 APS_ERR("null pointer!!\n");
1062 atomic_set(&obj
->als_suspend
, 1);
1063 if((err
= cm3232_enable_als(obj
->client
, 0)))
1065 APS_ERR("disable als fail: %d\n", err
);
1069 static void cm3232_late_resume(struct early_suspend
*h
)
1071 struct cm3232_priv
*obj
= container_of(h
, struct cm3232_priv
, early_drv
);
1073 hwm_sensor_data sensor_data
;
1074 memset(&sensor_data
, 0, sizeof(sensor_data
));
1078 APS_ERR("null pointer!!\n");
1082 atomic_set(&obj
->als_suspend
, 0);
1083 if(test_bit(CMC_BIT_ALS
, &obj
->enable
))
1085 if((err
= cm3232_enable_als(obj
->client
, 1)))
1087 APS_ERR("enable als fail: %d\n", err
);
1092 /*--------------------------------------------------------------------------------*/
1093 static int cm3232_init_client(struct i2c_client
*client
)
1095 struct cm3232_priv
*obj
= i2c_get_clientdata(client
);
1099 client
->addr
&=I2C_MASK_FLAG
;
1101 databuf
[0] = CM3232_REG_ALS_CONF
;
1102 if(1 == obj
->hw
->polling_mode_als
)
1106 res
= i2c_master_send(client
, databuf
, 0x2);
1109 APS_ERR("i2c_master_send function err\n");
1112 #if 0//modify for CM3232 polling mode.131012 xgt
1113 res
= cm3232_setup_eint(client
);
1116 APS_ERR("setup eint: %d\n", res
);
1121 #ifdef CUSTOM_KERNEL_SENSORHUB
1122 res
= SCP_sensorHub_rsp_registration(ID_LIGHT
, cm3232_irq_handler
);
1125 APS_ERR("i2c_master_send function err\n");
1129 return CM3232_SUCCESS
;
1132 APS_ERR("init dev: %d\n", res
);
1136 /*--------------------------------------------------------------------------------*/
1137 int cm3232_als_operate(void* self
, uint32_t command
, void* buff_in
, int size_in
,
1138 void* buff_out
, int size_out
, int* actualout
)
1142 hwm_sensor_data
* sensor_data
;
1143 struct cm3232_priv
*obj
= (struct cm3232_priv
*)self
;
1148 APS_ERR("cm3232 als delay command!\n");
1149 if((buff_in
== NULL
) || (size_in
< sizeof(int)))
1151 APS_ERR("Set delay parameter error!\n");
1157 APS_ERR("cm3232 als enable command!\n");
1158 if((buff_in
== NULL
) || (size_in
< sizeof(int)))
1160 APS_ERR("Enable sensor parameter error!\n");
1165 value
= *(int *)buff_in
;
1168 if((err
= cm3232_enable_als(obj
->client
, 1)))
1170 APS_ERR("enable als fail: %ld\n", err
);
1173 set_bit(CMC_BIT_ALS
, &obj
->enable
);
1177 if((err
= cm3232_enable_als(obj
->client
, 0)))
1179 APS_ERR("disable als fail: %ld\n", err
);
1182 clear_bit(CMC_BIT_ALS
, &obj
->enable
);
1188 case SENSOR_GET_DATA
:
1189 APS_ERR("cm3232 als get data command!\n");
1190 if((buff_out
== NULL
) || (size_out
< sizeof(hwm_sensor_data
)))
1192 APS_ERR("get sensor data parameter error!\n");
1197 sensor_data
= (hwm_sensor_data
*)buff_out
;
1199 if((err
= cm3232_read_als(obj
->client
, &obj
->als
)))
1205 sensor_data
->values
[0] = cm3232_get_als_value(obj
, obj
->als
);
1206 sensor_data
->value_divide
= 1;
1207 sensor_data
->status
= SENSOR_STATUS_ACCURACY_MEDIUM
;
1212 APS_ERR("light sensor operate function no this parameter %d!\n", command
);
1220 /*--------------------------------------------------------------------------------*/
1223 // if use this typ of enable , Gsensor should report inputEvent(x, y, z ,stats, div) to HAL
1224 static int cm3232_als_open_report_data(int open
)
1226 //should queuq work to report event if is_report_input_direct=true
1230 // if use this typ of enable , Gsensor only enabled but not report inputEvent to HAL
1232 static int cm3232_als_enable_nodata(int en
)
1235 #ifdef CUSTOM_KERNEL_SENSORHUB
1236 SCP_SENSOR_HUB_DATA req
;
1238 #endif //#ifdef CUSTOM_KERNEL_SENSORHUB
1240 APS_LOG("cm3232_obj als enable value = %d\n", en
);
1242 #ifdef CUSTOM_KERNEL_SENSORHUB
1243 req
.activate_req
.sensorType
= ID_LIGHT
;
1244 req
.activate_req
.action
= SENSOR_HUB_ACTIVATE
;
1245 req
.activate_req
.enable
= en
;
1246 len
= sizeof(req
.activate_req
);
1247 res
= SCP_sensorHub_req_send(&req
, &len
, 1);
1248 #else //#ifdef CUSTOM_KERNEL_SENSORHUB
1251 APS_ERR("cm3232_obj is null!!\n");
1254 res
=cm3232_enable_als(cm3232_obj
->client
, en
);
1255 #endif //#ifdef CUSTOM_KERNEL_SENSORHUB
1257 APS_ERR("als_enable_nodata is failed!!\n");
1263 static int cm3232_als_set_delay(u64 ns
)
1268 static int cm3232_als_get_data(int* value
, int* status
)
1271 #ifdef CUSTOM_KERNEL_SENSORHUB
1272 SCP_SENSOR_HUB_DATA req
;
1275 struct cm3232_priv
*obj
= NULL
;
1276 #endif //#ifdef CUSTOM_KERNEL_SENSORHUB
1278 #ifdef CUSTOM_KERNEL_SENSORHUB
1279 req
.get_data_req
.sensorType
= ID_LIGHT
;
1280 req
.get_data_req
.action
= SENSOR_HUB_GET_DATA
;
1281 len
= sizeof(req
.get_data_req
);
1282 err
= SCP_sensorHub_req_send(&req
, &len
, 1);
1285 APS_ERR("SCP_sensorHub_req_send fail!\n");
1289 *value
= req
.get_data_rsp
.int16_Data
[0];
1290 *status
= SENSOR_STATUS_ACCURACY_MEDIUM
;
1293 if(atomic_read(&cm3232_obj
->trace
) & CMC_TRC_ALS_DATA
)
1295 APS_LOG("value = %d\n", *value
);
1298 #else //#ifdef CUSTOM_KERNEL_SENSORHUB
1301 APS_ERR("cm3232_obj is null!!\n");
1305 if((err
= cm3232_read_als(obj
->client
, &obj
->als
)))
1311 *value
= cm3232_get_als_value(obj
, obj
->als
);
1312 *status
= SENSOR_STATUS_ACCURACY_MEDIUM
;
1314 #endif //#ifdef CUSTOM_KERNEL_SENSORHUB
1320 /*-----------------------------------i2c operations----------------------------------*/
1321 static int cm3232_i2c_probe(struct i2c_client
*client
, const struct i2c_device_id
*id
)
1323 struct cm3232_priv
*obj
;
1324 //struct hwmsen_object obj_als;
1326 struct als_control_path als_ctl
={0};
1327 struct als_data_path als_data
={0};
1328 //struct ps_control_path ps_ctl={0};
1329 //struct ps_data_path ps_data={0};
1332 APS_LOG("cm3232_i2c_probe\n");
1334 if(!(obj
= kzalloc(sizeof(*obj
), GFP_KERNEL
)))
1340 memset(obj
, 0, sizeof(*obj
));
1343 obj
->hw
= get_cust_alsps_hw();//get custom file data struct
1345 //INIT_WORK(&obj->eint_work, cm3232_eint_work);//modify for CM3232 polling mode.131012 xgt
1346 #ifdef CUSTOM_KERNEL_SENSORHUB
1347 INIT_WORK(&obj
->init_done_work
, cm3232_init_done_work
);
1348 #endif //#ifdef CUSTOM_KERNEL_SENSORHUB
1350 obj
->client
= client
;
1351 i2c_set_clientdata(client
, obj
);
1353 /*-----------------------------value need to be confirmed-----------------------------------------*/
1354 atomic_set(&obj
->als_debounce
, 200);
1355 atomic_set(&obj
->als_deb_on
, 0);
1356 atomic_set(&obj
->als_deb_end
, 0);
1357 atomic_set(&obj
->als_suspend
, 0);
1358 atomic_set(&obj
->als_cmd_val
, 0xDF);
1359 atomic_set(&obj
->als_thd_val_high
, obj
->hw
->als_threshold_high
);
1360 atomic_set(&obj
->als_thd_val_low
, obj
->hw
->als_threshold_low
);
1363 obj
->pending_intr
= 0;
1364 obj
->als_level_num
= sizeof(obj
->hw
->als_level
)/sizeof(obj
->hw
->als_level
[0]);
1365 obj
->als_value_num
= sizeof(obj
->hw
->als_value
)/sizeof(obj
->hw
->als_value
[0]);
1366 /*-----------------------------value need to be confirmed-----------------------------------------*/
1368 BUG_ON(sizeof(obj
->als_level
) != sizeof(obj
->hw
->als_level
));
1369 memcpy(obj
->als_level
, obj
->hw
->als_level
, sizeof(obj
->als_level
));
1370 BUG_ON(sizeof(obj
->als_value
) != sizeof(obj
->hw
->als_value
));
1371 memcpy(obj
->als_value
, obj
->hw
->als_value
, sizeof(obj
->als_value
));
1372 atomic_set(&obj
->i2c_retry
, 3);
1373 set_bit(CMC_BIT_ALS
, &obj
->enable
);
1375 cm3232_i2c_client
= client
;
1377 if((err
= cm3232_init_client(client
)))
1379 goto exit_init_failed
;
1381 APS_LOG("cm3232_init_client() OK!\n");
1383 if((err
= misc_register(&cm3232_device
)))
1385 APS_ERR("cm3232_device register failed\n");
1386 goto exit_misc_device_register_failed
;
1388 APS_LOG("cm3232_device misc_register OK!\n");
1390 /*------------------------cm3232 attribute file for debug--------------------------------------*/
1391 if((err
= cm3232_create_attr(&cm3232_init_info
.platform_diver_addr
->driver
)))
1393 APS_ERR("create attribute err = %d\n", err
);
1394 goto exit_create_attr_failed
;
1396 /*------------------------cm3232 attribute file for debug--------------------------------------*/
1397 als_ctl
.open_report_data
= cm3232_als_open_report_data
;
1398 als_ctl
.enable_nodata
= cm3232_als_enable_nodata
;
1399 als_ctl
.set_delay
= cm3232_als_set_delay
;
1400 als_ctl
.is_report_input_direct
= false;
1401 #ifdef CUSTOM_KERNEL_SENSORHUB
1402 als_ctl
.is_support_batch
= obj
->hw
->is_batch_supported_als
;
1404 als_ctl
.is_support_batch
= false;
1407 err
= als_register_control_path(&als_ctl
);
1410 APS_ERR("register fail = %d\n", err
);
1411 goto exit_sensor_obj_attach_fail
;
1414 als_data
.get_data
= cm3232_als_get_data
;
1415 als_data
.vender_div
= 100;
1416 err
= als_register_data_path(&als_data
);
1419 APS_ERR("tregister fail = %d\n", err
);
1420 goto exit_sensor_obj_attach_fail
;
1423 err
= batch_register_support_info(ID_LIGHT
,als_ctl
.is_support_batch
, 100, 0);
1426 APS_ERR("register light batch support err = %d\n", err
);
1427 goto exit_sensor_obj_attach_fail
;
1430 #if defined(CONFIG_HAS_EARLYSUSPEND)
1431 obj
->early_drv
.level
= EARLY_SUSPEND_LEVEL_STOP_DRAWING
- 2,
1432 obj
->early_drv
.suspend
= cm3232_early_suspend
,
1433 obj
->early_drv
.resume
= cm3232_late_resume
,
1434 register_early_suspend(&obj
->early_drv
);
1436 cm3232_init_flag
= 0;
1437 APS_LOG("cm3232_i2c_probe OK\n");
1438 APS_LOG("%s: OK\n", __func__
);
1439 //hw_module_info_add(&hw_info); //add tyd hardware info
1442 exit_create_attr_failed
:
1443 exit_sensor_obj_attach_fail
:
1444 exit_misc_device_register_failed
:
1445 misc_deregister(&cm3232_device
);
1449 cm3232_i2c_client
= NULL
;
1450 cm3232_init_flag
= -1;
1451 APS_ERR("%s: err = %d\n", __func__
, err
);
1455 static int cm3232_i2c_remove(struct i2c_client
*client
)
1458 /*------------------------cm3232 attribute file for debug--------------------------------------*/
1459 if((err
= cm3232_delete_attr(&cm3232_init_info
.platform_diver_addr
->driver
)))
1461 APS_ERR("cm3232_delete_attr fail: %d\n", err
);
1463 /*----------------------------------------------------------------------------------------*/
1465 if((err
= misc_deregister(&cm3232_device
)))
1467 APS_ERR("misc_deregister fail: %d\n", err
);
1470 cm3232_i2c_client
= NULL
;
1471 i2c_unregister_device(client
);
1472 kfree(i2c_get_clientdata(client
));
1477 static int cm3232_i2c_detect(struct i2c_client
*client
, struct i2c_board_info
*info
)
1479 strcpy(info
->type
, CM3232_DEV_NAME
);
1484 static int cm3232_i2c_suspend(struct i2c_client
*client
, pm_message_t msg
)
1490 static int cm3232_i2c_resume(struct i2c_client
*client
)
1496 /*----------------------------------------------------------------------------*/
1498 static int cm3232_probe(struct platform_device
*pdev
)
1500 struct alsps_hw
*hw
= get_cust_alsps_hw();
1503 cm3232_power(hw
, 1); //*****************
1505 if(i2c_add_driver(&cm3232_i2c_driver
))
1507 APS_ERR("add driver error\n");
1514 static int cm3232_local_init(void)
1516 struct alsps_hw
*hw
= get_cust_alsps_hw();
1517 //printk("fwq loccal init+++\n");
1519 cm3232_power(hw
, 1);
1520 if(i2c_add_driver(&cm3232_i2c_driver
))
1522 APS_ERR("add driver error\n");
1525 if(-1 == cm3232_init_flag
)
1529 //printk("fwq loccal init---\n");
1534 /*----------------------------------------------------------------------------*/
1535 static int cm3232_remove(void)
1537 struct alsps_hw
*hw
= get_cust_alsps_hw();
1540 cm3232_power(hw
, 0);//*****************
1542 i2c_del_driver(&cm3232_i2c_driver
);
1548 /*----------------------------------------------------------------------------*/
1550 static struct platform_driver cm3232_alsps_driver = {
1551 .probe = cm3232_probe,
1552 .remove = cm3232_remove,
1559 /*----------------------------------------------------------------------------*/
1560 static int __init
cm3232_init(void)
1562 struct alsps_hw
*hw
= get_cust_alsps_hw();
1563 APS_LOG("%s: i2c_number=%d\n", __func__
, hw
->i2c_num
);
1564 i2c_register_board_info(hw
->i2c_num
, &i2c_cm3232
, 1);
1565 alsps_driver_add(&cm3232_init_info
);
1566 APS_ERR("cm3232_init ok!\n");
1569 /*----------------------------------------------------------------------------*/
1570 static void __exit
cm3232_exit(void)
1573 //platform_driver_unregister(&cm3232_alsps_driver);
1575 /*----------------------------------------------------------------------------*/
1576 module_init(cm3232_init
);
1577 module_exit(cm3232_exit
);
1578 /*----------------------------------------------------------------------------*/
1579 MODULE_AUTHOR("yucong xiong");
1580 MODULE_DESCRIPTION("cm3232 driver");
1581 MODULE_LICENSE("GPL");