]> git.karo-electronics.de Git - karo-tx-linux.git/blob - drivers/input/misc/sparcspkr.c
42c11fbf3c79ff12d405f9f2c13d1ebed9da7901
[karo-tx-linux.git] / drivers / input / misc / sparcspkr.c
1 /*
2  *  Driver for PC-speaker like devices found on various Sparc systems.
3  *
4  *  Copyright (c) 2002 Vojtech Pavlik
5  *  Copyright (c) 2002, 2006 David S. Miller (davem@davemloft.net)
6  */
7 #include <linux/config.h>
8 #include <linux/kernel.h>
9 #include <linux/module.h>
10 #include <linux/init.h>
11 #include <linux/input.h>
12 #include <linux/platform_device.h>
13
14 #include <asm/io.h>
15 #include <asm/ebus.h>
16 #include <asm/isa.h>
17
18 MODULE_AUTHOR("David S. Miller <davem@davemloft.net>");
19 MODULE_DESCRIPTION("Sparc Speaker beeper driver");
20 MODULE_LICENSE("GPL");
21
22 struct sparcspkr_state {
23         const char              *name;
24         unsigned long           iobase;
25         int (*event)(struct input_dev *dev, unsigned int type, unsigned int code, int value);
26         spinlock_t              lock;
27         struct input_dev        *input_dev;
28 };
29
30 static int ebus_spkr_event(struct input_dev *dev, unsigned int type, unsigned int code, int value)
31 {
32         struct sparcspkr_state *state = dev_get_drvdata(dev->cdev.dev);
33         unsigned int count = 0;
34         unsigned long flags;
35
36         if (type != EV_SND)
37                 return -1;
38
39         switch (code) {
40                 case SND_BELL: if (value) value = 1000;
41                 case SND_TONE: break;
42                 default: return -1;
43         }
44
45         if (value > 20 && value < 32767)
46                 count = 1193182 / value;
47
48         spin_lock_irqsave(&state->lock, flags);
49
50         /* EBUS speaker only has on/off state, the frequency does not
51          * appear to be programmable.
52          */
53         if (state->iobase & 0x2UL)
54                 outb(!!count, state->iobase);
55         else
56                 outl(!!count, state->iobase);
57
58         spin_unlock_irqrestore(&state->lock, flags);
59
60         return 0;
61 }
62
63 static int isa_spkr_event(struct input_dev *dev, unsigned int type, unsigned int code, int value)
64 {
65         struct sparcspkr_state *state = dev_get_drvdata(dev->cdev.dev);
66         unsigned int count = 0;
67         unsigned long flags;
68
69         if (type != EV_SND)
70                 return -1;
71
72         switch (code) {
73                 case SND_BELL: if (value) value = 1000;
74                 case SND_TONE: break;
75                 default: return -1;
76         }
77
78         if (value > 20 && value < 32767)
79                 count = 1193182 / value;
80
81         spin_lock_irqsave(&state->lock, flags);
82
83         if (count) {
84                 /* enable counter 2 */
85                 outb(inb(state->iobase + 0x61) | 3, state->iobase + 0x61);
86                 /* set command for counter 2, 2 byte write */
87                 outb(0xB6, state->iobase + 0x43);
88                 /* select desired HZ */
89                 outb(count & 0xff, state->iobase + 0x42);
90                 outb((count >> 8) & 0xff, state->iobase + 0x42);
91         } else {
92                 /* disable counter 2 */
93                 outb(inb_p(state->iobase + 0x61) & 0xFC, state->iobase + 0x61);
94         }
95
96         spin_unlock_irqrestore(&state->lock, flags);
97
98         return 0;
99 }
100
101 static int __devinit sparcspkr_probe(struct device *dev)
102 {
103         struct sparcspkr_state *state = dev_get_drvdata(dev);
104         struct input_dev *input_dev;
105         int error;
106
107         input_dev = input_allocate_device();
108         if (!input_dev)
109                 return -ENOMEM;
110
111         input_dev->name = state->name;
112         input_dev->phys = "sparc/input0";
113         input_dev->id.bustype = BUS_ISA;
114         input_dev->id.vendor = 0x001f;
115         input_dev->id.product = 0x0001;
116         input_dev->id.version = 0x0100;
117         input_dev->cdev.dev = dev;
118
119         input_dev->evbit[0] = BIT(EV_SND);
120         input_dev->sndbit[0] = BIT(SND_BELL) | BIT(SND_TONE);
121
122         input_dev->event = state->event;
123
124         error = input_register_device(input_dev);
125         if (error) {
126                 input_free_device(input_dev);
127                 return error;
128         }
129
130         state->input_dev = input_dev;
131
132         return 0;
133 }
134
135 static int __devexit sparcspkr_remove(struct of_device *dev)
136 {
137         struct sparcspkr_state *state = dev_get_drvdata(&dev->dev);
138         struct input_dev *input_dev = state->input_dev;
139
140         /* turn off the speaker */
141         state->event(input_dev, EV_SND, SND_BELL, 0);
142
143         input_unregister_device(input_dev);
144
145         dev_set_drvdata(&dev->dev, NULL);
146         kfree(state);
147
148         return 0;
149 }
150
151 static int sparcspkr_shutdown(struct of_device *dev)
152 {
153         struct sparcspkr_state *state = dev_get_drvdata(&dev->dev);
154         struct input_dev *input_dev = state->input_dev;
155
156         /* turn off the speaker */
157         state->event(input_dev, EV_SND, SND_BELL, 0);
158
159         return 0;
160 }
161
162 static int __devinit ebus_beep_probe(struct of_device *dev, const struct of_device_id *match)
163 {
164         struct linux_ebus_device *edev = to_ebus_device(&dev->dev);
165         struct sparcspkr_state *state;
166         int err;
167
168         state = kzalloc(sizeof(*state), GFP_KERNEL);
169         if (!state)
170                 return -ENOMEM;
171
172         state->name = "Sparc EBUS Speaker";
173         state->iobase = edev->resource[0].start;
174         state->event = ebus_spkr_event;
175         spin_lock_init(&state->lock);
176
177         dev_set_drvdata(&dev->dev, state);
178
179         err = sparcspkr_probe(&dev->dev);
180         if (err) {
181                 dev_set_drvdata(&dev->dev, NULL);
182                 kfree(state);
183         }
184
185         return 0;
186 }
187
188 static struct of_device_id ebus_beep_match[] = {
189         {
190                 .name = "beep",
191         },
192         {},
193 };
194
195 static struct of_platform_driver ebus_beep_driver = {
196         .name           = "beep",
197         .match_table    = ebus_beep_match,
198         .probe          = ebus_beep_probe,
199         .remove         = sparcspkr_remove,
200         .shutdown       = sparcspkr_shutdown,
201 };
202
203 static int __devinit isa_beep_probe(struct of_device *dev, const struct of_device_id *match)
204 {
205         struct sparc_isa_device *idev = to_isa_device(&dev->dev);
206         struct sparcspkr_state *state;
207         int err;
208
209         state = kzalloc(sizeof(*state), GFP_KERNEL);
210         if (!state)
211                 return -ENOMEM;
212
213         state->name = "Sparc ISA Speaker";
214         state->iobase = idev->resource.start;
215         state->event = isa_spkr_event;
216         spin_lock_init(&state->lock);
217
218         dev_set_drvdata(&dev->dev, state);
219
220         err = sparcspkr_probe(&dev->dev);
221         if (err) {
222                 dev_set_drvdata(&dev->dev, NULL);
223                 kfree(state);
224         }
225
226         return 0;
227 }
228
229 static struct of_device_id isa_beep_match[] = {
230         {
231                 .name = "dma",
232         },
233         {},
234 };
235
236 static struct of_platform_driver isa_beep_driver = {
237         .name           = "beep",
238         .match_table    = isa_beep_match,
239         .probe          = isa_beep_probe,
240         .remove         = sparcspkr_remove,
241         .shutdown       = sparcspkr_shutdown,
242 };
243
244 static int __init sparcspkr_init(void)
245 {
246         int err = of_register_driver(&ebus_beep_driver, &ebus_bus_type);
247
248         if (!err) {
249                 err = of_register_driver(&isa_beep_driver, &isa_bus_type);
250                 if (err)
251                         of_unregister_driver(&ebus_beep_driver);
252         }
253
254         return err;
255 }
256
257 static void __exit sparcspkr_exit(void)
258 {
259         of_unregister_driver(&ebus_beep_driver);
260         of_unregister_driver(&isa_beep_driver);
261 }
262
263 module_init(sparcspkr_init);
264 module_exit(sparcspkr_exit);