2 #include "heart_rate.h"
4 struct hrm_context
*hrm_context_obj
= NULL
;
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
);
11 static void hrm_work_func(struct work_struct
*work
)
14 struct hrm_context
*cxt
= NULL
;
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
25 cxt
= hrm_context_obj
;
27 if(NULL
== cxt
->hrm_data
.get_data
)
29 HRM_ERR("hrm driver not register data path\n");
33 time
.tv_sec
= time
.tv_nsec
= 0;
34 time
= get_monotonic_coarse();
35 nt
= time
.tv_sec
*1000000000LL+time
.tv_nsec
;
37 //add wake lock to make sure data can be read before system suspend
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];
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]);
50 HRM_ERR("get hrm data fails!!\n" );
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]))
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
;
78 if(true == cxt
->is_first_data_after_enable
)
80 cxt
->is_first_data_after_enable
= false;
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])
87 HRM_LOG(" read invalid data \n");
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]);
97 hrm_data_report(cxt
->drv_data
.hrm_data
, cxt
->drv_data
.hrm_data
.status
);
100 if(true == cxt
->is_polling_run
)
103 mod_timer(&cxt
->timer
, jiffies
+ atomic_read(&cxt
->delay
)/(1000/HZ
));
108 static void hrm_poll(unsigned long data
)
110 struct hrm_context
*obj
= (struct hrm_context
*)data
;
113 schedule_work(&obj
->report
);
117 static struct hrm_context
*hrm_context_alloc_object(void)
120 struct hrm_context
*obj
= kzalloc(sizeof(*obj
), GFP_KERNEL
);
121 HRM_LOG("hrm_context_alloc_object++++\n");
124 HRM_ERR("Alloc hrm object error!\n");
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");
142 static int hrm_real_enable(int enable
)
145 struct hrm_context
*cxt
= NULL
;
146 cxt
= hrm_context_obj
;
150 if(true==cxt
->is_active_data
|| true ==cxt
->is_active_nodata
)
152 err
= cxt
->hrm_ctl
.enable_nodata(1);
155 err
= cxt
->hrm_ctl
.enable_nodata(1);
158 err
= cxt
->hrm_ctl
.enable_nodata(1);
160 HRM_ERR("hrm enable(%d) err 3 timers = %d\n", enable
, err
);
163 HRM_LOG("hrm real enable \n" );
169 if(false==cxt
->is_active_data
&& false ==cxt
->is_active_nodata
)
171 err
= cxt
->hrm_ctl
.enable_nodata(0);
174 HRM_ERR("hrm enable(%d) err = %d\n", enable
, err
);
176 HRM_LOG("hrm real disable \n" );
183 static int hrm_enable_data(int enable
)
185 struct hrm_context
*cxt
= NULL
;
186 cxt
= hrm_context_obj
;
187 if(NULL
== cxt
->hrm_ctl
.open_report_data
)
189 HRM_ERR("no hrm control path\n");
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)
201 if(false == cxt
->hrm_ctl
.is_report_input_direct
)
203 mod_timer(&cxt
->timer
, jiffies
+ atomic_read(&cxt
->delay
)/(1000/HZ
));
204 cxt
->is_polling_run
= true;
210 HRM_LOG("hrm disable \n");
212 cxt
->is_active_data
=false;
213 cxt
->hrm_ctl
.open_report_data(0);
214 if(true == cxt
->is_polling_run
)
216 if(false == cxt
->hrm_ctl
.is_report_input_direct
)
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
;
229 hrm_real_enable(enable
);
235 int hrm_enable_nodata(int enable
)
237 struct hrm_context
*cxt
= NULL
;
238 cxt
= hrm_context_obj
;
239 if(NULL
== cxt
->hrm_ctl
.enable_nodata
)
241 HRM_ERR("hrm_enable_nodata:hrm ctl path is NULL\n");
247 cxt
->is_active_nodata
= true;
252 cxt
->is_active_nodata
= false;
254 hrm_real_enable(enable
);
259 static ssize_t
hrm_show_enable_nodata(struct device
* dev
,
260 struct device_attribute
*attr
, char *buf
)
263 HRM_LOG(" not support now\n");
267 static ssize_t
hrm_store_enable_nodata(struct device
* dev
, struct device_attribute
*attr
,
268 const char *buf
, size_t count
)
270 struct hrm_context
*cxt
= NULL
;
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
)
277 HRM_LOG("hrm_ctl enable nodata NULL\n");
278 mutex_unlock(&hrm_context_obj
->hrm_op_mutex
);
281 if (!strncmp(buf
, "1", 1))
283 hrm_enable_nodata(1);
285 else if (!strncmp(buf
, "0", 1))
287 hrm_enable_nodata(0);
291 HRM_ERR(" hrm_store enable nodata cmd error !!\n");
293 mutex_unlock(&hrm_context_obj
->hrm_op_mutex
);
297 static ssize_t
hrm_store_active(struct device
* dev
, struct device_attribute
*attr
,
298 const char *buf
, size_t count
)
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
)
306 HRM_LOG("hrm_ctl enable NULL\n");
307 mutex_unlock(&hrm_context_obj
->hrm_op_mutex
);
310 if (!strncmp(buf
, "1", 1))
315 else if (!strncmp(buf
, "0", 1))
321 HRM_ERR(" hrm_store_active error !!\n");
323 mutex_unlock(&hrm_context_obj
->hrm_op_mutex
);
324 HRM_LOG(" hrm_store_active done\n");
327 /*----------------------------------------------------------------------------*/
328 static ssize_t
hrm_show_active(struct device
* dev
,
329 struct device_attribute
*attr
, char *buf
)
331 struct hrm_context
*cxt
= NULL
;
333 cxt
= hrm_context_obj
;
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
);
343 static ssize_t
hrm_store_delay(struct device
* dev
, struct device_attribute
*attr
,
344 const char *buf
, size_t count
)
346 // struct hrm_context *devobj = (struct hrm_context*)dev_get_drvdata(dev);
349 struct hrm_context
*cxt
= NULL
;
351 mutex_lock(&hrm_context_obj
->hrm_op_mutex
);
352 cxt
= hrm_context_obj
;
353 if(NULL
== cxt
->hrm_ctl
.set_delay
)
355 HRM_LOG("hrm_ctl set_delay NULL\n");
356 mutex_unlock(&hrm_context_obj
->hrm_op_mutex
);
360 if (1 != sscanf(buf
, "%d", &delay
)) {
361 HRM_ERR("invalid format!!\n");
362 mutex_unlock(&hrm_context_obj
->hrm_op_mutex
);
366 if(false == cxt
->hrm_ctl
.is_report_input_direct
)
368 mdelay
= (int)delay
/1000/1000;
369 atomic_set(&hrm_context_obj
->delay
, mdelay
);
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
);
377 static ssize_t
hrm_show_delay(struct device
* dev
,
378 struct device_attribute
*attr
, char *buf
)
381 HRM_LOG(" not support now\n");
385 static ssize_t
hrm_store_batch(struct device
* dev
, struct device_attribute
*attr
,
386 const char *buf
, size_t count
)
388 struct hrm_context
*cxt
= NULL
;
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
){
395 if (!strncmp(buf
, "1", 1))
397 cxt
->is_batch_enable
= true;
399 else if (!strncmp(buf
, "0", 1))
401 cxt
->is_batch_enable
= false;
405 HRM_ERR(" hrm_store_batch error !!\n");
408 HRM_LOG(" hrm_store_batch not support\n");
410 mutex_unlock(&hrm_context_obj
->hrm_op_mutex
);
411 HRM_LOG(" hrm_store_batch done: %d\n", cxt
->is_batch_enable
);
416 static ssize_t
hrm_show_batch(struct device
* dev
,
417 struct device_attribute
*attr
, char *buf
)
419 return snprintf(buf
, PAGE_SIZE
, "%d\n", 0);
422 static ssize_t
hrm_store_flush(struct device
* dev
, struct device_attribute
*attr
,
423 const char *buf
, size_t count
)
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);
432 static ssize_t
hrm_show_flush(struct device
* dev
,
433 struct device_attribute
*attr
, char *buf
)
435 return snprintf(buf
, PAGE_SIZE
, "%d\n", 0);
438 static ssize_t
hrm_show_devnum(struct device
* dev
,
439 struct device_attribute
*attr
, char *buf
)
441 const char *devname
= NULL
;
442 devname
= dev_name(&hrm_context_obj
->idev
->dev
);
443 return snprintf(buf
, PAGE_SIZE
, "%s\n", devname
+5);
445 static int heart_rate_remove(struct platform_device
*pdev
)
447 HRM_LOG("heart_rate_remove\n");
451 static int heart_rate_probe(struct platform_device
*pdev
)
453 HRM_LOG("heart_rate_probe\n");
458 static const struct of_device_id heart_rate_of_match
[] = {
459 { .compatible
= "mediatek,heart_rate", },
464 static struct platform_driver heart_rate_driver
= {
465 .probe
= heart_rate_probe
,
466 .remove
= heart_rate_remove
,
469 .name
= "heart_rate",
471 .of_match_table
= heart_rate_of_match
,
476 static int hrm_real_driver_init(void)
480 HRM_LOG(" hrm_real_driver_init +\n");
481 for(i
= 0; i
< MAX_CHOOSE_HRM_NUM
; i
++)
483 HRM_LOG(" i=%d\n",i
);
484 if(0 != heart_rate_init_list
[i
])
486 HRM_LOG(" hrm try to init driver %s\n", heart_rate_init_list
[i
]->name
);
487 err
= heart_rate_init_list
[i
]->init();
490 HRM_LOG(" hrm real driver %s probe ok\n", heart_rate_init_list
[i
]->name
);
496 if(i
== MAX_CHOOSE_HRM_NUM
)
498 HRM_LOG(" hrm_real_driver_init fail\n");
504 int hrm_driver_add(struct hrm_init_info
* obj
)
511 for(i
=0; i
< MAX_CHOOSE_HRM_NUM
; i
++ )
514 HRM_LOG("register hrm driver for the first time\n");
515 if(platform_driver_register(&heart_rate_driver
))
517 HRM_ERR("failed to register hrm driver already exist\n");
521 if(NULL
== heart_rate_init_list
[i
])
523 obj
->platform_diver_addr
= &heart_rate_driver
;
524 heart_rate_init_list
[i
] = obj
;
528 if(NULL
==heart_rate_init_list
[i
])
530 HRM_ERR("hrm driver add err \n");
536 EXPORT_SYMBOL_GPL(hrm_driver_add
);
538 static int hrm_misc_init(struct hrm_context
*cxt
)
542 cxt
->mdev
.minor
= MISC_DYNAMIC_MINOR
;
543 cxt
->mdev
.name
= HRM_MISC_DEV_NAME
;
544 if((err
= misc_register(&cxt
->mdev
)))
546 HRM_ERR("unable to register hrm misc device!!\n");
551 static void hrm_input_destroy(struct hrm_context
*cxt
)
553 struct input_dev
*dev
= cxt
->idev
;
555 input_unregister_device(dev
);
556 input_free_device(dev
);
559 static int hrm_input_init(struct hrm_context
*cxt
)
561 struct input_dev
*dev
;
564 dev
= input_allocate_device();
568 dev
->name
= HRM_INPUTDEV_NAME
;
570 input_set_capability(dev
, EV_ABS
, EVENT_TYPE_HRM_BPM
);
571 input_set_capability(dev
, EV_ABS
, EVENT_TYPE_HRM_STATUS
);
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
);
577 err
= input_register_device(dev
);
579 input_free_device(dev
);
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
);
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
,
604 static struct attribute_group hrm_attribute_group
= {
605 .attrs
= hrm_attributes
608 int hrm_register_data_path(struct hrm_data_path
*data
)
610 struct hrm_context
*cxt
= NULL
;
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
)
619 HRM_LOG("hrm register data path fail \n");
625 int hrm_register_control_path(struct hrm_control_path
*ctl
)
627 struct hrm_context
*cxt
= NULL
;
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
;
635 if(NULL
==cxt
->hrm_ctl
.set_delay
|| NULL
==cxt
->hrm_ctl
.open_report_data
636 || NULL
==cxt
->hrm_ctl
.enable_nodata
)
638 HRM_LOG("hrm register control path fail \n");
642 //add misc dev for sensor hal control cmd
643 err
= hrm_misc_init(hrm_context_obj
);
646 HRM_ERR("unable to register hrm misc device!!\n");
649 err
= sysfs_create_group(&hrm_context_obj
->mdev
.this_device
->kobj
,
650 &hrm_attribute_group
);
653 HRM_ERR("unable to create hrm attribute file\n");
657 kobject_uevent(&hrm_context_obj
->mdev
.this_device
->kobj
, KOBJ_ADD
);
662 int hrm_data_report(hwm_sensor_data data
,int status
)
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
;
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
);
674 static int hrm_probe(struct platform_device
*pdev
)
678 HRM_LOG("+++++++++++++hrm_probe!!\n");
680 hrm_context_obj
= hrm_context_alloc_object();
681 if (!hrm_context_obj
)
684 HRM_ERR("unable to allocate devobj!\n");
685 goto exit_alloc_data_failed
;
688 //init real hrmeleration driver
689 err
= hrm_real_driver_init();
692 HRM_ERR("hrm real driver init fail\n");
693 goto real_driver_init_fail
;
696 //err = hrm_factory_device_init();
699 // HRM_ERR("hrm_factory_device_init fail\n");
703 err
= hrm_input_init(hrm_context_obj
);
706 HRM_ERR("unable to register hrm input device!\n");
707 goto exit_alloc_input_dev_failed
;
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)
718 HRM_LOG("----hrm_probe OK !!\n");
721 //exit_hwmsen_create_attr_failed:
722 //exit_misc_register_failed:
728 HRM_ERR("sysfs node creation error \n");
729 hrm_input_destroy(hrm_context_obj
);
732 real_driver_init_fail
:
733 exit_alloc_input_dev_failed
:
734 kfree(hrm_context_obj
);
736 exit_alloc_data_failed
:
739 HRM_LOG("----hrm_probe fail !!!\n");
745 static int hrm_remove(struct platform_device
*pdev
)
749 input_unregister_device(hrm_context_obj
->idev
);
750 sysfs_remove_group(&hrm_context_obj
->idev
->dev
.kobj
,
751 &hrm_attribute_group
);
753 if((err
= misc_deregister(&hrm_context_obj
->mdev
)))
755 HRM_ERR("misc_deregister fail: %d\n", err
);
757 kfree(hrm_context_obj
);
762 static void hrm_early_suspend(struct early_suspend
*h
)
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
)));
768 /*----------------------------------------------------------------------------*/
769 static void hrm_late_resume(struct early_suspend
*h
)
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
)));
776 static int hrm_suspend(struct platform_device
*dev
, pm_message_t state
)
780 /*----------------------------------------------------------------------------*/
781 static int hrm_resume(struct platform_device
*dev
)
787 static const struct of_device_id m_hrm_pl_of_match
[] = {
788 { .compatible
= "mediatek,m_hrm_pl", },
793 static struct platform_driver hrm_driver
=
796 .remove
= hrm_remove
,
797 .suspend
= hrm_suspend
,
798 .resume
= hrm_resume
,
801 .name
= HRM_PL_DEV_NAME
,//mt_hrm_pl
803 .of_match_table
= m_hrm_pl_of_match
,
808 static int __init
hrm_init(void)
812 if(platform_driver_register(&hrm_driver
))
814 HRM_ERR("failed to register hrm driver\n");
821 static void __exit
hrm_exit(void)
823 platform_driver_unregister(&hrm_driver
);
824 platform_driver_unregister(&heart_rate_driver
);
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");