rfkill-regulator.c 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154
  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 = false;
  34. }
  35. } else {
  36. if (!rfkill_data->reg_enabled) {
  37. regulator_enable(rfkill_data->vcc);
  38. rfkill_data->reg_enabled = true;
  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. ret = -ENOMEM;
  79. goto err_rfkill_alloc;
  80. }
  81. if (regulator_is_enabled(vcc)) {
  82. dev_dbg(&pdev->dev, "Regulator already enabled\n");
  83. rfkill_data->reg_enabled = true;
  84. }
  85. rfkill_data->vcc = vcc;
  86. rfkill_data->rf_kill = rf_kill;
  87. ret = rfkill_register(rf_kill);
  88. if (ret) {
  89. dev_err(&pdev->dev, "Cannot register rfkill device\n");
  90. goto err_rfkill_register;
  91. }
  92. platform_set_drvdata(pdev, rfkill_data);
  93. dev_info(&pdev->dev, "%s initialized\n", pdata->name);
  94. return 0;
  95. err_rfkill_register:
  96. rfkill_destroy(rf_kill);
  97. err_rfkill_alloc:
  98. kfree(rfkill_data);
  99. err_data_alloc:
  100. regulator_put(vcc);
  101. out:
  102. return ret;
  103. }
  104. static int __devexit rfkill_regulator_remove(struct platform_device *pdev)
  105. {
  106. struct rfkill_regulator_data *rfkill_data = platform_get_drvdata(pdev);
  107. struct rfkill *rf_kill = rfkill_data->rf_kill;
  108. rfkill_unregister(rf_kill);
  109. rfkill_destroy(rf_kill);
  110. regulator_put(rfkill_data->vcc);
  111. kfree(rfkill_data);
  112. return 0;
  113. }
  114. static struct platform_driver rfkill_regulator_driver = {
  115. .probe = rfkill_regulator_probe,
  116. .remove = __devexit_p(rfkill_regulator_remove),
  117. .driver = {
  118. .name = "rfkill-regulator",
  119. .owner = THIS_MODULE,
  120. },
  121. };
  122. module_platform_driver(rfkill_regulator_driver);
  123. MODULE_AUTHOR("Guiming Zhuo <gmzhuo@gmail.com>");
  124. MODULE_AUTHOR("Antonio Ospite <ospite@studenti.unina.it>");
  125. MODULE_DESCRIPTION("Regulator consumer driver for rfkill");
  126. MODULE_LICENSE("GPL");
  127. MODULE_ALIAS("platform:rfkill-regulator");