import PULS_20160108
[GitHub/mt8127/android_kernel_alcatel_ttab.git] / drivers / misc / mediatek / heart_rate_sensor / heart_rate.c
1
2 #include "heart_rate.h"
3
4 struct hrm_context *hrm_context_obj = NULL;
5
6
7 static struct hrm_init_info* heart_rate_init_list[MAX_CHOOSE_HRM_NUM]= {0}; //modified
8 static void hrm_early_suspend(struct early_suspend *h);
9 static void hrm_late_resume(struct early_suspend *h);
10
11 static void hrm_work_func(struct work_struct *work)
12 {
13
14 struct hrm_context *cxt = NULL;
15 //int out_size;
16 //hwm_sensor_data sensor_data;
17 //u64 data64[6]; //for unify get_data parameter type
18 u32 data32[6]; //for hwm_sensor_data.values as int
19 //u64 data[4];
20 int status;
21 int64_t nt;
22 struct timespec time;
23 int err = 0;
24
25 cxt = hrm_context_obj;
26
27 if(NULL == cxt->hrm_data.get_data)
28 {
29 HRM_ERR("hrm driver not register data path\n");
30 }
31
32
33 time.tv_sec = time.tv_nsec = 0;
34 time = get_monotonic_coarse();
35 nt = time.tv_sec*1000000000LL+time.tv_nsec;
36
37 //add wake lock to make sure data can be read before system suspend
38 //initial data
39 //data[0] = cxt->drv_data.hrm_data.values[0];
40 //data[1] = cxt->drv_data.hrm_data.values[1];
41 //data[2] = cxt->drv_data.hrm_data.values[2];
42 //data[3] = cxt->drv_data.hrm_data.values[3];
43
44 err = cxt->hrm_data.get_data(data32, &status);
45 HRM_LOG("hrm get_data %d,%d,%d %d \n" ,
46 data32[0],data32[1],data32[2],data32[3]);
47
48 if(err)
49 {
50 HRM_ERR("get hrm data fails!!\n" );
51 goto hrm_loop;
52 }
53 else
54 {
55 if((data32[0] == cxt->drv_data.hrm_data.values[0])
56 && (data32[1] == cxt->drv_data.hrm_data.values[1])
57 && (data32[2] == cxt->drv_data.hrm_data.values[2])
58 && (data32[3] == cxt->drv_data.hrm_data.values[3]))
59 {
60 goto hrm_loop;
61 }
62 else
63 {
64 cxt->drv_data.hrm_data.values[0] = data32[0];
65 cxt->drv_data.hrm_data.values[1] = data32[1];
66 cxt->drv_data.hrm_data.values[2] = data32[2];
67 cxt->drv_data.hrm_data.values[3] = data32[3];
68 HRM_LOG("hrm values %d,%d,%d,%d\n" ,
69 cxt->drv_data.hrm_data.values[0],
70 cxt->drv_data.hrm_data.values[1],
71 cxt->drv_data.hrm_data.values[2],
72 cxt->drv_data.hrm_data.values[3]);
73 cxt->drv_data.hrm_data.status = status;
74 cxt->drv_data.hrm_data.time = nt;
75 }
76 }
77
78 if(true == cxt->is_first_data_after_enable)
79 {
80 cxt->is_first_data_after_enable = false;
81 //filter -1 value
82 if(HRM_INVALID_VALUE == cxt->drv_data.hrm_data.values[0]||
83 HRM_INVALID_VALUE == cxt->drv_data.hrm_data.values[1] ||
84 HRM_INVALID_VALUE == cxt->drv_data.hrm_data.values[2] ||
85 HRM_INVALID_VALUE == cxt->drv_data.hrm_data.values[3])
86 {
87 HRM_LOG(" read invalid data \n");
88 goto hrm_loop;
89
90 }
91 }
92 //report data to input device
93 //printk("new hrm work run....\n");
94 HRM_LOG("hrm data %d,%d,%d %d \n" ,cxt->drv_data.hrm_data.values[0],
95 cxt->drv_data.hrm_data.values[1],cxt->drv_data.hrm_data.values[2],cxt->drv_data.hrm_data.values[3]);
96
97 hrm_data_report(cxt->drv_data.hrm_data, cxt->drv_data.hrm_data.status);
98
99 hrm_loop:
100 if(true == cxt->is_polling_run)
101 {
102 {
103 mod_timer(&cxt->timer, jiffies + atomic_read(&cxt->delay)/(1000/HZ));
104 }
105 }
106 }
107
108 static void hrm_poll(unsigned long data)
109 {
110 struct hrm_context *obj = (struct hrm_context *)data;
111 if(obj != NULL)
112 {
113 schedule_work(&obj->report);
114 }
115 }
116
117 static struct hrm_context *hrm_context_alloc_object(void)
118 {
119
120 struct hrm_context *obj = kzalloc(sizeof(*obj), GFP_KERNEL);
121 HRM_LOG("hrm_context_alloc_object++++\n");
122 if(!obj)
123 {
124 HRM_ERR("Alloc hrm object error!\n");
125 return NULL;
126 }
127 atomic_set(&obj->delay, 200); /*5Hz*/// set work queue delay time 200ms
128 atomic_set(&obj->wake, 0);
129 INIT_WORK(&obj->report, hrm_work_func);
130 init_timer(&obj->timer);
131 obj->timer.expires = jiffies + atomic_read(&obj->delay)/(1000/HZ);
132 obj->timer.function = hrm_poll;
133 obj->timer.data = (unsigned long)obj;
134 obj->is_first_data_after_enable = false;
135 obj->is_polling_run = false;
136 obj->is_batch_enable = false;
137 mutex_init(&obj->hrm_op_mutex);
138 HRM_LOG("hrm_context_alloc_object----\n");
139 return obj;
140 }
141
142 static int hrm_real_enable(int enable)
143 {
144 int err =0;
145 struct hrm_context *cxt = NULL;
146 cxt = hrm_context_obj;
147 if(1==enable)
148 {
149
150 if(true==cxt->is_active_data || true ==cxt->is_active_nodata)
151 {
152 err = cxt->hrm_ctl.enable_nodata(1);
153 if(err)
154 {
155 err = cxt->hrm_ctl.enable_nodata(1);
156 if(err)
157 {
158 err = cxt->hrm_ctl.enable_nodata(1);
159 if(err)
160 HRM_ERR("hrm enable(%d) err 3 timers = %d\n", enable, err);
161 }
162 }
163 HRM_LOG("hrm real enable \n" );
164 }
165
166 }
167 if(0==enable)
168 {
169 if(false==cxt->is_active_data && false ==cxt->is_active_nodata)
170 {
171 err = cxt->hrm_ctl.enable_nodata(0);
172 if(err)
173 {
174 HRM_ERR("hrm enable(%d) err = %d\n", enable, err);
175 }
176 HRM_LOG("hrm real disable \n" );
177 }
178
179 }
180
181 return err;
182 }
183 static int hrm_enable_data(int enable)
184 {
185 struct hrm_context *cxt = NULL;
186 cxt = hrm_context_obj;
187 if(NULL == cxt->hrm_ctl.open_report_data)
188 {
189 HRM_ERR("no hrm control path\n");
190 return -1;
191 }
192
193 if(1 == enable)
194 {
195 HRM_LOG("hrm enable data\n");
196 cxt->is_active_data =true;
197 cxt->is_first_data_after_enable = true;
198 cxt->hrm_ctl.open_report_data(1);
199 if(false == cxt->is_polling_run && cxt->is_batch_enable == false)
200 {
201 if(false == cxt->hrm_ctl.is_report_input_direct)
202 {
203 mod_timer(&cxt->timer, jiffies + atomic_read(&cxt->delay)/(1000/HZ));
204 cxt->is_polling_run = true;
205 }
206 }
207 }
208 if(0 == enable)
209 {
210 HRM_LOG("hrm disable \n");
211
212 cxt->is_active_data =false;
213 cxt->hrm_ctl.open_report_data(0);
214 if(true == cxt->is_polling_run)
215 {
216 if(false == cxt->hrm_ctl.is_report_input_direct)
217 {
218 cxt->is_polling_run = false;
219 del_timer_sync(&cxt->timer);
220 cancel_work_sync(&cxt->report);
221 cxt->drv_data.hrm_data.values[0] = HRM_INVALID_VALUE;
222 cxt->drv_data.hrm_data.values[1] = HRM_INVALID_VALUE;
223 cxt->drv_data.hrm_data.values[2] = HRM_INVALID_VALUE;
224 cxt->drv_data.hrm_data.values[3] = HRM_INVALID_VALUE;
225 }
226 }
227
228 }
229 hrm_real_enable(enable);
230 return 0;
231 }
232
233
234
235 int hrm_enable_nodata(int enable)
236 {
237 struct hrm_context *cxt = NULL;
238 cxt = hrm_context_obj;
239 if(NULL == cxt->hrm_ctl.enable_nodata)
240 {
241 HRM_ERR("hrm_enable_nodata:hrm ctl path is NULL\n");
242 return -1;
243 }
244
245 if(1 == enable)
246 {
247 cxt->is_active_nodata = true;
248 }
249
250 if(0 == enable)
251 {
252 cxt->is_active_nodata = false;
253 }
254 hrm_real_enable(enable);
255 return 0;
256 }
257
258
259 static ssize_t hrm_show_enable_nodata(struct device* dev,
260 struct device_attribute *attr, char *buf)
261 {
262 int len = 0;
263 HRM_LOG(" not support now\n");
264 return len;
265 }
266
267 static ssize_t hrm_store_enable_nodata(struct device* dev, struct device_attribute *attr,
268 const char *buf, size_t count)
269 {
270 struct hrm_context *cxt = NULL;
271 //int err =0;
272 HRM_LOG("hrm_store_enable nodata buf=%s\n",buf);
273 mutex_lock(&hrm_context_obj->hrm_op_mutex);
274 cxt = hrm_context_obj;
275 if(NULL == cxt->hrm_ctl.enable_nodata)
276 {
277 HRM_LOG("hrm_ctl enable nodata NULL\n");
278 mutex_unlock(&hrm_context_obj->hrm_op_mutex);
279 return count;
280 }
281 if (!strncmp(buf, "1", 1))
282 {
283 hrm_enable_nodata(1);
284 }
285 else if (!strncmp(buf, "0", 1))
286 {
287 hrm_enable_nodata(0);
288 }
289 else
290 {
291 HRM_ERR(" hrm_store enable nodata cmd error !!\n");
292 }
293 mutex_unlock(&hrm_context_obj->hrm_op_mutex);
294 return count;
295 }
296
297 static ssize_t hrm_store_active(struct device* dev, struct device_attribute *attr,
298 const char *buf, size_t count)
299 {
300 struct hrm_context *cxt = NULL;
301 HRM_LOG("hrm_store_active buf=%s\n",buf);
302 mutex_lock(&hrm_context_obj->hrm_op_mutex);
303 cxt = hrm_context_obj;
304 if(NULL == cxt->hrm_ctl.open_report_data)
305 {
306 HRM_LOG("hrm_ctl enable NULL\n");
307 mutex_unlock(&hrm_context_obj->hrm_op_mutex);
308 return count;
309 }
310 if (!strncmp(buf, "1", 1))
311 {
312 hrm_enable_data(1);
313
314 }
315 else if (!strncmp(buf, "0", 1))
316 {
317 hrm_enable_data(0);
318 }
319 else
320 {
321 HRM_ERR(" hrm_store_active error !!\n");
322 }
323 mutex_unlock(&hrm_context_obj->hrm_op_mutex);
324 HRM_LOG(" hrm_store_active done\n");
325 return count;
326 }
327 /*----------------------------------------------------------------------------*/
328 static ssize_t hrm_show_active(struct device* dev,
329 struct device_attribute *attr, char *buf)
330 {
331 struct hrm_context *cxt = NULL;
332 int div = 0;
333 cxt = hrm_context_obj;
334 //int len = 0;
335 HRM_LOG("hrm show active not support now\n");
336 //div=cxt->hrm_data.vender_div;
337 HRM_LOG("hrm vender_div value: %d\n", div);
338 return snprintf(buf, PAGE_SIZE, "%d\n", div);
339
340 //return len;
341 }
342
343 static ssize_t hrm_store_delay(struct device* dev, struct device_attribute *attr,
344 const char *buf, size_t count)
345 {
346 // struct hrm_context *devobj = (struct hrm_context*)dev_get_drvdata(dev);
347 int delay;
348 int mdelay=0;
349 struct hrm_context *cxt = NULL;
350 //int err =0;
351 mutex_lock(&hrm_context_obj->hrm_op_mutex);
352 cxt = hrm_context_obj;
353 if(NULL == cxt->hrm_ctl.set_delay)
354 {
355 HRM_LOG("hrm_ctl set_delay NULL\n");
356 mutex_unlock(&hrm_context_obj->hrm_op_mutex);
357 return count;
358 }
359
360 if (1 != sscanf(buf, "%d", &delay)) {
361 HRM_ERR("invalid format!!\n");
362 mutex_unlock(&hrm_context_obj->hrm_op_mutex);
363 return count;
364 }
365
366 if(false == cxt->hrm_ctl.is_report_input_direct)
367 {
368 mdelay = (int)delay/1000/1000;
369 atomic_set(&hrm_context_obj->delay, mdelay);
370 }
371 cxt->hrm_ctl.set_delay(delay);
372 HRM_LOG(" hrm_delay %d ns\n",delay);
373 mutex_unlock(&hrm_context_obj->hrm_op_mutex);
374 return count;
375 }
376
377 static ssize_t hrm_show_delay(struct device* dev,
378 struct device_attribute *attr, char *buf)
379 {
380 int len = 0;
381 HRM_LOG(" not support now\n");
382 return len;
383 }
384
385 static ssize_t hrm_store_batch(struct device* dev, struct device_attribute *attr,
386 const char *buf, size_t count)
387 {
388 struct hrm_context *cxt = NULL;
389 //int err =0;
390 HRM_LOG("hrm_store_batch buf=%s\n",buf);
391 mutex_lock(&hrm_context_obj->hrm_op_mutex);
392 cxt = hrm_context_obj;
393 if(cxt->hrm_ctl.is_support_batch){
394
395 if (!strncmp(buf, "1", 1))
396 {
397 cxt->is_batch_enable = true;
398 }
399 else if (!strncmp(buf, "0", 1))
400 {
401 cxt->is_batch_enable = false;
402 }
403 else
404 {
405 HRM_ERR(" hrm_store_batch error !!\n");
406 }
407 }else{
408 HRM_LOG(" hrm_store_batch not support\n");
409 }
410 mutex_unlock(&hrm_context_obj->hrm_op_mutex);
411 HRM_LOG(" hrm_store_batch done: %d\n", cxt->is_batch_enable);
412 return count;
413
414 }
415
416 static ssize_t hrm_show_batch(struct device* dev,
417 struct device_attribute *attr, char *buf)
418 {
419 return snprintf(buf, PAGE_SIZE, "%d\n", 0);
420 }
421
422 static ssize_t hrm_store_flush(struct device* dev, struct device_attribute *attr,
423 const char *buf, size_t count)
424 {
425 //mutex_lock(&hrm_context_obj->hrm_op_mutex);
426 //struct hrm_context *devobj = (struct hrm_context*)dev_get_drvdata(dev);
427 //do read FIFO data function and report data immediately
428 //mutex_unlock(&hrm_context_obj->hrm_op_mutex);
429 return count;
430 }
431
432 static ssize_t hrm_show_flush(struct device* dev,
433 struct device_attribute *attr, char *buf)
434 {
435 return snprintf(buf, PAGE_SIZE, "%d\n", 0);
436 }
437
438 static ssize_t hrm_show_devnum(struct device* dev,
439 struct device_attribute *attr, char *buf)
440 {
441 const char *devname = NULL;
442 devname = dev_name(&hrm_context_obj->idev->dev);
443 return snprintf(buf, PAGE_SIZE, "%s\n", devname+5);
444 }
445 static int heart_rate_remove(struct platform_device *pdev)
446 {
447 HRM_LOG("heart_rate_remove\n");
448 return 0;
449 }
450
451 static int heart_rate_probe(struct platform_device *pdev)
452 {
453 HRM_LOG("heart_rate_probe\n");
454 return 0;
455 }
456
457 #ifdef CONFIG_OF
458 static const struct of_device_id heart_rate_of_match[] = {
459 { .compatible = "mediatek,heart_rate", },
460 {},
461 };
462 #endif
463
464 static struct platform_driver heart_rate_driver = {
465 .probe = heart_rate_probe,
466 .remove = heart_rate_remove,
467 .driver =
468 {
469 .name = "heart_rate",
470 #ifdef CONFIG_OF
471 .of_match_table = heart_rate_of_match,
472 #endif
473 }
474 };
475
476 static int hrm_real_driver_init(void)
477 {
478 int i =0;
479 int err=0;
480 HRM_LOG(" hrm_real_driver_init +\n");
481 for(i = 0; i < MAX_CHOOSE_HRM_NUM; i++)
482 {
483 HRM_LOG(" i=%d\n",i);
484 if(0 != heart_rate_init_list[i])
485 {
486 HRM_LOG(" hrm try to init driver %s\n", heart_rate_init_list[i]->name);
487 err = heart_rate_init_list[i]->init();
488 if(0 == err)
489 {
490 HRM_LOG(" hrm real driver %s probe ok\n", heart_rate_init_list[i]->name);
491 break;
492 }
493 }
494 }
495
496 if(i == MAX_CHOOSE_HRM_NUM)
497 {
498 HRM_LOG(" hrm_real_driver_init fail\n");
499 err=-1;
500 }
501 return err;
502 }
503
504 int hrm_driver_add(struct hrm_init_info* obj)
505 {
506 int err=0;
507 int i =0;
508
509 HRM_FUN(f);
510
511 for(i =0; i < MAX_CHOOSE_HRM_NUM; i++ )
512 {
513 if(i == 0){
514 HRM_LOG("register hrm driver for the first time\n");
515 if(platform_driver_register(&heart_rate_driver))
516 {
517 HRM_ERR("failed to register hrm driver already exist\n");
518 }
519 }
520
521 if(NULL == heart_rate_init_list[i])
522 {
523 obj->platform_diver_addr = &heart_rate_driver;
524 heart_rate_init_list[i] = obj;
525 break;
526 }
527 }
528 if(NULL==heart_rate_init_list[i])
529 {
530 HRM_ERR("hrm driver add err \n");
531 err=-1;
532 }
533
534 return err;
535 }
536 EXPORT_SYMBOL_GPL(hrm_driver_add);
537
538 static int hrm_misc_init(struct hrm_context *cxt)
539 {
540
541 int err=0;
542 cxt->mdev.minor = MISC_DYNAMIC_MINOR;
543 cxt->mdev.name = HRM_MISC_DEV_NAME;
544 if((err = misc_register(&cxt->mdev)))
545 {
546 HRM_ERR("unable to register hrm misc device!!\n");
547 }
548 return err;
549 }
550
551 static void hrm_input_destroy(struct hrm_context *cxt)
552 {
553 struct input_dev *dev = cxt->idev;
554
555 input_unregister_device(dev);
556 input_free_device(dev);
557 }
558
559 static int hrm_input_init(struct hrm_context *cxt)
560 {
561 struct input_dev *dev;
562 int err = 0;
563
564 dev = input_allocate_device();
565 if (NULL == dev)
566 return -ENOMEM;
567
568 dev->name = HRM_INPUTDEV_NAME;
569
570 input_set_capability(dev, EV_ABS, EVENT_TYPE_HRM_BPM);
571 input_set_capability(dev, EV_ABS, EVENT_TYPE_HRM_STATUS);
572
573 input_set_abs_params(dev, EVENT_TYPE_HRM_BPM, HRM_VALUE_MIN, HRM_VALUE_MAX, 0, 0);
574 input_set_abs_params(dev, EVENT_TYPE_HRM_STATUS, HRM_VALUE_MIN, HRM_VALUE_MAX, 0, 0);
575 input_set_drvdata(dev, cxt);
576
577 err = input_register_device(dev);
578 if (err < 0) {
579 input_free_device(dev);
580 return err;
581 }
582 cxt->idev= dev;
583
584 return 0;
585 }
586
587 DEVICE_ATTR(hrmenablenodata, S_IWUSR | S_IRUGO, hrm_show_enable_nodata, hrm_store_enable_nodata);
588 DEVICE_ATTR(hrmactive, S_IWUSR | S_IRUGO, hrm_show_active, hrm_store_active);
589 DEVICE_ATTR(hrmdelay, S_IWUSR | S_IRUGO, hrm_show_delay, hrm_store_delay);
590 DEVICE_ATTR(hrmbatch, S_IWUSR | S_IRUGO, hrm_show_batch, hrm_store_batch);
591 DEVICE_ATTR(hrmflush, S_IWUSR | S_IRUGO, hrm_show_flush, hrm_store_flush);
592 DEVICE_ATTR(hrmdevnum, S_IWUSR | S_IRUGO, hrm_show_devnum, NULL);
593
594 static struct attribute *hrm_attributes[] = {
595 &dev_attr_hrmenablenodata.attr,
596 &dev_attr_hrmactive.attr,
597 &dev_attr_hrmdelay.attr,
598 &dev_attr_hrmbatch.attr,
599 &dev_attr_hrmflush.attr,
600 &dev_attr_hrmdevnum.attr,
601 NULL
602 };
603
604 static struct attribute_group hrm_attribute_group = {
605 .attrs = hrm_attributes
606 };
607
608 int hrm_register_data_path(struct hrm_data_path *data)
609 {
610 struct hrm_context *cxt = NULL;
611 //int err =0;
612 cxt = hrm_context_obj;
613 cxt->hrm_data.get_data = data->get_data;
614 //cxt->hrm_data.vender_div = data->vender_div;
615 //cxt->hrm_data.get_raw_data = data->get_raw_data;
616 //HRM_LOG("hrm register data path vender_div: %d\n", cxt->hrm_data.vender_div);
617 if(NULL == cxt->hrm_data.get_data)
618 {
619 HRM_LOG("hrm register data path fail \n");
620 return -1;
621 }
622 return 0;
623 }
624
625 int hrm_register_control_path(struct hrm_control_path *ctl)
626 {
627 struct hrm_context *cxt = NULL;
628 int err =0;
629 cxt = hrm_context_obj;
630 cxt->hrm_ctl.set_delay = ctl->set_delay;
631 cxt->hrm_ctl.open_report_data= ctl->open_report_data;
632 cxt->hrm_ctl.enable_nodata = ctl->enable_nodata;
633 cxt->hrm_ctl.is_support_batch = ctl->is_support_batch;
634
635 if(NULL==cxt->hrm_ctl.set_delay || NULL==cxt->hrm_ctl.open_report_data
636 || NULL==cxt->hrm_ctl.enable_nodata)
637 {
638 HRM_LOG("hrm register control path fail \n");
639 return -1;
640 }
641
642 //add misc dev for sensor hal control cmd
643 err = hrm_misc_init(hrm_context_obj);
644 if(err)
645 {
646 HRM_ERR("unable to register hrm misc device!!\n");
647 return -2;
648 }
649 err = sysfs_create_group(&hrm_context_obj->mdev.this_device->kobj,
650 &hrm_attribute_group);
651 if (err < 0)
652 {
653 HRM_ERR("unable to create hrm attribute file\n");
654 return -3;
655 }
656
657 kobject_uevent(&hrm_context_obj->mdev.this_device->kobj, KOBJ_ADD);
658
659 return 0;
660 }
661
662 int hrm_data_report(hwm_sensor_data data,int status)
663 {
664 HRM_LOG("+hrm_data_report! %d, %d, %d, %d\n",data.values[0], data.values[1], data.values[2], data.values[3]);
665 struct hrm_context *cxt = NULL;
666 int err =0;
667 cxt = hrm_context_obj;
668 input_report_abs(cxt->idev, EVENT_TYPE_HRM_BPM, data.values[0]);
669 input_report_abs(cxt->idev, EVENT_TYPE_HRM_STATUS, data.values[1]);
670 input_sync(cxt->idev);
671 return err;
672 }
673
674 static int hrm_probe(struct platform_device *pdev)
675 {
676
677 int err;
678 HRM_LOG("+++++++++++++hrm_probe!!\n");
679
680 hrm_context_obj = hrm_context_alloc_object();
681 if (!hrm_context_obj)
682 {
683 err = -ENOMEM;
684 HRM_ERR("unable to allocate devobj!\n");
685 goto exit_alloc_data_failed;
686 }
687
688 //init real hrmeleration driver
689 err = hrm_real_driver_init();
690 if(err)
691 {
692 HRM_ERR("hrm real driver init fail\n");
693 goto real_driver_init_fail;
694 }
695
696 //err = hrm_factory_device_init();
697 //if(err)
698 //{
699 // HRM_ERR("hrm_factory_device_init fail\n");
700 //}
701
702 //init input dev
703 err = hrm_input_init(hrm_context_obj);
704 if(err)
705 {
706 HRM_ERR("unable to register hrm input device!\n");
707 goto exit_alloc_input_dev_failed;
708 }
709
710 #if defined(CONFIG_HAS_EARLYSUSPEND) && defined(CONFIG_EARLYSUSPEND)
711 atomic_set(&(hrm_context_obj->early_suspend), 0);
712 hrm_context_obj->early_drv.level = EARLY_SUSPEND_LEVEL_STOP_DRAWING - 1,
713 hrm_context_obj->early_drv.suspend = hrm_early_suspend,
714 hrm_context_obj->early_drv.resume = hrm_late_resume,
715 register_early_suspend(&hrm_context_obj->early_drv);
716 #endif //#if defined(CONFIG_HAS_EARLYSUSPEND) && defined(CONFIG_EARLYSUSPEND)
717
718 HRM_LOG("----hrm_probe OK !!\n");
719 return 0;
720
721 //exit_hwmsen_create_attr_failed:
722 //exit_misc_register_failed:
723
724 //exit_err_sysfs:
725
726 if (err)
727 {
728 HRM_ERR("sysfs node creation error \n");
729 hrm_input_destroy(hrm_context_obj);
730 }
731
732 real_driver_init_fail:
733 exit_alloc_input_dev_failed:
734 kfree(hrm_context_obj);
735
736 exit_alloc_data_failed:
737
738
739 HRM_LOG("----hrm_probe fail !!!\n");
740 return err;
741 }
742
743
744
745 static int hrm_remove(struct platform_device *pdev)
746 {
747 int err=0;
748 HRM_FUN(f);
749 input_unregister_device(hrm_context_obj->idev);
750 sysfs_remove_group(&hrm_context_obj->idev->dev.kobj,
751 &hrm_attribute_group);
752
753 if((err = misc_deregister(&hrm_context_obj->mdev)))
754 {
755 HRM_ERR("misc_deregister fail: %d\n", err);
756 }
757 kfree(hrm_context_obj);
758
759 return 0;
760 }
761
762 static void hrm_early_suspend(struct early_suspend *h)
763 {
764 atomic_set(&(hrm_context_obj->early_suspend), 1);
765 HRM_LOG(" hrm_early_suspend ok------->hwm_obj->early_suspend=%d \n",atomic_read(&(hrm_context_obj->early_suspend)));
766 return ;
767 }
768 /*----------------------------------------------------------------------------*/
769 static void hrm_late_resume(struct early_suspend *h)
770 {
771 atomic_set(&(hrm_context_obj->early_suspend), 0);
772 HRM_LOG(" hrm_late_resume ok------->hwm_obj->early_suspend=%d \n",atomic_read(&(hrm_context_obj->early_suspend)));
773 return ;
774 }
775
776 static int hrm_suspend(struct platform_device *dev, pm_message_t state)
777 {
778 return 0;
779 }
780 /*----------------------------------------------------------------------------*/
781 static int hrm_resume(struct platform_device *dev)
782 {
783 return 0;
784 }
785
786 #ifdef CONFIG_OF
787 static const struct of_device_id m_hrm_pl_of_match[] = {
788 { .compatible = "mediatek,m_hrm_pl", },
789 {},
790 };
791 #endif
792
793 static struct platform_driver hrm_driver =
794 {
795 .probe = hrm_probe,
796 .remove = hrm_remove,
797 .suspend = hrm_suspend,
798 .resume = hrm_resume,
799 .driver =
800 {
801 .name = HRM_PL_DEV_NAME,//mt_hrm_pl
802 #ifdef CONFIG_OF
803 .of_match_table = m_hrm_pl_of_match,
804 #endif
805 }
806 };
807
808 static int __init hrm_init(void)
809 {
810 HRM_FUN(f);
811
812 if(platform_driver_register(&hrm_driver))
813 {
814 HRM_ERR("failed to register hrm driver\n");
815 return -ENODEV;
816 }
817
818 return 0;
819 }
820
821 static void __exit hrm_exit(void)
822 {
823 platform_driver_unregister(&hrm_driver);
824 platform_driver_unregister(&heart_rate_driver);
825 }
826
827 late_initcall(hrm_init);
828 //module_init(hrm_init);
829 //module_exit(hrm_exit);
830 MODULE_LICENSE("GPL");
831 MODULE_DESCRIPTION("HEART_RATE device driver");
832 MODULE_AUTHOR("Mediatek");
833