import PULS_20160108
[GitHub/mt8127/android_kernel_alcatel_ttab.git] / drivers / misc / mediatek / alsps / cm3232-new / cm3232.c
1 /*
2 * Author: yucong xiong <yucong.xion@mediatek.com>
3 *
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.
7 *
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.
12 *
13 */
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>
27
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>
32
33 #define POWER_NONE_MACRO MT65XX_POWER_NONE
34
35 #include <linux/hwmsensor.h>
36 #include <linux/hwmsen_dev.h>
37 #include <linux/sensors_io.h>
38 #include <asm/io.h>
39 #include <cust_eint.h>
40 #include <cust_alsps.h>
41 #include "cm3232.h"
42 //#include <linux/hw_module_info.h>
43 #include <linux/sched.h>
44 #include <alsps.h>
45 #include <linux/batch.h>
46
47 #ifdef CUSTOM_KERNEL_SENSORHUB
48 #include <SCP_sensorHub.h>
49 #endif
50
51 /******************************************************************************
52 * configuration
53 *******************************************************************************/
54 /*----------------------------------------------------------------------------*/
55
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 /******************************************************************************
64 * extern functions
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);
72
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);
79
80 static int cm3232_remove(void);
81 static int cm3232_local_init(void);
82
83 static int cm3232_init_flag =-1; // 0<==>OK -1 <==> fail
84 static struct alsps_init_info cm3232_init_info = {
85 .name = "cm3232",
86 .init = cm3232_local_init,
87 .uninit = cm3232_remove,
88 };
89
90
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 /*----------------------------------------------------------------------------*/
95
96 /*static hw_module_info hw_info = {
97 .type = HW_MODULE_TYPE_ALSPS,
98 .id = 0x10,
99 .priority = HW_MODULE_PRIORITY_ALSPS,
100 .name = "CM3232",
101 .vendor = "CAPELLA",
102 .more = ""
103 };*/
104
105 struct cm3232_priv {
106 struct alsps_hw *hw;
107 struct i2c_client *client;
108 struct work_struct eint_work;
109 #ifdef CUSTOM_KERNEL_SENSORHUB
110 struct work_struct init_done_work;
111 #endif
112
113 /*misc*/
114 u16 als_modulus;
115 atomic_t i2c_retry;
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*/
120 atomic_t trace;
121
122
123 /*data*/
124 u16 als;
125 u8 _align;
126 u16 als_level_num;
127 u16 als_value_num;
128 u32 als_level[C_CUST_ALS_LEVEL-1];
129 u32 als_value[C_CUST_ALS_LEVEL];
130
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*/
136
137 /*early suspend*/
138 #if defined(CONFIG_HAS_EARLYSUSPEND)
139 struct early_suspend early_drv;
140 #endif
141 };
142 /*----------------------------------------------------------------------------*/
143
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,
151 .driver = {
152 .name = CM3232_DEV_NAME,
153 },
154 };
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 /*----------------------------------------------------------------------------*/
161
162
163 /*----------------------------------------------------------------------------*/
164 typedef enum {
165 CMC_BIT_ALS = 1,
166 }CMC_BIT;
167 /*-----------------------------CMC for debugging-------------------------------*/
168 typedef enum {
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,
175 } CMC_TRC;
176 /*----------------------------------------------------------------------------*/
177 static void cm3232_power(struct alsps_hw *hw, unsigned int on)
178 {
179 static unsigned int power_on = 0;
180
181 APS_LOG("power %s\n", on ? "on" : "off");
182
183 if(hw->power_id != POWER_NONE_MACRO)
184 {
185 if(power_on == on)
186 {
187 APS_LOG("ignore power control: %d\n", on);
188 }
189 else if(on)
190 {
191 if(!hwPowerOn(hw->power_id, hw->power_vol, "CM3232"))
192 {
193 APS_ERR("power on fails!!\n");
194 }
195 }
196 else
197 {
198 if(!hwPowerDown(hw->power_id, "CM3232"))
199 {
200 APS_ERR("power off fail!!\n");
201 }
202 }
203 }
204 power_on = on;
205 }
206 /********************************************************************/
207 int cm3232_enable_als(struct i2c_client *client, int enable)
208 {
209 struct cm3232_priv *obj = i2c_get_clientdata(client);
210 int res;
211 u8 databuf[3];
212 client->addr &=I2C_MASK_FLAG;
213 client->addr |=I2C_WR_FLAG;
214 client->addr |=I2C_RS_FLAG;
215 if(enable == 1)
216 {
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);
221 if(res < 0)
222 {
223 APS_ERR("i2c_master_send function err\n");
224 goto ENABLE_ALS_EXIT_ERR;
225 }
226
227 APS_LOG("CM3232_REG_ALS_CONF evalue value_low = %x, value_high = %x\n",databuf[0],databuf[1]);
228 #endif
229 databuf[1] = 0x00;//databuf[0]&0xFE;
230 databuf[0] = CM3232_REG_ALS_CONF;
231 client->addr &=I2C_MASK_FLAG;
232
233 res = i2c_master_send(client, databuf, 0x2);
234 if(res < 0)
235 {
236 APS_ERR("i2c_master_send function err\n");
237 goto ENABLE_ALS_EXIT_ERR;
238 }
239 atomic_set(&obj->als_deb_on, 1);
240 atomic_set(&obj->als_deb_end, jiffies+atomic_read(&obj->als_debounce)/(1000/HZ));
241 }
242 else{
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);
247 if(res < 0)
248 {
249 APS_ERR("i2c_master_send function err\n");
250 goto ENABLE_ALS_EXIT_ERR;
251 }
252
253 APS_LOG("CM3232_REG_ALS_CONF dvalue value_low = %x, value_high = %x\n",databuf[0],databuf[1]);
254 #endif
255 databuf[1] = 0x01;//databuf[0]|0x01;
256 databuf[0] = CM3232_REG_ALS_CONF;
257 client->addr &=I2C_MASK_FLAG;
258
259 res = i2c_master_send(client, databuf, 0x2);
260 if(res < 0)
261 {
262 APS_ERR("i2c_master_send function err\n");
263 goto ENABLE_ALS_EXIT_ERR;
264 }
265 atomic_set(&obj->als_deb_on, 0);
266 }
267 return 0;
268 ENABLE_ALS_EXIT_ERR:
269 return res;
270 }
271 /********************************************************************/
272 long cm3232_read_als(struct i2c_client *client, u16 *data)
273 {
274 long res;
275 u8 databuf[2];
276 client->addr &=I2C_MASK_FLAG;
277 client->addr |=I2C_WR_FLAG;
278 client->addr |=I2C_RS_FLAG;
279 APS_FUN(f);
280
281 databuf[0] = CM3232_REG_ALS_DATA;
282 res = i2c_master_send(client, databuf, 0x201);
283 if(res < 0)
284 {
285 APS_ERR("i2c_master_send function err\n");
286 goto READ_ALS_EXIT_ERR;
287 }
288
289 APS_LOG("CM3232_REG_ALS_DATA value value_low = %x, value_high = %x\n",databuf[0],databuf[1]);
290
291 *data = ((databuf[1]<<8)|databuf[0]);
292 return 0;
293 READ_ALS_EXIT_ERR:
294 return res;
295 }
296 /********************************************************************/
297 static int cm3232_get_als_value(struct cm3232_priv *obj, u16 als)
298 {
299 int idx;
300 int invalid = 0;
301 for(idx = 0; idx < obj->als_level_num; idx++)
302 {
303 if((als/ALS_K_VALUE) < obj->hw->als_level[idx])
304 {
305 break;
306 }
307 }
308 if(idx >= obj->als_value_num)
309 {
310 APS_ERR("exceed range\n");
311 idx = obj->als_value_num - 1;
312 }
313
314 if(1 == atomic_read(&obj->als_deb_on))
315 {
316 unsigned long endt = atomic_read(&obj->als_deb_end);
317 if(time_after(jiffies, endt))
318 {
319 atomic_set(&obj->als_deb_on, 0);
320 }
321
322 if(1 == atomic_read(&obj->als_deb_on))
323 {
324 invalid = 1;
325 }
326 }
327
328 if(!invalid)
329 {
330 if (atomic_read(&obj->trace) & CMC_TRC_CVT_ALS)
331 {
332 APS_DBG("ALS: %05d => %05d\n", als, obj->hw->als_value[idx]);
333 }
334
335 return obj->hw->als_value[idx];
336 }
337 else
338 {
339 if(atomic_read(&obj->trace) & CMC_TRC_CVT_ALS)
340 {
341 APS_DBG("ALS: %05d => %05d (-1)\n", als, obj->hw->als_value[idx]);
342 }
343 return -1;
344 }
345
346 }
347
348
349 /*-------------------------------attribute file for debugging----------------------------------*/
350
351 /******************************************************************************
352 * Sysfs attributes
353 *******************************************************************************/
354 static ssize_t cm3232_show_config(struct device_driver *ddri, char *buf)
355 {
356 ssize_t res;
357
358 if(!cm3232_obj)
359 {
360 APS_ERR("cm3232_obj is null!!\n");
361 return 0;
362 }
363
364 res = snprintf(buf, PAGE_SIZE, "(%d %d)\n",
365 atomic_read(&cm3232_obj->i2c_retry), atomic_read(&cm3232_obj->als_debounce));
366 return res;
367 }
368 /*----------------------------------------------------------------------------*/
369 static ssize_t cm3232_store_config(struct device_driver *ddri, const char *buf, size_t count)
370 {
371 int retry, als_deb,mask, thres;
372 if(!cm3232_obj)
373 {
374 APS_ERR("cm3232_obj is null!!\n");
375 return 0;
376 }
377
378 if(5 == sscanf(buf, "%d %d %d %d", &retry, &als_deb, &mask, &thres))
379 {
380 atomic_set(&cm3232_obj->i2c_retry, retry);
381 atomic_set(&cm3232_obj->als_debounce, als_deb);
382 }
383 else
384 {
385 APS_ERR("invalid content: '%s', length = %zu\n", buf, count);
386 }
387 return count;
388 }
389 /*----------------------------------------------------------------------------*/
390 static ssize_t cm3232_show_trace(struct device_driver *ddri, char *buf)
391 {
392 ssize_t res;
393 if(!cm3232_obj)
394 {
395 APS_ERR("cm3232_obj is null!!\n");
396 return 0;
397 }
398
399 res = snprintf(buf, PAGE_SIZE, "0x%04X\n", atomic_read(&cm3232_obj->trace));
400 return res;
401 }
402 /*----------------------------------------------------------------------------*/
403 static ssize_t cm3232_store_trace(struct device_driver *ddri, const char *buf, size_t count)
404 {
405 int trace;
406 if(!cm3232_obj)
407 {
408 APS_ERR("cm3232_obj is null!!\n");
409 return 0;
410 }
411
412 if(1 == sscanf(buf, "0x%x", &trace))
413 {
414 atomic_set(&cm3232_obj->trace, trace);
415 }
416 else
417 {
418 APS_ERR("invalid content: '%s', length = %zu\n", buf, count);
419 }
420 return count;
421 }
422 /*----------------------------------------------------------------------------*/
423 static ssize_t cm3232_show_als(struct device_driver *ddri, char *buf)
424 {
425 int res;
426
427 if(!cm3232_obj)
428 {
429 APS_ERR("cm3232_obj is null!!\n");
430 return 0;
431 }
432 if((res = cm3232_read_als(cm3232_obj->client, &cm3232_obj->als)))
433 {
434 return snprintf(buf, PAGE_SIZE, "ERROR: %d\n", res);
435 }
436 else
437 {
438 return snprintf(buf, PAGE_SIZE, "0x%04X\n", cm3232_obj->als);
439 }
440 }
441 /*----------------------------------------------------------------------------*/
442 static ssize_t cm3232_show_reg(struct device_driver *ddri, char *buf)
443 {
444 if(!cm3232_obj)
445 {
446 APS_ERR("cm3232_obj is null!!\n");
447 return 0;
448 }
449
450
451 return 0;
452 }
453 #if 0
454 /*----------------------------------------------------------------------------*/
455 static ssize_t cm3232_show_send(struct device_driver *ddri, char *buf)
456 {
457 return 0;
458 }
459 /*----------------------------------------------------------------------------*/
460 static ssize_t cm3232_store_send(struct device_driver *ddri, const char *buf, size_t count)
461 {
462 int addr, cmd;
463 u8 dat;
464
465 if(!cm3232_obj)
466 {
467 APS_ERR("cm3232_obj is null!!\n");
468 return 0;
469 }
470 else if(2 != sscanf(buf, "%x %x", &addr, &cmd))
471 {
472 APS_ERR("invalid format: '%s'\n", buf);
473 return 0;
474 }
475
476 dat = (u8)cmd;
477 //****************************
478 return count;
479 }
480 /*----------------------------------------------------------------------------*/
481 static ssize_t cm3232_show_recv(struct device_driver *ddri, char *buf)
482 {
483 return 0;
484 }
485 /*----------------------------------------------------------------------------*/
486 static ssize_t cm3232_store_recv(struct device_driver *ddri, const char *buf, size_t count)
487 {
488 int addr;
489 //u8 dat;
490 if(!cm3232_obj)
491 {
492 APS_ERR("cm3232_obj is null!!\n");
493 return 0;
494 }
495 else if(1 != sscanf(buf, "%x", &addr))
496 {
497 APS_ERR("invalid format: '%s'\n", buf);
498 return 0;
499 }
500
501 //****************************
502 return count;
503 }
504 /*----------------------------------------------------------------------------*/
505 static ssize_t cm3232_show_status(struct device_driver *ddri, char *buf)
506 {
507 ssize_t len = 0;
508
509 if(!cm3232_obj)
510 {
511 APS_ERR("cm3232_obj is null!!\n");
512 return 0;
513 }
514
515 if(cm3232_obj->hw)
516 {
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);
519 }
520 else
521 {
522 len += snprintf(buf+len, PAGE_SIZE-len, "CUST: NULL\n");
523 }
524
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);
527
528 len += snprintf(buf+len, PAGE_SIZE-len, "MISC: %d \n", atomic_read(&cm3232_obj->als_suspend));
529
530 return len;
531 }
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)
537 {
538 int idx = 0;
539 char *cur = (char*)buf, *end = (char*)(buf+count);
540
541 while(idx < len)
542 {
543 while((cur < end) && IS_SPACE(*cur))
544 {
545 cur++;
546 }
547
548 if(1 != sscanf(cur, "%d", &data[idx]))
549 {
550 break;
551 }
552
553 idx++;
554 while((cur < end) && !IS_SPACE(*cur))
555 {
556 cur++;
557 }
558 }
559 return idx;
560 }
561 /*----------------------------------------------------------------------------*/
562 static ssize_t cm3232_show_alslv(struct device_driver *ddri, char *buf)
563 {
564 ssize_t len = 0;
565 int idx;
566 if(!cm3232_obj)
567 {
568 APS_ERR("cm3232_obj is null!!\n");
569 return 0;
570 }
571
572 for(idx = 0; idx < cm3232_obj->als_level_num; idx++)
573 {
574 len += snprintf(buf+len, PAGE_SIZE-len, "%d ", cm3232_obj->hw->als_level[idx]);
575 }
576 len += snprintf(buf+len, PAGE_SIZE-len, "\n");
577 return len;
578 }
579 /*----------------------------------------------------------------------------*/
580 static ssize_t cm3232_store_alslv(struct device_driver *ddri, const char *buf, size_t count)
581 {
582 if(!cm3232_obj)
583 {
584 APS_ERR("cm3232_obj is null!!\n");
585 return 0;
586 }
587 else if(!strcmp(buf, "def"))
588 {
589 memcpy(cm3232_obj->als_level, cm3232_obj->hw->als_level, sizeof(cm3232_obj->als_level));
590 }
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))
593 {
594 APS_ERR("invalid format: '%s'\n", buf);
595 }
596 return count;
597 }
598 /*----------------------------------------------------------------------------*/
599 static ssize_t cm3232_show_alsval(struct device_driver *ddri, char *buf)
600 {
601 ssize_t len = 0;
602 int idx;
603 if(!cm3232_obj)
604 {
605 APS_ERR("cm3232_obj is null!!\n");
606 return 0;
607 }
608
609 for(idx = 0; idx < cm3232_obj->als_value_num; idx++)
610 {
611 len += snprintf(buf+len, PAGE_SIZE-len, "%d ", cm3232_obj->hw->als_value[idx]);
612 }
613 len += snprintf(buf+len, PAGE_SIZE-len, "\n");
614 return len;
615 }
616 /*----------------------------------------------------------------------------*/
617 static ssize_t cm3232_store_alsval(struct device_driver *ddri, const char *buf, size_t count)
618 {
619 if(!cm3232_obj)
620 {
621 APS_ERR("cm3232_obj is null!!\n");
622 return 0;
623 }
624 else if(!strcmp(buf, "def"))
625 {
626 memcpy(cm3232_obj->als_value, cm3232_obj->hw->als_value, sizeof(cm3232_obj->als_value));
627 }
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))
630 {
631 APS_ERR("invalid format: '%s'\n", buf);
632 }
633 return count;
634 }
635 /*---------------------------------------------------------------------------------------*/
636 #endif
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[] = {
648 &driver_attr_als,
649 &driver_attr_trace, /*trace log*/
650 &driver_attr_config,
651 &driver_attr_alslv,
652 &driver_attr_alsval,
653 &driver_attr_status,
654 &driver_attr_send,
655 &driver_attr_recv,
656 &driver_attr_reg,
657 };
658
659 /*----------------------------------------------------------------------------*/
660 static int cm3232_create_attr(struct device_driver *driver)
661 {
662 int idx, err = 0;
663 int num = (int)(sizeof(cm3232_attr_list)/sizeof(cm3232_attr_list[0]));
664 if (driver == NULL)
665 {
666 return -EINVAL;
667 }
668
669 for(idx = 0; idx < num; idx++)
670 {
671 if((err = driver_create_file(driver, cm3232_attr_list[idx])))
672 {
673 APS_ERR("driver_create_file (%s) = %d\n", cm3232_attr_list[idx]->attr.name, err);
674 break;
675 }
676 }
677 return err;
678 }
679 /*----------------------------------------------------------------------------*/
680 static int cm3232_delete_attr(struct device_driver *driver)
681 {
682 int idx ,err = 0;
683 int num = (int)(sizeof(cm3232_attr_list)/sizeof(cm3232_attr_list[0]));
684
685 if (!driver)
686 return -EINVAL;
687
688 for (idx = 0; idx < num; idx++)
689 {
690 driver_remove_file(driver, cm3232_attr_list[idx]);
691 }
692
693 return err;
694 }
695 /*----------------------------------------------------------------------------*/
696
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)
702 {
703 int res;
704 u8 databuf[2];
705 u8 intr;
706
707 client->addr &=I2C_MASK_FLAG;
708 client->addr |=I2C_WR_FLAG;
709 client->addr |=I2C_RS_FLAG;
710
711 databuf[0] = CM3232_REG_PS_DATA;
712 res = i2c_master_send(client, databuf, 0x201);
713 if(res<0)
714 {
715 APS_ERR("i2c_master_send function err res = %d\n",res);
716 goto EXIT_ERR;
717 }
718
719 APS_LOG("CM3232_REG_PS_DATA value value_low = %x, value_reserve = %x\n",databuf[0],databuf[1]);
720
721 client->addr &=I2C_MASK_FLAG;
722 client->addr |=I2C_WR_FLAG;
723 client->addr |=I2C_RS_FLAG;
724
725 databuf[0] = CM3232_REG_INT_FLAG;
726 res = i2c_master_send(client, databuf, 0x201);
727 if(res<0)
728 {
729 APS_ERR("i2c_master_send function err res = %d\n",res);
730 goto EXIT_ERR;
731 }
732
733 APS_LOG("CM3232_REG_INT_FLAG value value_low = %x, value_high = %x\n",databuf[0],databuf[1]);
734
735 if(databuf[1]&0x02)
736 {
737 intr_flag = 0;//for close
738 }else if(databuf[1]&0x01)
739 {
740 intr_flag = 1;//for away
741 }else{
742 res = -1;
743 APS_ERR("cm3232_check_intr fail databuf[1]&0x01: %d\n", res);
744 goto EXIT_ERR;
745 }
746
747 return 0;
748 EXIT_ERR:
749 APS_ERR("cm3232_check_intr dev: %d\n", res);
750 return res;
751 }
752 /*----------------------------------------------------------------------------*/
753 static void cm3232_eint_work(struct work_struct *work)
754 {
755 struct cm3232_priv *obj = (struct cm3232_priv *)container_of(work, struct cm3232_priv, eint_work);
756 hwm_sensor_data sensor_data;
757 int res = 0;
758 //res = cm3232_check_intr(obj->client);
759
760 #if 1
761 //res = cm3232_check_intr(obj->client);
762 if(res != 0){
763 goto EXIT_INTR_ERR;
764 }else{
765 sensor_data.values[0] = intr_flag;
766 sensor_data.value_divide = 1;
767 sensor_data.status = SENSOR_STATUS_ACCURACY_MEDIUM;
768
769 }
770 if((res = hwmsen_get_interrupt_data(ID_PROXIMITY, &sensor_data)))
771 {
772 APS_ERR("call hwmsen_get_interrupt_data fail = %d\n", res);
773 goto EXIT_INTR_ERR;
774 }
775 #endif
776 //mt65xx_eint_unmask(CUST_EINT_ALS_NUM);
777 return;
778 EXIT_INTR_ERR:
779 //mt65xx_eint_unmask(CUST_EINT_ALS_NUM);
780 APS_ERR("cm3232_eint_work err: %d\n", res);
781 }
782 /*----------------------------------------------------------------------------*/
783 static void cm3232_eint_func(void)
784 {
785 struct cm3232_priv *obj = g_cm3232_ptr;
786 if(!obj)
787 {
788 return;
789 }
790 APS_ERR("debug cm3232_eint_func!");
791 schedule_work(&obj->eint_work);
792 }
793
794 int cm3232_setup_eint(struct i2c_client *client)
795 {
796 struct cm3232_priv *obj = i2c_get_clientdata(client);
797
798 g_cm3232_ptr = obj;
799
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);
804
805 #if 0
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);
810
811 mt65xx_eint_unmask(CUST_EINT_ALS_NUM);
812 #endif
813 return 0;
814 }
815 /*-------------------------------MISC device related------------------------------------------*/
816 #endif
817
818 #ifdef CUSTOM_KERNEL_SENSORHUB
819 static void cm3232_init_done_work(struct work_struct *work)
820 {
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;
825 int i;
826 uint sizeOfCustData;
827 uint len;
828 char *p = (char *)obj->hw;
829
830 APS_FUN();
831
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);
835
836 for (i=0;sizeOfCustData>0;i++)
837 {
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;
842
843 if (sizeOfCustData > max_cust_data_size_per_packet)
844 {
845 len = max_cust_data_size_per_packet;
846 }
847 else
848 {
849 len = sizeOfCustData;
850 }
851
852 memcpy(p_cust_data->setCust.data, p, len);
853 sizeOfCustData -= len;
854 p += len;
855
856 len += offsetof(SCP_SENSOR_HUB_SET_CUST_REQ, custData) + offsetof(CM3232_SET_CUST, data);
857 SCP_sensorHub_req_send(&data, &len, 1);
858 }
859
860 #if 0
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);
871 #endif
872 }
873
874 static int cm3232_irq_handler(void* data, uint len)
875 {
876 struct cm3232_priv *obj = cm3232_obj;
877 SCP_SENSOR_HUB_DATA_P rsp = (SCP_SENSOR_HUB_DATA_P)data;
878
879 if(!obj)
880 {
881 return -1;
882 }
883
884 APS_ERR("len = %d, type = %d, action = %d, errCode = %d\n", len, rsp->rsp.sensorType, rsp->rsp.action, rsp->rsp.errCode);
885
886 switch(rsp->rsp.action)
887 {
888 case SENSOR_HUB_NOTIFY:
889 switch(rsp->notify_rsp.event)
890 {
891 case SCP_INIT_DONE:
892 schedule_work(&obj->init_done_work);
893 //schedule_delayed_work(&obj->init_done_work, HZ);
894 break;
895 #if 0
896 case SCP_NOTIFY:
897 if (CM3232_NOTIFY_PROXIMITY_CHANGE == rsp->notify_rsp.data[0])
898 {
899 intr_flag = rsp->notify_rsp.data[1];
900 cm3232_eint_func();
901 }
902 else
903 {
904 APS_ERR("Unknow notify");
905 }
906 break;
907 #endif
908 default:
909 APS_ERR("Error sensor hub notify");
910 break;
911 }
912 break;
913 default:
914 APS_ERR("Error sensor hub action");
915 break;
916 }
917
918 return 0;
919 }
920 #endif //#ifdef CUSTOM_KERNEL_SENSORHUB
921
922
923 /************************************************************/
924 static int cm3232_open(struct inode *inode, struct file *file)
925 {
926 file->private_data = cm3232_i2c_client;
927
928 if (!file->private_data)
929 {
930 APS_ERR("null pointer!!\n");
931 return -EINVAL;
932 }
933 return nonseekable_open(inode, file);
934 }
935 /************************************************************/
936 static int cm3232_release(struct inode *inode, struct file *file)
937 {
938 file->private_data = NULL;
939 return 0;
940 }
941 /************************************************************/
942 static long cm3232_unlocked_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
943 {
944 struct i2c_client *client = (struct i2c_client*)file->private_data;
945 struct cm3232_priv *obj = i2c_get_clientdata(client);
946 long err = 0;
947 void __user *ptr = (void __user*) arg;
948 int dat;
949 uint32_t enable;
950
951 switch (cmd)
952 {
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");
958 goto err_out;
959
960 case ALSPS_SET_ALS_MODE:
961
962 if(copy_from_user(&enable, ptr, sizeof(enable)))
963 {
964 err = -EFAULT;
965 goto err_out;
966 }
967 if(enable)
968 {
969 if((err = cm3232_enable_als(obj->client, 1)))
970 {
971 APS_ERR("enable als fail: %ld\n", err);
972 goto err_out;
973 }
974 set_bit(CMC_BIT_ALS, &obj->enable);
975 }
976 else
977 {
978 if((err = cm3232_enable_als(obj->client, 0)))
979 {
980 APS_ERR("disable als fail: %ld\n", err);
981 goto err_out;
982 }
983 clear_bit(CMC_BIT_ALS, &obj->enable);
984 }
985 break;
986
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)))
990 {
991 err = -EFAULT;
992 goto err_out;
993 }
994 break;
995
996 case ALSPS_GET_ALS_DATA:
997 if((err = cm3232_read_als(obj->client, &obj->als)))
998 {
999 goto err_out;
1000 }
1001
1002 dat = cm3232_get_als_value(obj, obj->als);
1003 if(copy_to_user(ptr, &dat, sizeof(dat)))
1004 {
1005 err = -EFAULT;
1006 goto err_out;
1007 }
1008 break;
1009
1010 case ALSPS_GET_ALS_RAW_DATA:
1011 if((err = cm3232_read_als(obj->client, &obj->als)))
1012 {
1013 goto err_out;
1014 }
1015
1016 dat = obj->als;
1017 if(copy_to_user(ptr, &dat, sizeof(dat)))
1018 {
1019 err = -EFAULT;
1020 goto err_out;
1021 }
1022 break;
1023 /*------------------------------------------------------------------------------------------*/
1024
1025 default:
1026 APS_ERR("%s not supported = 0x%04x", __FUNCTION__, cmd);
1027 err = -ENOIOCTLCMD;
1028 break;
1029 }
1030
1031 err_out:
1032 return err;
1033 }
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,
1041 };
1042
1043 static struct miscdevice cm3232_device = {
1044 .minor = MISC_DYNAMIC_MINOR,
1045 .name = "als_ps",
1046 .fops = &cm3232_fops,
1047 };
1048
1049 /*--------------------------------------------------------------------------------------*/
1050 static void cm3232_early_suspend(struct early_suspend *h)
1051 {
1052 struct cm3232_priv *obj = container_of(h, struct cm3232_priv, early_drv);
1053 int err;
1054 APS_FUN();
1055
1056 if(!obj)
1057 {
1058 APS_ERR("null pointer!!\n");
1059 return;
1060 }
1061
1062 atomic_set(&obj->als_suspend, 1);
1063 if((err = cm3232_enable_als(obj->client, 0)))
1064 {
1065 APS_ERR("disable als fail: %d\n", err);
1066 }
1067 }
1068
1069 static void cm3232_late_resume(struct early_suspend *h)
1070 {
1071 struct cm3232_priv *obj = container_of(h, struct cm3232_priv, early_drv);
1072 int err;
1073 hwm_sensor_data sensor_data;
1074 memset(&sensor_data, 0, sizeof(sensor_data));
1075 APS_FUN();
1076 if(!obj)
1077 {
1078 APS_ERR("null pointer!!\n");
1079 return;
1080 }
1081
1082 atomic_set(&obj->als_suspend, 0);
1083 if(test_bit(CMC_BIT_ALS, &obj->enable))
1084 {
1085 if((err = cm3232_enable_als(obj->client, 1)))
1086 {
1087 APS_ERR("enable als fail: %d\n", err);
1088
1089 }
1090 }
1091 }
1092 /*--------------------------------------------------------------------------------*/
1093 static int cm3232_init_client(struct i2c_client *client)
1094 {
1095 struct cm3232_priv *obj = i2c_get_clientdata(client);
1096 u8 databuf[3];
1097 int res = 0;
1098
1099 client->addr &=I2C_MASK_FLAG;
1100
1101 databuf[0] = CM3232_REG_ALS_CONF;
1102 if(1 == obj->hw->polling_mode_als)
1103 databuf[1] = 0x01;
1104 else
1105 databuf[1] = 0x03;
1106 res = i2c_master_send(client, databuf, 0x2);
1107 if(res <= 0)
1108 {
1109 APS_ERR("i2c_master_send function err\n");
1110 goto EXIT_ERR;
1111 }
1112 #if 0//modify for CM3232 polling mode.131012 xgt
1113 res = cm3232_setup_eint(client);
1114 if(res!=0)
1115 {
1116 APS_ERR("setup eint: %d\n", res);
1117 return res;
1118 }
1119 #endif
1120
1121 #ifdef CUSTOM_KERNEL_SENSORHUB
1122 res = SCP_sensorHub_rsp_registration(ID_LIGHT, cm3232_irq_handler);
1123 if(res != 0)
1124 {
1125 APS_ERR("i2c_master_send function err\n");
1126 goto EXIT_ERR;
1127 }
1128 #endif
1129 return CM3232_SUCCESS;
1130
1131 EXIT_ERR:
1132 APS_ERR("init dev: %d\n", res);
1133 return res;
1134 }
1135 #if 0
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)
1139 {
1140 long err = 0;
1141 int value;
1142 hwm_sensor_data* sensor_data;
1143 struct cm3232_priv *obj = (struct cm3232_priv *)self;
1144 APS_FUN(f);
1145 switch (command)
1146 {
1147 case SENSOR_DELAY:
1148 APS_ERR("cm3232 als delay command!\n");
1149 if((buff_in == NULL) || (size_in < sizeof(int)))
1150 {
1151 APS_ERR("Set delay parameter error!\n");
1152 err = -EINVAL;
1153 }
1154 break;
1155
1156 case SENSOR_ENABLE:
1157 APS_ERR("cm3232 als enable command!\n");
1158 if((buff_in == NULL) || (size_in < sizeof(int)))
1159 {
1160 APS_ERR("Enable sensor parameter error!\n");
1161 err = -EINVAL;
1162 }
1163 else
1164 {
1165 value = *(int *)buff_in;
1166 if(value)
1167 {
1168 if((err = cm3232_enable_als(obj->client, 1)))
1169 {
1170 APS_ERR("enable als fail: %ld\n", err);
1171 return -1;
1172 }
1173 set_bit(CMC_BIT_ALS, &obj->enable);
1174 }
1175 else
1176 {
1177 if((err = cm3232_enable_als(obj->client, 0)))
1178 {
1179 APS_ERR("disable als fail: %ld\n", err);
1180 return -1;
1181 }
1182 clear_bit(CMC_BIT_ALS, &obj->enable);
1183 }
1184
1185 }
1186 break;
1187
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)))
1191 {
1192 APS_ERR("get sensor data parameter error!\n");
1193 err = -EINVAL;
1194 }
1195 else
1196 {
1197 sensor_data = (hwm_sensor_data *)buff_out;
1198
1199 if((err = cm3232_read_als(obj->client, &obj->als)))
1200 {
1201 err = -1;;
1202 }
1203 else
1204 {
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;
1208 }
1209 }
1210 break;
1211 default:
1212 APS_ERR("light sensor operate function no this parameter %d!\n", command);
1213 err = -1;
1214 break;
1215 }
1216
1217 return err;
1218
1219 }
1220 /*--------------------------------------------------------------------------------*/
1221 #endif
1222
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)
1225 {
1226 //should queuq work to report event if is_report_input_direct=true
1227 return 0;
1228 }
1229
1230 // if use this typ of enable , Gsensor only enabled but not report inputEvent to HAL
1231
1232 static int cm3232_als_enable_nodata(int en)
1233 {
1234 int res = 0;
1235 #ifdef CUSTOM_KERNEL_SENSORHUB
1236 SCP_SENSOR_HUB_DATA req;
1237 int len;
1238 #endif //#ifdef CUSTOM_KERNEL_SENSORHUB
1239
1240 APS_LOG("cm3232_obj als enable value = %d\n", en);
1241
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
1249 if(!cm3232_obj)
1250 {
1251 APS_ERR("cm3232_obj is null!!\n");
1252 return -1;
1253 }
1254 res=cm3232_enable_als(cm3232_obj->client, en);
1255 #endif //#ifdef CUSTOM_KERNEL_SENSORHUB
1256 if(res){
1257 APS_ERR("als_enable_nodata is failed!!\n");
1258 return -1;
1259 }
1260 return 0;
1261 }
1262
1263 static int cm3232_als_set_delay(u64 ns)
1264 {
1265 return 0;
1266 }
1267
1268 static int cm3232_als_get_data(int* value, int* status)
1269 {
1270 int err = 0;
1271 #ifdef CUSTOM_KERNEL_SENSORHUB
1272 SCP_SENSOR_HUB_DATA req;
1273 int len;
1274 #else
1275 struct cm3232_priv *obj = NULL;
1276 #endif //#ifdef CUSTOM_KERNEL_SENSORHUB
1277
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);
1283 if (err)
1284 {
1285 APS_ERR("SCP_sensorHub_req_send fail!\n");
1286 }
1287 else
1288 {
1289 *value = req.get_data_rsp.int16_Data[0];
1290 *status = SENSOR_STATUS_ACCURACY_MEDIUM;
1291 }
1292
1293 if(atomic_read(&cm3232_obj->trace) & CMC_TRC_ALS_DATA)
1294 {
1295 APS_LOG("value = %d\n", *value);
1296 //show data
1297 }
1298 #else //#ifdef CUSTOM_KERNEL_SENSORHUB
1299 if(!cm3232_obj)
1300 {
1301 APS_ERR("cm3232_obj is null!!\n");
1302 return -1;
1303 }
1304 obj = cm3232_obj;
1305 if((err = cm3232_read_als(obj->client, &obj->als)))
1306 {
1307 err = -1;
1308 }
1309 else
1310 {
1311 *value = cm3232_get_als_value(obj, obj->als);
1312 *status = SENSOR_STATUS_ACCURACY_MEDIUM;
1313 }
1314 #endif //#ifdef CUSTOM_KERNEL_SENSORHUB
1315
1316 return err;
1317 }
1318
1319
1320 /*-----------------------------------i2c operations----------------------------------*/
1321 static int cm3232_i2c_probe(struct i2c_client *client, const struct i2c_device_id *id)
1322 {
1323 struct cm3232_priv *obj;
1324 //struct hwmsen_object obj_als;
1325 int err = 0;
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};
1330
1331
1332 APS_LOG("cm3232_i2c_probe\n");
1333
1334 if(!(obj = kzalloc(sizeof(*obj), GFP_KERNEL)))
1335 {
1336 err = -ENOMEM;
1337 goto exit;
1338 }
1339
1340 memset(obj, 0, sizeof(*obj));
1341 cm3232_obj = obj;
1342
1343 obj->hw = get_cust_alsps_hw();//get custom file data struct
1344
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
1349
1350 obj->client = client;
1351 i2c_set_clientdata(client, obj);
1352
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);
1361
1362 obj->enable = 0;
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-----------------------------------------*/
1367
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);
1374
1375 cm3232_i2c_client = client;
1376
1377 if((err = cm3232_init_client(client)))
1378 {
1379 goto exit_init_failed;
1380 }
1381 APS_LOG("cm3232_init_client() OK!\n");
1382
1383 if((err = misc_register(&cm3232_device)))
1384 {
1385 APS_ERR("cm3232_device register failed\n");
1386 goto exit_misc_device_register_failed;
1387 }
1388 APS_LOG("cm3232_device misc_register OK!\n");
1389
1390 /*------------------------cm3232 attribute file for debug--------------------------------------*/
1391 if((err = cm3232_create_attr(&cm3232_init_info.platform_diver_addr->driver)))
1392 {
1393 APS_ERR("create attribute err = %d\n", err);
1394 goto exit_create_attr_failed;
1395 }
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;
1403 #else
1404 als_ctl.is_support_batch = false;
1405 #endif
1406
1407 err = als_register_control_path(&als_ctl);
1408 if(err)
1409 {
1410 APS_ERR("register fail = %d\n", err);
1411 goto exit_sensor_obj_attach_fail;
1412 }
1413
1414 als_data.get_data = cm3232_als_get_data;
1415 als_data.vender_div = 100;
1416 err = als_register_data_path(&als_data);
1417 if(err)
1418 {
1419 APS_ERR("tregister fail = %d\n", err);
1420 goto exit_sensor_obj_attach_fail;
1421 }
1422
1423 err = batch_register_support_info(ID_LIGHT,als_ctl.is_support_batch, 100, 0);
1424 if(err)
1425 {
1426 APS_ERR("register light batch support err = %d\n", err);
1427 goto exit_sensor_obj_attach_fail;
1428 }
1429
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);
1435 #endif
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
1440 return 0;
1441
1442 exit_create_attr_failed:
1443 exit_sensor_obj_attach_fail:
1444 exit_misc_device_register_failed:
1445 misc_deregister(&cm3232_device);
1446 exit_init_failed:
1447 kfree(obj);
1448 exit:
1449 cm3232_i2c_client = NULL;
1450 cm3232_init_flag = -1;
1451 APS_ERR("%s: err = %d\n", __func__, err);
1452 return err;
1453 }
1454
1455 static int cm3232_i2c_remove(struct i2c_client *client)
1456 {
1457 int err;
1458 /*------------------------cm3232 attribute file for debug--------------------------------------*/
1459 if((err = cm3232_delete_attr(&cm3232_init_info.platform_diver_addr->driver)))
1460 {
1461 APS_ERR("cm3232_delete_attr fail: %d\n", err);
1462 }
1463 /*----------------------------------------------------------------------------------------*/
1464
1465 if((err = misc_deregister(&cm3232_device)))
1466 {
1467 APS_ERR("misc_deregister fail: %d\n", err);
1468 }
1469
1470 cm3232_i2c_client = NULL;
1471 i2c_unregister_device(client);
1472 kfree(i2c_get_clientdata(client));
1473 return 0;
1474
1475 }
1476
1477 static int cm3232_i2c_detect(struct i2c_client *client, struct i2c_board_info *info)
1478 {
1479 strcpy(info->type, CM3232_DEV_NAME);
1480 return 0;
1481
1482 }
1483
1484 static int cm3232_i2c_suspend(struct i2c_client *client, pm_message_t msg)
1485 {
1486 APS_FUN();
1487 return 0;
1488 }
1489
1490 static int cm3232_i2c_resume(struct i2c_client *client)
1491 {
1492 APS_FUN();
1493 return 0;
1494 }
1495
1496 /*----------------------------------------------------------------------------*/
1497 #if 0
1498 static int cm3232_probe(struct platform_device *pdev)
1499 {
1500 struct alsps_hw *hw = get_cust_alsps_hw();
1501 APS_FUN();
1502
1503 cm3232_power(hw, 1); //*****************
1504
1505 if(i2c_add_driver(&cm3232_i2c_driver))
1506 {
1507 APS_ERR("add driver error\n");
1508 return -1;
1509 }
1510 return 0;
1511 }
1512 #endif
1513
1514 static int cm3232_local_init(void)
1515 {
1516 struct alsps_hw *hw = get_cust_alsps_hw();
1517 //printk("fwq loccal init+++\n");
1518
1519 cm3232_power(hw, 1);
1520 if(i2c_add_driver(&cm3232_i2c_driver))
1521 {
1522 APS_ERR("add driver error\n");
1523 return -1;
1524 }
1525 if(-1 == cm3232_init_flag)
1526 {
1527 return -1;
1528 }
1529 //printk("fwq loccal init---\n");
1530 return 0;
1531 }
1532
1533
1534 /*----------------------------------------------------------------------------*/
1535 static int cm3232_remove(void)
1536 {
1537 struct alsps_hw *hw = get_cust_alsps_hw();
1538 APS_FUN();
1539
1540 cm3232_power(hw, 0);//*****************
1541
1542 i2c_del_driver(&cm3232_i2c_driver);
1543 return 0;
1544 }
1545
1546
1547
1548 /*----------------------------------------------------------------------------*/
1549 /*
1550 static struct platform_driver cm3232_alsps_driver = {
1551 .probe = cm3232_probe,
1552 .remove = cm3232_remove,
1553 .driver = {
1554 .name = "als_ps",
1555 }
1556 };
1557 */
1558
1559 /*----------------------------------------------------------------------------*/
1560 static int __init cm3232_init(void)
1561 {
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");
1567 return 0;
1568 }
1569 /*----------------------------------------------------------------------------*/
1570 static void __exit cm3232_exit(void)
1571 {
1572 APS_FUN();
1573 //platform_driver_unregister(&cm3232_alsps_driver);
1574 }
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");
1582