~ubuntu-branches/ubuntu/trusty/linux-backports-modules-3.2.0/trusty

« back to all changes in this revision

Viewing changes to updates/cw-3.3/net/rfkill/rfkill-regulator.c

  • Committer: Package Import Robot
  • Author(s): Leann Ogasawara
  • Date: 2012-02-15 08:42:08 UTC
  • Revision ID: package-import@ubuntu.com-20120215084208-2gcs2zosufz014pi
Tags: 3.2.0-18.1
* Open Precise LBM
* Add compat-wireless v3.3
* Consolidated amd64 server flavour into generic
* Remove lpia control file
* Update Vcs-Git to ubuntu-preicse-lbm

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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 = false;
 
40
                }
 
41
        } else {
 
42
                if (!rfkill_data->reg_enabled) {
 
43
                        regulator_enable(rfkill_data->vcc);
 
44
                        rfkill_data->reg_enabled = true;
 
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
                ret = -ENOMEM;
 
94
                goto err_rfkill_alloc;
 
95
        }
 
96
 
 
97
        if (regulator_is_enabled(vcc)) {
 
98
                dev_dbg(&pdev->dev, "Regulator already enabled\n");
 
99
                rfkill_data->reg_enabled = true;
 
100
        }
 
101
        rfkill_data->vcc = vcc;
 
102
        rfkill_data->rf_kill = rf_kill;
 
103
 
 
104
        ret = rfkill_register(rf_kill);
 
105
        if (ret) {
 
106
                dev_err(&pdev->dev, "Cannot register rfkill device\n");
 
107
                goto err_rfkill_register;
 
108
        }
 
109
 
 
110
        platform_set_drvdata(pdev, rfkill_data);
 
111
        dev_info(&pdev->dev, "%s initialized\n", pdata->name);
 
112
 
 
113
        return 0;
 
114
 
 
115
err_rfkill_register:
 
116
        rfkill_destroy(rf_kill);
 
117
err_rfkill_alloc:
 
118
        kfree(rfkill_data);
 
119
err_data_alloc:
 
120
        regulator_put(vcc);
 
121
out:
 
122
        return ret;
 
123
}
 
124
 
 
125
static int __devexit rfkill_regulator_remove(struct platform_device *pdev)
 
126
{
 
127
        struct rfkill_regulator_data *rfkill_data = platform_get_drvdata(pdev);
 
128
        struct rfkill *rf_kill = rfkill_data->rf_kill;
 
129
 
 
130
        rfkill_unregister(rf_kill);
 
131
        rfkill_destroy(rf_kill);
 
132
        regulator_put(rfkill_data->vcc);
 
133
        kfree(rfkill_data);
 
134
 
 
135
        return 0;
 
136
}
 
137
 
 
138
static struct platform_driver rfkill_regulator_driver = {
 
139
        .probe = rfkill_regulator_probe,
 
140
        .remove = __devexit_p(rfkill_regulator_remove),
 
141
        .driver = {
 
142
                .name = "rfkill-regulator",
 
143
                .owner = THIS_MODULE,
 
144
        },
 
145
};
 
146
 
 
147
module_platform_driver(rfkill_regulator_driver);
 
148
 
 
149
MODULE_AUTHOR("Guiming Zhuo <gmzhuo@gmail.com>");
 
150
MODULE_AUTHOR("Antonio Ospite <ospite@studenti.unina.it>");
 
151
MODULE_DESCRIPTION("Regulator consumer driver for rfkill");
 
152
MODULE_LICENSE("GPL");
 
153
MODULE_ALIAS("platform:rfkill-regulator");