~ubuntu-branches/debian/wheezy/linux-2.6/wheezy

« back to all changes in this revision

Viewing changes to drivers/input/misc/pwm-beeper.c

  • Committer: Bazaar Package Importer
  • Author(s): Ben Hutchings, Ben Hutchings, Aurelien Jarno, Martin Michlmayr
  • Date: 2011-04-06 13:53:30 UTC
  • mfrom: (43.1.5 sid)
  • Revision ID: james.westby@ubuntu.com-20110406135330-wjufxhd0tvn3zx4z
Tags: 2.6.38-3
[ Ben Hutchings ]
* [ppc64] Add to linux-tools package architectures (Closes: #620124)
* [amd64] Save cr4 to mmu_cr4_features at boot time (Closes: #620284)
* appletalk: Fix bugs introduced when removing use of BKL
* ALSA: Fix yet another race in disconnection
* cciss: Fix lost command issue
* ath9k: Fix kernel panic in AR2427
* ses: Avoid kernel panic when lun 0 is not mapped
* PCI/ACPI: Report ASPM support to BIOS if not disabled from command line

[ Aurelien Jarno ]
* rtlwifi: fix build when PCI is not enabled.

[ Martin Michlmayr ]
* rtlwifi: Eliminate udelay calls with too large values (Closes: #620204)

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 *  Copyright (C) 2010, Lars-Peter Clausen <lars@metafoo.de>
 
3
 *  PWM beeper driver
 
4
 *
 
5
 *  This program is free software; you can redistribute it and/or modify it
 
6
 *  under  the terms of the GNU General  Public License as published by the
 
7
 *  Free Software Foundation;  either version 2 of the License, or (at your
 
8
 *  option) any later version.
 
9
 *
 
10
 *  You should have received a copy of the GNU General Public License along
 
11
 *  with this program; if not, write to the Free Software Foundation, Inc.,
 
12
 *  675 Mass Ave, Cambridge, MA 02139, USA.
 
13
 *
 
14
 */
 
15
 
 
16
#include <linux/input.h>
 
17
#include <linux/module.h>
 
18
#include <linux/kernel.h>
 
19
#include <linux/platform_device.h>
 
20
#include <linux/pwm.h>
 
21
#include <linux/slab.h>
 
22
 
 
23
struct pwm_beeper {
 
24
        struct input_dev *input;
 
25
        struct pwm_device *pwm;
 
26
        unsigned long period;
 
27
};
 
28
 
 
29
#define HZ_TO_NANOSECONDS(x) (1000000000UL/(x))
 
30
 
 
31
static int pwm_beeper_event(struct input_dev *input,
 
32
                            unsigned int type, unsigned int code, int value)
 
33
{
 
34
        int ret = 0;
 
35
        struct pwm_beeper *beeper = input_get_drvdata(input);
 
36
        unsigned long period;
 
37
 
 
38
        if (type != EV_SND || value < 0)
 
39
                return -EINVAL;
 
40
 
 
41
        switch (code) {
 
42
        case SND_BELL:
 
43
                value = value ? 1000 : 0;
 
44
                break;
 
45
        case SND_TONE:
 
46
                break;
 
47
        default:
 
48
                return -EINVAL;
 
49
        }
 
50
 
 
51
        if (value == 0) {
 
52
                pwm_config(beeper->pwm, 0, 0);
 
53
                pwm_disable(beeper->pwm);
 
54
        } else {
 
55
                period = HZ_TO_NANOSECONDS(value);
 
56
                ret = pwm_config(beeper->pwm, period / 2, period);
 
57
                if (ret)
 
58
                        return ret;
 
59
                ret = pwm_enable(beeper->pwm);
 
60
                if (ret)
 
61
                        return ret;
 
62
                beeper->period = period;
 
63
        }
 
64
 
 
65
        return 0;
 
66
}
 
67
 
 
68
static int __devinit pwm_beeper_probe(struct platform_device *pdev)
 
69
{
 
70
        unsigned long pwm_id = (unsigned long)pdev->dev.platform_data;
 
71
        struct pwm_beeper *beeper;
 
72
        int error;
 
73
 
 
74
        beeper = kzalloc(sizeof(*beeper), GFP_KERNEL);
 
75
        if (!beeper)
 
76
                return -ENOMEM;
 
77
 
 
78
        beeper->pwm = pwm_request(pwm_id, "pwm beeper");
 
79
 
 
80
        if (IS_ERR(beeper->pwm)) {
 
81
                error = PTR_ERR(beeper->pwm);
 
82
                dev_err(&pdev->dev, "Failed to request pwm device: %d\n", error);
 
83
                goto err_free;
 
84
        }
 
85
 
 
86
        beeper->input = input_allocate_device();
 
87
        if (!beeper->input) {
 
88
                dev_err(&pdev->dev, "Failed to allocate input device\n");
 
89
                error = -ENOMEM;
 
90
                goto err_pwm_free;
 
91
        }
 
92
        beeper->input->dev.parent = &pdev->dev;
 
93
 
 
94
        beeper->input->name = "pwm-beeper";
 
95
        beeper->input->phys = "pwm/input0";
 
96
        beeper->input->id.bustype = BUS_HOST;
 
97
        beeper->input->id.vendor = 0x001f;
 
98
        beeper->input->id.product = 0x0001;
 
99
        beeper->input->id.version = 0x0100;
 
100
 
 
101
        beeper->input->evbit[0] = BIT(EV_SND);
 
102
        beeper->input->sndbit[0] = BIT(SND_TONE) | BIT(SND_BELL);
 
103
 
 
104
        beeper->input->event = pwm_beeper_event;
 
105
 
 
106
        input_set_drvdata(beeper->input, beeper);
 
107
 
 
108
        error = input_register_device(beeper->input);
 
109
        if (error) {
 
110
                dev_err(&pdev->dev, "Failed to register input device: %d\n", error);
 
111
                goto err_input_free;
 
112
        }
 
113
 
 
114
        platform_set_drvdata(pdev, beeper);
 
115
 
 
116
        return 0;
 
117
 
 
118
err_input_free:
 
119
        input_free_device(beeper->input);
 
120
err_pwm_free:
 
121
        pwm_free(beeper->pwm);
 
122
err_free:
 
123
        kfree(beeper);
 
124
 
 
125
        return error;
 
126
}
 
127
 
 
128
static int __devexit pwm_beeper_remove(struct platform_device *pdev)
 
129
{
 
130
        struct pwm_beeper *beeper = platform_get_drvdata(pdev);
 
131
 
 
132
        platform_set_drvdata(pdev, NULL);
 
133
        input_unregister_device(beeper->input);
 
134
 
 
135
        pwm_disable(beeper->pwm);
 
136
        pwm_free(beeper->pwm);
 
137
 
 
138
        kfree(beeper);
 
139
 
 
140
        return 0;
 
141
}
 
142
 
 
143
#ifdef CONFIG_PM
 
144
static int pwm_beeper_suspend(struct device *dev)
 
145
{
 
146
        struct pwm_beeper *beeper = dev_get_drvdata(dev);
 
147
 
 
148
        if (beeper->period)
 
149
                pwm_disable(beeper->pwm);
 
150
 
 
151
        return 0;
 
152
}
 
153
 
 
154
static int pwm_beeper_resume(struct device *dev)
 
155
{
 
156
        struct pwm_beeper *beeper = dev_get_drvdata(dev);
 
157
 
 
158
        if (beeper->period) {
 
159
                pwm_config(beeper->pwm, beeper->period / 2, beeper->period);
 
160
                pwm_enable(beeper->pwm);
 
161
        }
 
162
 
 
163
        return 0;
 
164
}
 
165
 
 
166
static SIMPLE_DEV_PM_OPS(pwm_beeper_pm_ops,
 
167
                         pwm_beeper_suspend, pwm_beeper_resume);
 
168
 
 
169
#define PWM_BEEPER_PM_OPS (&pwm_beeper_pm_ops)
 
170
#else
 
171
#define PWM_BEEPER_PM_OPS NULL
 
172
#endif
 
173
 
 
174
static struct platform_driver pwm_beeper_driver = {
 
175
        .probe  = pwm_beeper_probe,
 
176
        .remove = __devexit_p(pwm_beeper_remove),
 
177
        .driver = {
 
178
                .name   = "pwm-beeper",
 
179
                .owner  = THIS_MODULE,
 
180
                .pm     = PWM_BEEPER_PM_OPS,
 
181
        },
 
182
};
 
183
 
 
184
static int __init pwm_beeper_init(void)
 
185
{
 
186
        return platform_driver_register(&pwm_beeper_driver);
 
187
}
 
188
module_init(pwm_beeper_init);
 
189
 
 
190
static void __exit pwm_beeper_exit(void)
 
191
{
 
192
        platform_driver_unregister(&pwm_beeper_driver);
 
193
}
 
194
module_exit(pwm_beeper_exit);
 
195
 
 
196
MODULE_AUTHOR("Lars-Peter Clausen <lars@metafoo.de>");
 
197
MODULE_DESCRIPTION("PWM beeper driver");
 
198
MODULE_LICENSE("GPL");
 
199
MODULE_ALIAS("platform:pwm-beeper");