bt_device.c 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232
  1. /*
  2. *
  3. * arch/arm/mach-meson/bcm-bt.c
  4. *
  5. * Copyright (C) 2010 AMLOGIC, INC.
  6. *
  7. * License terms: GNU General Public License (GPL) version 2
  8. * Platform machine definition.
  9. */
  10. #include <linux/module.h>
  11. #include <linux/platform_device.h>
  12. #include <linux/delay.h>
  13. #include <linux/string.h>
  14. #include <linux/ctype.h>
  15. #include <linux/leds.h>
  16. #include <linux/gpio.h>
  17. #include <linux/rfkill.h>
  18. #include <plat/bt_device.h>
  19. #include <net/bluetooth/bluetooth.h>
  20. #include <net/bluetooth/hci_core.h>
  21. #ifdef CONFIG_HAS_EARLYSUSPEND
  22. #include <linux/earlysuspend.h>
  23. static struct early_suspend bt_early_suspend;
  24. #endif
  25. extern struct bt_dev_data bt_dev;
  26. void rfkill_switch_all(enum rfkill_type type, bool blocked);
  27. #if 0
  28. static unsigned long bt_baud;
  29. extern int get_baud(int line);
  30. extern void set_baud(int line, unsigned long newbaud);
  31. static struct delayed_work btwork;
  32. static void bt_reset_workqueue(struct work_struct *work)
  33. {
  34. struct hci_dev *hdev;
  35. printk("bt reset\n");
  36. if( hdev = hci_dev_get(0)){
  37. hci_resume_dev(hdev);
  38. }
  39. }
  40. #endif
  41. static int bt_set_block(void *data, bool blocked)
  42. {
  43. pr_info("BT_RADIO going: %s\n", blocked ? "off" : "on");
  44. if (!blocked) {
  45. pr_info("BCM_BT: going ON\n");
  46. if (NULL != bt_dev.bt_dev_on) {
  47. bt_dev.bt_dev_on();
  48. }
  49. } else {
  50. pr_info("BCM_BT: going OFF\n");
  51. if (NULL != bt_dev.bt_dev_off) {
  52. bt_dev.bt_dev_off();
  53. }
  54. }
  55. return 0;
  56. }
  57. static const struct rfkill_ops bt_rfkill_ops = {
  58. .set_block = bt_set_block,
  59. };
  60. static int bt_earlysuspend(struct platform_device *pdev, pm_message_t state)
  61. {
  62. #if 0
  63. struct hci_dev *hdev;
  64. pr_info("BCM_BT: going early suspend\n");
  65. if( hdev = hci_dev_get(0)){
  66. if (NULL != bt_dev.bt_dev_suspend) {
  67. bt_dev.bt_dev_suspend();
  68. }
  69. }
  70. #endif
  71. return 0;
  72. }
  73. static int bt_lateresume(struct platform_device *pdev)
  74. {
  75. #if 0
  76. struct hci_dev *hdev;
  77. pr_info("BCM_BT: going later resume\n");
  78. if( hdev = hci_dev_get(0)){
  79. if (NULL != bt_dev.bt_dev_resume) {
  80. bt_dev.bt_dev_resume();
  81. }
  82. /* when call the hci_dev_open after hci_dev_close, the bt will be restart */
  83. //hci_dev_open(0);
  84. }
  85. #endif
  86. return 0;
  87. }
  88. static int bt_suspend(struct platform_device *pdev, pm_message_t state)
  89. {
  90. #if 0
  91. struct hci_dev *hdev;
  92. pr_info("BCM_BT: going suspend\n");
  93. if( hdev = hci_dev_get(0)){
  94. if (NULL != bt_dev.bt_dev_off) {
  95. bt_dev.bt_dev_off();
  96. }
  97. /* if we do not power off bt , we should restore uart baud */
  98. //bt_baud = get_baud(1);
  99. }
  100. #endif
  101. return 0;
  102. }
  103. static int bt_resume(struct platform_device *pdev)
  104. {
  105. #if 0
  106. struct hci_dev *hdev;
  107. pr_info("BCM_BT: going resume\n");
  108. if( hdev = hci_dev_get(0)){
  109. if (NULL != bt_dev.bt_dev_on) {
  110. bt_dev.bt_dev_on();
  111. }
  112. //set_baud(1, bt_baud);
  113. //hci_dev_close(0);
  114. schedule_delayed_work(&btwork, 100);
  115. }
  116. #endif
  117. return 0;
  118. }
  119. static int __init bt_probe(struct platform_device *pdev)
  120. {
  121. int rc = 0;
  122. struct rfkill *bt_rfk;
  123. #if 0
  124. INIT_DELAYED_WORK(&btwork, bt_reset_workqueue);
  125. #endif
  126. /* default to bluetooth off */
  127. //rfkill_switch_all(RFKILL_TYPE_BLUETOOTH, 1);
  128. if (NULL != bt_dev.bt_dev_off) {
  129. bt_dev.bt_dev_off();
  130. }
  131. bt_rfk = rfkill_alloc("bt-dev", &pdev->dev, RFKILL_TYPE_BLUETOOTH,
  132. &bt_rfkill_ops, NULL);
  133. if (!bt_rfk) {
  134. printk("rfk alloc fail\n");
  135. rc = -ENOMEM;
  136. goto err_rfk_alloc;
  137. }
  138. /* if not set false, the bt_set_block will call when rfkill class resume */
  139. rfkill_init_sw_state(bt_rfk, false); //we want to reset bt when system resume
  140. rc = rfkill_register(bt_rfk);
  141. if (rc){
  142. printk("rfkill_register fail\n");
  143. goto err_rfkill;
  144. }
  145. platform_set_drvdata(pdev, bt_rfk);
  146. #ifdef CONFIG_HAS_EARLYSUSPEND
  147. bt_early_suspend.level = EARLY_SUSPEND_LEVEL_DISABLE_FB;
  148. bt_early_suspend.suspend = bt_earlysuspend;
  149. bt_early_suspend.resume = bt_lateresume;
  150. bt_early_suspend.param = pdev;
  151. register_early_suspend(&bt_early_suspend);
  152. #endif
  153. return 0;
  154. err_rfkill:
  155. rfkill_destroy(bt_rfk);
  156. err_rfk_alloc:
  157. return rc;
  158. }
  159. static int bt_remove(struct platform_device *pdev)
  160. {
  161. struct rfkill *rfk = platform_get_drvdata(pdev);
  162. platform_set_drvdata(pdev, NULL);
  163. if (rfk) {
  164. rfkill_unregister(rfk);
  165. rfkill_destroy(rfk);
  166. }
  167. rfk = NULL;
  168. return 0;
  169. }
  170. static struct platform_driver bt_driver = {
  171. .driver = {
  172. .name = "bt-dev",
  173. },
  174. .probe = bt_probe,
  175. .remove = bt_remove,
  176. .suspend = bt_suspend,
  177. .resume = bt_resume,
  178. };
  179. static int __init bt_init(void)
  180. {
  181. printk("amlogic rfkill init\n");
  182. if (NULL != bt_dev.bt_dev_init) {
  183. bt_dev.bt_dev_init();
  184. }
  185. return platform_driver_register(&bt_driver);
  186. }
  187. static void __exit bt_exit(void)
  188. {
  189. platform_driver_unregister(&bt_driver);
  190. }
  191. module_init(bt_init);
  192. module_exit(bt_exit);
  193. MODULE_DESCRIPTION("bt rfkill");
  194. MODULE_AUTHOR("");
  195. MODULE_LICENSE("GPL");