xref: /linux/drivers/input/misc/sparcspkr.c (revision 5e8d780d745c1619aba81fe7166c5a4b5cad2b84)
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);
265