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