rfkill-regulator.c 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164
  1. /*
  2. * rfkill-regulator.c - Regulator consumer driver for rfkill
  3. *
  4. * Copyright (C) 2009 Guiming Zhuo <gmzhuo@gmail.com>
  5. * Copyright (C) 2011 Antonio Ospite <ospite@studenti.unina.it>
  6. *
  7. * Implementation inspired by leds-regulator driver.
  8. *
  9. * This program is free software; you can redistribute it and/or modify
  10. * it under the terms of the GNU General Public License version 2 as
  11. * published by the Free Software Foundation.
  12. *
  13. */
  14. #include <linux/module.h>
  15. #include <linux/err.h>
  16. #include <linux/slab.h>
  17. #include <linux/platform_device.h>
  18. #include <linux/regulator/consumer.h>
  19. #include <linux/rfkill.h>
  20. #include <linux/rfkill-regulator.h>
  21. struct rfkill_regulator_data {
  22. struct rfkill *rf_kill;
  23. bool reg_enabled;
  24. struct regulator *vcc;
  25. };
  26. static int rfkill_regulator_set_block(void *data, bool blocked)
  27. {
  28. struct rfkill_regulator_data *rfkill_data = data;
  29. pr_debug("%s: blocked: %d\n", __func__, blocked);
  30. if (blocked) {
  31. if (rfkill_data->reg_enabled) {
  32. regulator_disable(rfkill_data->vcc);
  33. rfkill_data->reg_enabled = 0;
  34. }
  35. } else {
  36. if (!rfkill_data->reg_enabled) {
  37. regulator_enable(rfkill_data->vcc);
  38. rfkill_data->reg_enabled = 1;
  39. }
  40. }
  41. pr_debug("%s: regulator_is_enabled after set_block: %d\n", __func__,
  42. regulator_is_enabled(rfkill_data->vcc));
  43. return 0;
  44. }
  45. struct rfkill_ops rfkill_regulator_ops = {
  46. .set_block = rfkill_regulator_set_block,
  47. };
  48. static int __devinit rfkill_regulator_probe(struct platform_device *pdev)
  49. {
  50. struct rfkill_regulator_platform_data *pdata = pdev->dev.platform_data;
  51. struct rfkill_regulator_data *rfkill_data;
  52. struct regulator *vcc;
  53. struct rfkill *rf_kill;
  54. int ret = 0;
  55. if (pdata == NULL) {
  56. dev_err(&pdev->dev, "no platform data\n");
  57. return -ENODEV;
  58. }
  59. if (pdata->name == NULL || pdata->type == 0) {
  60. dev_err(&pdev->dev, "invalid name or type in platform data\n");
  61. return -EINVAL;
  62. }
  63. vcc = regulator_get_exclusive(&pdev->dev, "vrfkill");
  64. if (IS_ERR(vcc)) {
  65. dev_err(&pdev->dev, "Cannot get vcc for %s\n", pdata->name);
  66. ret = PTR_ERR(vcc);
  67. goto out;
  68. }
  69. rfkill_data = kzalloc(sizeof(*rfkill_data), GFP_KERNEL);
  70. if (rfkill_data == NULL) {
  71. ret = -ENOMEM;
  72. goto err_data_alloc;
  73. }
  74. rf_kill = rfkill_alloc(pdata->name, &pdev->dev,
  75. pdata->type,
  76. &rfkill_regulator_ops, rfkill_data);
  77. if (rf_kill == NULL) {
  78. dev_err(&pdev->dev, "Cannot alloc rfkill device\n");
  79. ret = -ENOMEM;
  80. goto err_rfkill_alloc;
  81. }
  82. if (regulator_is_enabled(vcc)) {
  83. dev_dbg(&pdev->dev, "Regulator already enabled\n");
  84. rfkill_data->reg_enabled = 1;
  85. }
  86. rfkill_data->vcc = vcc;
  87. rfkill_data->rf_kill = rf_kill;
  88. ret = rfkill_register(rf_kill);
  89. if (ret) {
  90. dev_err(&pdev->dev, "Cannot register rfkill device\n");
  91. goto err_rfkill_register;
  92. }
  93. platform_set_drvdata(pdev, rfkill_data);
  94. dev_info(&pdev->dev, "%s initialized\n", pdata->name);
  95. return 0;
  96. err_rfkill_register:
  97. rfkill_destroy(rf_kill);
  98. err_rfkill_alloc:
  99. kfree(rfkill_data);
  100. err_data_alloc:
  101. regulator_put(vcc);
  102. out:
  103. return ret;
  104. }
  105. static int __devexit rfkill_regulator_remove(struct platform_device *pdev)
  106. {
  107. struct rfkill_regulator_data *rfkill_data = platform_get_drvdata(pdev);
  108. struct rfkill *rf_kill = rfkill_data->rf_kill;
  109. rfkill_unregister(rf_kill);
  110. rfkill_destroy(rf_kill);
  111. regulator_put(rfkill_data->vcc);
  112. kfree(rfkill_data);
  113. return 0;
  114. }
  115. static struct platform_driver rfkill_regulator_driver = {
  116. .probe = rfkill_regulator_probe,
  117. .remove = __devexit_p(rfkill_regulator_remove),
  118. .driver = {
  119. .name = "rfkill-regulator",
  120. .owner = THIS_MODULE,
  121. },
  122. };
  123. static int __init rfkill_regulator_init(void)
  124. {
  125. return platform_driver_register(&rfkill_regulator_driver);
  126. }
  127. module_init(rfkill_regulator_init);
  128. static void __exit rfkill_regulator_exit(void)
  129. {
  130. platform_driver_unregister(&rfkill_regulator_driver);
  131. }
  132. module_exit(rfkill_regulator_exit);
  133. MODULE_AUTHOR("Guiming Zhuo <gmzhuo@gmail.com>");
  134. MODULE_AUTHOR("Antonio Ospite <ospite@studenti.unina.it>");
  135. MODULE_DESCRIPTION("Regulator consumer driver for rfkill");
  136. MODULE_LICENSE("GPL");
  137. MODULE_ALIAS("platform:rfkill-regulator");