diff options
| author | Antonio Ospite <ospite@studenti.unina.it> | 2011-04-13 15:40:45 -0400 |
|---|---|---|
| committer | John W. Linville <linville@tuxdriver.com> | 2011-04-19 15:38:02 -0400 |
| commit | cbc6a6ed0900aed789b5ca77192845f2f987af70 (patch) | |
| tree | d7aa6e267e34417a857121de210ffd47f8e0eb2a /net/rfkill | |
| parent | bb411b4db2767cfd4a99b3328da843ce4ea1596a (diff) | |
rfkill: Regulator consumer driver for rfkill
Add a regulator consumer driver for rfkill to enable controlling radio
transmitters connected to voltage regulators using the regulator
framework.
A new "vrfkill" virtual supply is provided to use in platform code.
Signed-off-by: Guiming Zhuo <gmzhuo@gmail.com>
Signed-off-by: Antonio Ospite <ospite@studenti.unina.it>
Reviewed-by: Johannes Berg <johannes@sipsolutions.net>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'net/rfkill')
| -rw-r--r-- | net/rfkill/Kconfig | 11 | ||||
| -rw-r--r-- | net/rfkill/Makefile | 1 | ||||
| -rw-r--r-- | net/rfkill/rfkill-regulator.c | 164 |
3 files changed, 176 insertions, 0 deletions
diff --git a/net/rfkill/Kconfig b/net/rfkill/Kconfig index 7fce6dfd2180..48464ca13b24 100644 --- a/net/rfkill/Kconfig +++ b/net/rfkill/Kconfig | |||
| @@ -22,3 +22,14 @@ config RFKILL_INPUT | |||
| 22 | depends on RFKILL | 22 | depends on RFKILL |
| 23 | depends on INPUT = y || RFKILL = INPUT | 23 | depends on INPUT = y || RFKILL = INPUT |
| 24 | default y if !EXPERT | 24 | default y if !EXPERT |
| 25 | |||
| 26 | config RFKILL_REGULATOR | ||
| 27 | tristate "Generic rfkill regulator driver" | ||
| 28 | depends on RFKILL || !RFKILL | ||
| 29 | depends on REGULATOR | ||
| 30 | help | ||
| 31 | This options enable controlling radio transmitters connected to | ||
| 32 | voltage regulator using the regulator framework. | ||
| 33 | |||
| 34 | To compile this driver as a module, choose M here: the module will | ||
| 35 | be called rfkill-regulator. | ||
diff --git a/net/rfkill/Makefile b/net/rfkill/Makefile index 662105352691..d9a5a58ffd8c 100644 --- a/net/rfkill/Makefile +++ b/net/rfkill/Makefile | |||
| @@ -5,3 +5,4 @@ | |||
| 5 | rfkill-y += core.o | 5 | rfkill-y += core.o |
| 6 | rfkill-$(CONFIG_RFKILL_INPUT) += input.o | 6 | rfkill-$(CONFIG_RFKILL_INPUT) += input.o |
| 7 | obj-$(CONFIG_RFKILL) += rfkill.o | 7 | obj-$(CONFIG_RFKILL) += rfkill.o |
| 8 | obj-$(CONFIG_RFKILL_REGULATOR) += rfkill-regulator.o | ||
diff --git a/net/rfkill/rfkill-regulator.c b/net/rfkill/rfkill-regulator.c new file mode 100644 index 000000000000..18dc512a10f3 --- /dev/null +++ b/net/rfkill/rfkill-regulator.c | |||
| @@ -0,0 +1,164 @@ | |||
| 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 | |||
| 15 | #include <linux/module.h> | ||
| 16 | #include <linux/err.h> | ||
| 17 | #include <linux/slab.h> | ||
| 18 | #include <linux/platform_device.h> | ||
| 19 | #include <linux/regulator/consumer.h> | ||
| 20 | #include <linux/rfkill.h> | ||
| 21 | #include <linux/rfkill-regulator.h> | ||
| 22 | |||
| 23 | struct rfkill_regulator_data { | ||
| 24 | struct rfkill *rf_kill; | ||
| 25 | bool reg_enabled; | ||
| 26 | |||
| 27 | struct regulator *vcc; | ||
| 28 | }; | ||
| 29 | |||
| 30 | static int rfkill_regulator_set_block(void *data, bool blocked) | ||
| 31 | { | ||
| 32 | struct rfkill_regulator_data *rfkill_data = data; | ||
| 33 | |||
| 34 | pr_debug("%s: blocked: %d\n", __func__, blocked); | ||
| 35 | |||
| 36 | if (blocked) { | ||
| 37 | if (rfkill_data->reg_enabled) { | ||
| 38 | regulator_disable(rfkill_data->vcc); | ||
| 39 | rfkill_data->reg_enabled = 0; | ||
| 40 | } | ||
| 41 | } else { | ||
| 42 | if (!rfkill_data->reg_enabled) { | ||
| 43 | regulator_enable(rfkill_data->vcc); | ||
| 44 | rfkill_data->reg_enabled = 1; | ||
| 45 | } | ||
| 46 | } | ||
| 47 | |||
| 48 | pr_debug("%s: regulator_is_enabled after set_block: %d\n", __func__, | ||
| 49 | regulator_is_enabled(rfkill_data->vcc)); | ||
| 50 | |||
| 51 | return 0; | ||
| 52 | } | ||
| 53 | |||
| 54 | struct rfkill_ops rfkill_regulator_ops = { | ||
| 55 | .set_block = rfkill_regulator_set_block, | ||
| 56 | }; | ||
| 57 | |||
| 58 | static int __devinit rfkill_regulator_probe(struct platform_device *pdev) | ||
| 59 | { | ||
| 60 | struct rfkill_regulator_platform_data *pdata = pdev->dev.platform_data; | ||
| 61 | struct rfkill_regulator_data *rfkill_data; | ||
| 62 | struct regulator *vcc; | ||
| 63 | struct rfkill *rf_kill; | ||
| 64 | int ret = 0; | ||
| 65 | |||
| 66 | if (pdata == NULL) { | ||
| 67 | dev_err(&pdev->dev, "no platform data\n"); | ||
| 68 | return -ENODEV; | ||
| 69 | } | ||
| 70 | |||
| 71 | if (pdata->name == NULL || pdata->type == 0) { | ||
| 72 | dev_err(&pdev->dev, "invalid name or type in platform data\n"); | ||
| 73 | return -EINVAL; | ||
| 74 | } | ||
| 75 | |||
| 76 | vcc = regulator_get_exclusive(&pdev->dev, "vrfkill"); | ||
| 77 | if (IS_ERR(vcc)) { | ||
| 78 | dev_err(&pdev->dev, "Cannot get vcc for %s\n", pdata->name); | ||
| 79 | ret = PTR_ERR(vcc); | ||
| 80 | goto out; | ||
| 81 | } | ||
| 82 | |||
| 83 | rfkill_data = kzalloc(sizeof(*rfkill_data), GFP_KERNEL); | ||
| 84 | if (rfkill_data == NULL) { | ||
| 85 | ret = -ENOMEM; | ||
| 86 | goto err_data_alloc; | ||
| 87 | } | ||
| 88 | |||
| 89 | rf_kill = rfkill_alloc(pdata->name, &pdev->dev, | ||
| 90 | pdata->type, | ||
| 91 | &rfkill_regulator_ops, rfkill_data); | ||
| 92 | if (rf_kill == NULL) { | ||
| 93 | dev_err(&pdev->dev, "Cannot alloc rfkill device\n"); | ||
| 94 | ret = -ENOMEM; | ||
| 95 | goto err_rfkill_alloc; | ||
| 96 | } | ||
| 97 | |||
| 98 | if (regulator_is_enabled(vcc)) { | ||
| 99 | dev_dbg(&pdev->dev, "Regulator already enabled\n"); | ||
| 100 | rfkill_data->reg_enabled = 1; | ||
| 101 | } | ||
| 102 | rfkill_data->vcc = vcc; | ||
| 103 | rfkill_data->rf_kill = rf_kill; | ||
| 104 | |||
| 105 | ret = rfkill_register(rf_kill); | ||
| 106 | if (ret) { | ||
| 107 | dev_err(&pdev->dev, "Cannot register rfkill device\n"); | ||
| 108 | goto err_rfkill_register; | ||
| 109 | } | ||
| 110 | |||
| 111 | platform_set_drvdata(pdev, rfkill_data); | ||
| 112 | dev_info(&pdev->dev, "%s initialized\n", pdata->name); | ||
| 113 | |||
| 114 | return 0; | ||
| 115 | |||
| 116 | err_rfkill_register: | ||
| 117 | rfkill_destroy(rf_kill); | ||
| 118 | err_rfkill_alloc: | ||
| 119 | kfree(rfkill_data); | ||
| 120 | err_data_alloc: | ||
| 121 | regulator_put(vcc); | ||
| 122 | out: | ||
| 123 | return ret; | ||
| 124 | } | ||
| 125 | |||
| 126 | static int __devexit rfkill_regulator_remove(struct platform_device *pdev) | ||
| 127 | { | ||
| 128 | struct rfkill_regulator_data *rfkill_data = platform_get_drvdata(pdev); | ||
| 129 | struct rfkill *rf_kill = rfkill_data->rf_kill; | ||
| 130 | |||
| 131 | rfkill_unregister(rf_kill); | ||
| 132 | rfkill_destroy(rf_kill); | ||
| 133 | regulator_put(rfkill_data->vcc); | ||
| 134 | kfree(rfkill_data); | ||
| 135 | |||
| 136 | return 0; | ||
| 137 | } | ||
| 138 | |||
| 139 | static struct platform_driver rfkill_regulator_driver = { | ||
| 140 | .probe = rfkill_regulator_probe, | ||
| 141 | .remove = __devexit_p(rfkill_regulator_remove), | ||
| 142 | .driver = { | ||
| 143 | .name = "rfkill-regulator", | ||
| 144 | .owner = THIS_MODULE, | ||
| 145 | }, | ||
| 146 | }; | ||
| 147 | |||
| 148 | static int __init rfkill_regulator_init(void) | ||
| 149 | { | ||
| 150 | return platform_driver_register(&rfkill_regulator_driver); | ||
| 151 | } | ||
| 152 | module_init(rfkill_regulator_init); | ||
| 153 | |||
| 154 | static void __exit rfkill_regulator_exit(void) | ||
| 155 | { | ||
| 156 | platform_driver_unregister(&rfkill_regulator_driver); | ||
| 157 | } | ||
| 158 | module_exit(rfkill_regulator_exit); | ||
| 159 | |||
| 160 | MODULE_AUTHOR("Guiming Zhuo <gmzhuo@gmail.com>"); | ||
| 161 | MODULE_AUTHOR("Antonio Ospite <ospite@studenti.unina.it>"); | ||
| 162 | MODULE_DESCRIPTION("Regulator consumer driver for rfkill"); | ||
| 163 | MODULE_LICENSE("GPL"); | ||
| 164 | MODULE_ALIAS("platform:rfkill-regulator"); | ||
