rfkill-regulator.c 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155
  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. int ret = 0;
  30. pr_debug("%s: blocked: %d\n", __func__, blocked);
  31. if (blocked) {
  32. if (rfkill_data->reg_enabled) {
  33. regulator_disable(rfkill_data->vcc);
  34. rfkill_data->reg_enabled = false;
  35. }
  36. } else {
  37. if (!rfkill_data->reg_enabled) {
  38. ret = regulator_enable(rfkill_data->vcc);
  39. if (!ret)
  40. rfkill_data->reg_enabled = true;
  41. }
  42. }
  43. pr_debug("%s: regulator_is_enabled after set_block: %d\n", __func__,
  44. regulator_is_enabled(rfkill_data->vcc));
  45. return ret;
  46. }
  47. static struct rfkill_ops rfkill_regulator_ops = {
  48. .set_block = rfkill_regulator_set_block,
  49. };
  50. static int rfkill_regulator_probe(struct platform_device *pdev)
  51. {
  52. struct rfkill_regulator_platform_data *pdata = pdev->dev.platform_data;
  53. struct rfkill_regulator_data *rfkill_data;
  54. struct regulator *vcc;
  55. struct rfkill *rf_kill;
  56. int ret = 0;
  57. if (pdata == NULL) {
  58. dev_err(&pdev->dev, "no platform data\n");
  59. return -ENODEV;
  60. }
  61. if (pdata->name == NULL || pdata->type == 0) {
  62. dev_err(&pdev->dev, "invalid name or type in platform data\n");
  63. return -EINVAL;
  64. }
  65. vcc = regulator_get_exclusive(&pdev->dev, "vrfkill");
  66. if (IS_ERR(vcc)) {
  67. dev_err(&pdev->dev, "Cannot get vcc for %s\n", pdata->name);
  68. ret = PTR_ERR(vcc);
  69. goto out;
  70. }
  71. rfkill_data = kzalloc(sizeof(*rfkill_data), GFP_KERNEL);
  72. if (rfkill_data == NULL) {
  73. ret = -ENOMEM;
  74. goto err_data_alloc;
  75. }
  76. rf_kill = rfkill_alloc(pdata->name, &pdev->dev,
  77. pdata->type,
  78. &rfkill_regulator_ops, rfkill_data);
  79. if (rf_kill == NULL) {
  80. ret = -ENOMEM;
  81. goto err_rfkill_alloc;
  82. }
  83. if (regulator_is_enabled(vcc)) {
  84. dev_dbg(&pdev->dev, "Regulator already enabled\n");
  85. rfkill_data->reg_enabled = true;
  86. }
  87. rfkill_data->vcc = vcc;
  88. rfkill_data->rf_kill = rf_kill;
  89. ret = rfkill_register(rf_kill);
  90. if (ret) {
  91. dev_err(&pdev->dev, "Cannot register rfkill device\n");
  92. goto err_rfkill_register;
  93. }
  94. platform_set_drvdata(pdev, rfkill_data);
  95. dev_info(&pdev->dev, "%s initialized\n", pdata->name);
  96. return 0;
  97. err_rfkill_register:
  98. rfkill_destroy(rf_kill);
  99. err_rfkill_alloc:
  100. kfree(rfkill_data);
  101. err_data_alloc:
  102. regulator_put(vcc);
  103. out:
  104. return ret;
  105. }
  106. static int rfkill_regulator_remove(struct platform_device *pdev)
  107. {
  108. struct rfkill_regulator_data *rfkill_data = platform_get_drvdata(pdev);
  109. struct rfkill *rf_kill = rfkill_data->rf_kill;
  110. rfkill_unregister(rf_kill);
  111. rfkill_destroy(rf_kill);
  112. regulator_put(rfkill_data->vcc);
  113. kfree(rfkill_data);
  114. return 0;
  115. }
  116. static struct platform_driver rfkill_regulator_driver = {
  117. .probe = rfkill_regulator_probe,
  118. .remove = rfkill_regulator_remove,
  119. .driver = {
  120. .name = "rfkill-regulator",
  121. },
  122. };
  123. module_platform_driver(rfkill_regulator_driver);
  124. MODULE_AUTHOR("Guiming Zhuo <gmzhuo@gmail.com>");
  125. MODULE_AUTHOR("Antonio Ospite <ospite@studenti.unina.it>");
  126. MODULE_DESCRIPTION("Regulator consumer driver for rfkill");
  127. MODULE_LICENSE("GPL");
  128. MODULE_ALIAS("platform:rfkill-regulator");