Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
fork

Configure Feed

Select the types of activity you want to include in your feed.

at v3.1-rc7 164 lines 4.1 kB view raw
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 23struct rfkill_regulator_data { 24 struct rfkill *rf_kill; 25 bool reg_enabled; 26 27 struct regulator *vcc; 28}; 29 30static 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 54struct rfkill_ops rfkill_regulator_ops = { 55 .set_block = rfkill_regulator_set_block, 56}; 57 58static 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 116err_rfkill_register: 117 rfkill_destroy(rf_kill); 118err_rfkill_alloc: 119 kfree(rfkill_data); 120err_data_alloc: 121 regulator_put(vcc); 122out: 123 return ret; 124} 125 126static 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 139static 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 148static int __init rfkill_regulator_init(void) 149{ 150 return platform_driver_register(&rfkill_regulator_driver); 151} 152module_init(rfkill_regulator_init); 153 154static void __exit rfkill_regulator_exit(void) 155{ 156 platform_driver_unregister(&rfkill_regulator_driver); 157} 158module_exit(rfkill_regulator_exit); 159 160MODULE_AUTHOR("Guiming Zhuo <gmzhuo@gmail.com>"); 161MODULE_AUTHOR("Antonio Ospite <ospite@studenti.unina.it>"); 162MODULE_DESCRIPTION("Regulator consumer driver for rfkill"); 163MODULE_LICENSE("GPL"); 164MODULE_ALIAS("platform:rfkill-regulator");