sparcspkr.c revision a2bd4fd17926d715a470fbe0ebe05128ba410984
11da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
21da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *  Driver for PC-speaker like devices found on various Sparc systems.
31da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
41da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *  Copyright (c) 2002 Vojtech Pavlik
5a2bd4fd17926d715a470fbe0ebe05128ba410984David S. Miller *  Copyright (c) 2002, 2006 David S. Miller (davem@davemloft.net)
61da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
71da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/config.h>
81da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/kernel.h>
91da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/module.h>
101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/init.h>
111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/input.h>
12f5b64078d75528f36b78d30e945bb1b05cb05f26Dmitry Torokhov#include <linux/platform_device.h>
131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <asm/io.h>
151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <asm/ebus.h>
161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <asm/isa.h>
171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
18a2bd4fd17926d715a470fbe0ebe05128ba410984David S. MillerMODULE_AUTHOR("David S. Miller <davem@davemloft.net>");
1976b7cddfd576331761e945a508254abad11039e9Dmitry TorokhovMODULE_DESCRIPTION("Sparc Speaker beeper driver");
201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_LICENSE("GPL");
211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
22a2bd4fd17926d715a470fbe0ebe05128ba410984David S. Millerstruct sparcspkr_state {
23a2bd4fd17926d715a470fbe0ebe05128ba410984David S. Miller	const char		*name;
24a2bd4fd17926d715a470fbe0ebe05128ba410984David S. Miller	unsigned long		iobase;
25a2bd4fd17926d715a470fbe0ebe05128ba410984David S. Miller	int (*event)(struct input_dev *dev, unsigned int type, unsigned int code, int value);
26a2bd4fd17926d715a470fbe0ebe05128ba410984David S. Miller	spinlock_t		lock;
27a2bd4fd17926d715a470fbe0ebe05128ba410984David S. Miller	struct input_dev	*input_dev;
28a2bd4fd17926d715a470fbe0ebe05128ba410984David S. Miller};
291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int ebus_spkr_event(struct input_dev *dev, unsigned int type, unsigned int code, int value)
311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
32a2bd4fd17926d715a470fbe0ebe05128ba410984David S. Miller	struct sparcspkr_state *state = dev_get_drvdata(dev->cdev.dev);
331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unsigned int count = 0;
341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unsigned long flags;
351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (type != EV_SND)
371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return -1;
381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	switch (code) {
401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		case SND_BELL: if (value) value = 1000;
411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		case SND_TONE: break;
421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		default: return -1;
431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (value > 20 && value < 32767)
461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		count = 1193182 / value;
471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
48a2bd4fd17926d715a470fbe0ebe05128ba410984David S. Miller	spin_lock_irqsave(&state->lock, flags);
491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* EBUS speaker only has on/off state, the frequency does not
511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * appear to be programmable.
521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 */
53a2bd4fd17926d715a470fbe0ebe05128ba410984David S. Miller	if (state->iobase & 0x2UL)
54a2bd4fd17926d715a470fbe0ebe05128ba410984David S. Miller		outb(!!count, state->iobase);
55f5b64078d75528f36b78d30e945bb1b05cb05f26Dmitry Torokhov	else
56a2bd4fd17926d715a470fbe0ebe05128ba410984David S. Miller		outl(!!count, state->iobase);
571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
58a2bd4fd17926d715a470fbe0ebe05128ba410984David S. Miller	spin_unlock_irqrestore(&state->lock, flags);
591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return 0;
611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int isa_spkr_event(struct input_dev *dev, unsigned int type, unsigned int code, int value)
641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
65a2bd4fd17926d715a470fbe0ebe05128ba410984David S. Miller	struct sparcspkr_state *state = dev_get_drvdata(dev->cdev.dev);
661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unsigned int count = 0;
671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unsigned long flags;
681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (type != EV_SND)
701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return -1;
711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	switch (code) {
731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		case SND_BELL: if (value) value = 1000;
741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		case SND_TONE: break;
751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		default: return -1;
761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (value > 20 && value < 32767)
791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		count = 1193182 / value;
801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
81a2bd4fd17926d715a470fbe0ebe05128ba410984David S. Miller	spin_lock_irqsave(&state->lock, flags);
821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (count) {
841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/* enable counter 2 */
85a2bd4fd17926d715a470fbe0ebe05128ba410984David S. Miller		outb(inb(state->iobase + 0x61) | 3, state->iobase + 0x61);
861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/* set command for counter 2, 2 byte write */
87a2bd4fd17926d715a470fbe0ebe05128ba410984David S. Miller		outb(0xB6, state->iobase + 0x43);
881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/* select desired HZ */
89a2bd4fd17926d715a470fbe0ebe05128ba410984David S. Miller		outb(count & 0xff, state->iobase + 0x42);
90a2bd4fd17926d715a470fbe0ebe05128ba410984David S. Miller		outb((count >> 8) & 0xff, state->iobase + 0x42);
911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	} else {
921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/* disable counter 2 */
93a2bd4fd17926d715a470fbe0ebe05128ba410984David S. Miller		outb(inb_p(state->iobase + 0x61) & 0xFC, state->iobase + 0x61);
941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
96a2bd4fd17926d715a470fbe0ebe05128ba410984David S. Miller	spin_unlock_irqrestore(&state->lock, flags);
971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return 0;
991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
1001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
101a2bd4fd17926d715a470fbe0ebe05128ba410984David S. Millerstatic int __devinit sparcspkr_probe(struct device *dev)
1021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
103a2bd4fd17926d715a470fbe0ebe05128ba410984David S. Miller	struct sparcspkr_state *state = dev_get_drvdata(dev);
104f5b64078d75528f36b78d30e945bb1b05cb05f26Dmitry Torokhov	struct input_dev *input_dev;
105f5b64078d75528f36b78d30e945bb1b05cb05f26Dmitry Torokhov	int error;
1061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
107f5b64078d75528f36b78d30e945bb1b05cb05f26Dmitry Torokhov	input_dev = input_allocate_device();
108f5b64078d75528f36b78d30e945bb1b05cb05f26Dmitry Torokhov	if (!input_dev)
10976b7cddfd576331761e945a508254abad11039e9Dmitry Torokhov		return -ENOMEM;
11076b7cddfd576331761e945a508254abad11039e9Dmitry Torokhov
111a2bd4fd17926d715a470fbe0ebe05128ba410984David S. Miller	input_dev->name = state->name;
112f5b64078d75528f36b78d30e945bb1b05cb05f26Dmitry Torokhov	input_dev->phys = "sparc/input0";
113f5b64078d75528f36b78d30e945bb1b05cb05f26Dmitry Torokhov	input_dev->id.bustype = BUS_ISA;
114f5b64078d75528f36b78d30e945bb1b05cb05f26Dmitry Torokhov	input_dev->id.vendor = 0x001f;
115f5b64078d75528f36b78d30e945bb1b05cb05f26Dmitry Torokhov	input_dev->id.product = 0x0001;
116f5b64078d75528f36b78d30e945bb1b05cb05f26Dmitry Torokhov	input_dev->id.version = 0x0100;
117a2bd4fd17926d715a470fbe0ebe05128ba410984David S. Miller	input_dev->cdev.dev = dev;
1181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
119f5b64078d75528f36b78d30e945bb1b05cb05f26Dmitry Torokhov	input_dev->evbit[0] = BIT(EV_SND);
120f5b64078d75528f36b78d30e945bb1b05cb05f26Dmitry Torokhov	input_dev->sndbit[0] = BIT(SND_BELL) | BIT(SND_TONE);
1211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
122a2bd4fd17926d715a470fbe0ebe05128ba410984David S. Miller	input_dev->event = state->event;
123f5b64078d75528f36b78d30e945bb1b05cb05f26Dmitry Torokhov
124f5b64078d75528f36b78d30e945bb1b05cb05f26Dmitry Torokhov	error = input_register_device(input_dev);
125f5b64078d75528f36b78d30e945bb1b05cb05f26Dmitry Torokhov	if (error) {
126f5b64078d75528f36b78d30e945bb1b05cb05f26Dmitry Torokhov		input_free_device(input_dev);
127f5b64078d75528f36b78d30e945bb1b05cb05f26Dmitry Torokhov		return error;
128f5b64078d75528f36b78d30e945bb1b05cb05f26Dmitry Torokhov	}
129f5b64078d75528f36b78d30e945bb1b05cb05f26Dmitry Torokhov
130a2bd4fd17926d715a470fbe0ebe05128ba410984David S. Miller	state->input_dev = input_dev;
1311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return 0;
1331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
134f5b64078d75528f36b78d30e945bb1b05cb05f26Dmitry Torokhov
135a2bd4fd17926d715a470fbe0ebe05128ba410984David S. Millerstatic int __devexit sparcspkr_remove(struct of_device *dev)
136f5b64078d75528f36b78d30e945bb1b05cb05f26Dmitry Torokhov{
137a2bd4fd17926d715a470fbe0ebe05128ba410984David S. Miller	struct sparcspkr_state *state = dev_get_drvdata(&dev->dev);
138a2bd4fd17926d715a470fbe0ebe05128ba410984David S. Miller	struct input_dev *input_dev = state->input_dev;
139f5b64078d75528f36b78d30e945bb1b05cb05f26Dmitry Torokhov
140f5b64078d75528f36b78d30e945bb1b05cb05f26Dmitry Torokhov	/* turn off the speaker */
141a2bd4fd17926d715a470fbe0ebe05128ba410984David S. Miller	state->event(input_dev, EV_SND, SND_BELL, 0);
142a2bd4fd17926d715a470fbe0ebe05128ba410984David S. Miller
143a2bd4fd17926d715a470fbe0ebe05128ba410984David S. Miller	input_unregister_device(input_dev);
144a2bd4fd17926d715a470fbe0ebe05128ba410984David S. Miller
145a2bd4fd17926d715a470fbe0ebe05128ba410984David S. Miller	dev_set_drvdata(&dev->dev, NULL);
146a2bd4fd17926d715a470fbe0ebe05128ba410984David S. Miller	kfree(state);
147f5b64078d75528f36b78d30e945bb1b05cb05f26Dmitry Torokhov
148f5b64078d75528f36b78d30e945bb1b05cb05f26Dmitry Torokhov	return 0;
149f5b64078d75528f36b78d30e945bb1b05cb05f26Dmitry Torokhov}
150f5b64078d75528f36b78d30e945bb1b05cb05f26Dmitry Torokhov
151a2bd4fd17926d715a470fbe0ebe05128ba410984David S. Millerstatic int sparcspkr_shutdown(struct of_device *dev)
152f5b64078d75528f36b78d30e945bb1b05cb05f26Dmitry Torokhov{
153a2bd4fd17926d715a470fbe0ebe05128ba410984David S. Miller	struct sparcspkr_state *state = dev_get_drvdata(&dev->dev);
154a2bd4fd17926d715a470fbe0ebe05128ba410984David S. Miller	struct input_dev *input_dev = state->input_dev;
155a2bd4fd17926d715a470fbe0ebe05128ba410984David S. Miller
156f5b64078d75528f36b78d30e945bb1b05cb05f26Dmitry Torokhov	/* turn off the speaker */
157a2bd4fd17926d715a470fbe0ebe05128ba410984David S. Miller	state->event(input_dev, EV_SND, SND_BELL, 0);
158a2bd4fd17926d715a470fbe0ebe05128ba410984David S. Miller
159a2bd4fd17926d715a470fbe0ebe05128ba410984David S. Miller	return 0;
160a2bd4fd17926d715a470fbe0ebe05128ba410984David S. Miller}
161a2bd4fd17926d715a470fbe0ebe05128ba410984David S. Miller
162a2bd4fd17926d715a470fbe0ebe05128ba410984David S. Millerstatic int __devinit ebus_beep_probe(struct of_device *dev, const struct of_device_id *match)
163a2bd4fd17926d715a470fbe0ebe05128ba410984David S. Miller{
164a2bd4fd17926d715a470fbe0ebe05128ba410984David S. Miller	struct linux_ebus_device *edev = to_ebus_device(&dev->dev);
165a2bd4fd17926d715a470fbe0ebe05128ba410984David S. Miller	struct sparcspkr_state *state;
166a2bd4fd17926d715a470fbe0ebe05128ba410984David S. Miller	int err;
167a2bd4fd17926d715a470fbe0ebe05128ba410984David S. Miller
168a2bd4fd17926d715a470fbe0ebe05128ba410984David S. Miller	state = kzalloc(sizeof(*state), GFP_KERNEL);
169a2bd4fd17926d715a470fbe0ebe05128ba410984David S. Miller	if (!state)
170a2bd4fd17926d715a470fbe0ebe05128ba410984David S. Miller		return -ENOMEM;
171a2bd4fd17926d715a470fbe0ebe05128ba410984David S. Miller
172a2bd4fd17926d715a470fbe0ebe05128ba410984David S. Miller	state->name = "Sparc EBUS Speaker";
173a2bd4fd17926d715a470fbe0ebe05128ba410984David S. Miller	state->iobase = edev->resource[0].start;
174a2bd4fd17926d715a470fbe0ebe05128ba410984David S. Miller	state->event = ebus_spkr_event;
175a2bd4fd17926d715a470fbe0ebe05128ba410984David S. Miller	spin_lock_init(&state->lock);
176a2bd4fd17926d715a470fbe0ebe05128ba410984David S. Miller
177a2bd4fd17926d715a470fbe0ebe05128ba410984David S. Miller	dev_set_drvdata(&dev->dev, state);
178a2bd4fd17926d715a470fbe0ebe05128ba410984David S. Miller
179a2bd4fd17926d715a470fbe0ebe05128ba410984David S. Miller	err = sparcspkr_probe(&dev->dev);
180a2bd4fd17926d715a470fbe0ebe05128ba410984David S. Miller	if (err) {
181a2bd4fd17926d715a470fbe0ebe05128ba410984David S. Miller		dev_set_drvdata(&dev->dev, NULL);
182a2bd4fd17926d715a470fbe0ebe05128ba410984David S. Miller		kfree(state);
183a2bd4fd17926d715a470fbe0ebe05128ba410984David S. Miller	}
184a2bd4fd17926d715a470fbe0ebe05128ba410984David S. Miller
185a2bd4fd17926d715a470fbe0ebe05128ba410984David S. Miller	return 0;
186f5b64078d75528f36b78d30e945bb1b05cb05f26Dmitry Torokhov}
187f5b64078d75528f36b78d30e945bb1b05cb05f26Dmitry Torokhov
188a2bd4fd17926d715a470fbe0ebe05128ba410984David S. Millerstatic struct of_device_id ebus_beep_match[] = {
189a2bd4fd17926d715a470fbe0ebe05128ba410984David S. Miller	{
190a2bd4fd17926d715a470fbe0ebe05128ba410984David S. Miller		.name = "beep",
191f5b64078d75528f36b78d30e945bb1b05cb05f26Dmitry Torokhov	},
192a2bd4fd17926d715a470fbe0ebe05128ba410984David S. Miller	{},
193f5b64078d75528f36b78d30e945bb1b05cb05f26Dmitry Torokhov};
194f5b64078d75528f36b78d30e945bb1b05cb05f26Dmitry Torokhov
195a2bd4fd17926d715a470fbe0ebe05128ba410984David S. Millerstatic struct of_platform_driver ebus_beep_driver = {
196a2bd4fd17926d715a470fbe0ebe05128ba410984David S. Miller	.name		= "beep",
197a2bd4fd17926d715a470fbe0ebe05128ba410984David S. Miller	.match_table	= ebus_beep_match,
198a2bd4fd17926d715a470fbe0ebe05128ba410984David S. Miller	.probe		= ebus_beep_probe,
199a2bd4fd17926d715a470fbe0ebe05128ba410984David S. Miller	.remove		= sparcspkr_remove,
200a2bd4fd17926d715a470fbe0ebe05128ba410984David S. Miller	.shutdown	= sparcspkr_shutdown,
201a2bd4fd17926d715a470fbe0ebe05128ba410984David S. Miller};
202f5b64078d75528f36b78d30e945bb1b05cb05f26Dmitry Torokhov
203a2bd4fd17926d715a470fbe0ebe05128ba410984David S. Millerstatic int __devinit isa_beep_probe(struct of_device *dev, const struct of_device_id *match)
204f5b64078d75528f36b78d30e945bb1b05cb05f26Dmitry Torokhov{
205a2bd4fd17926d715a470fbe0ebe05128ba410984David S. Miller	struct sparc_isa_device *idev = to_isa_device(&dev->dev);
206a2bd4fd17926d715a470fbe0ebe05128ba410984David S. Miller	struct sparcspkr_state *state;
207a2bd4fd17926d715a470fbe0ebe05128ba410984David S. Miller	int err;
208f5b64078d75528f36b78d30e945bb1b05cb05f26Dmitry Torokhov
209a2bd4fd17926d715a470fbe0ebe05128ba410984David S. Miller	state = kzalloc(sizeof(*state), GFP_KERNEL);
210a2bd4fd17926d715a470fbe0ebe05128ba410984David S. Miller	if (!state)
211a2bd4fd17926d715a470fbe0ebe05128ba410984David S. Miller		return -ENOMEM;
212f5b64078d75528f36b78d30e945bb1b05cb05f26Dmitry Torokhov
213a2bd4fd17926d715a470fbe0ebe05128ba410984David S. Miller	state->name = "Sparc ISA Speaker";
214a2bd4fd17926d715a470fbe0ebe05128ba410984David S. Miller	state->iobase = idev->resource.start;
215a2bd4fd17926d715a470fbe0ebe05128ba410984David S. Miller	state->event = isa_spkr_event;
216a2bd4fd17926d715a470fbe0ebe05128ba410984David S. Miller	spin_lock_init(&state->lock);
217a2bd4fd17926d715a470fbe0ebe05128ba410984David S. Miller
218a2bd4fd17926d715a470fbe0ebe05128ba410984David S. Miller	dev_set_drvdata(&dev->dev, state);
219f5b64078d75528f36b78d30e945bb1b05cb05f26Dmitry Torokhov
220a2bd4fd17926d715a470fbe0ebe05128ba410984David S. Miller	err = sparcspkr_probe(&dev->dev);
221a2bd4fd17926d715a470fbe0ebe05128ba410984David S. Miller	if (err) {
222a2bd4fd17926d715a470fbe0ebe05128ba410984David S. Miller		dev_set_drvdata(&dev->dev, NULL);
223a2bd4fd17926d715a470fbe0ebe05128ba410984David S. Miller		kfree(state);
224a2bd4fd17926d715a470fbe0ebe05128ba410984David S. Miller	}
225f5b64078d75528f36b78d30e945bb1b05cb05f26Dmitry Torokhov
226f5b64078d75528f36b78d30e945bb1b05cb05f26Dmitry Torokhov	return 0;
227a2bd4fd17926d715a470fbe0ebe05128ba410984David S. Miller}
228f5b64078d75528f36b78d30e945bb1b05cb05f26Dmitry Torokhov
229a2bd4fd17926d715a470fbe0ebe05128ba410984David S. Millerstatic struct of_device_id isa_beep_match[] = {
230a2bd4fd17926d715a470fbe0ebe05128ba410984David S. Miller	{
231a2bd4fd17926d715a470fbe0ebe05128ba410984David S. Miller		.name = "dma",
232a2bd4fd17926d715a470fbe0ebe05128ba410984David S. Miller	},
233a2bd4fd17926d715a470fbe0ebe05128ba410984David S. Miller	{},
234a2bd4fd17926d715a470fbe0ebe05128ba410984David S. Miller};
235f5b64078d75528f36b78d30e945bb1b05cb05f26Dmitry Torokhov
236a2bd4fd17926d715a470fbe0ebe05128ba410984David S. Millerstatic struct of_platform_driver isa_beep_driver = {
237a2bd4fd17926d715a470fbe0ebe05128ba410984David S. Miller	.name		= "beep",
238a2bd4fd17926d715a470fbe0ebe05128ba410984David S. Miller	.match_table	= isa_beep_match,
239a2bd4fd17926d715a470fbe0ebe05128ba410984David S. Miller	.probe		= isa_beep_probe,
240a2bd4fd17926d715a470fbe0ebe05128ba410984David S. Miller	.remove		= sparcspkr_remove,
241a2bd4fd17926d715a470fbe0ebe05128ba410984David S. Miller	.shutdown	= sparcspkr_shutdown,
242a2bd4fd17926d715a470fbe0ebe05128ba410984David S. Miller};
2431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int __init sparcspkr_init(void)
2451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
246a2bd4fd17926d715a470fbe0ebe05128ba410984David S. Miller	int err = of_register_driver(&ebus_beep_driver, &ebus_bus_type);
247a2bd4fd17926d715a470fbe0ebe05128ba410984David S. Miller
248a2bd4fd17926d715a470fbe0ebe05128ba410984David S. Miller	if (!err) {
249a2bd4fd17926d715a470fbe0ebe05128ba410984David S. Miller		err = of_register_driver(&isa_beep_driver, &isa_bus_type);
250a2bd4fd17926d715a470fbe0ebe05128ba410984David S. Miller		if (err)
251a2bd4fd17926d715a470fbe0ebe05128ba410984David S. Miller			of_unregister_driver(&ebus_beep_driver);
2521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
2531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
254a2bd4fd17926d715a470fbe0ebe05128ba410984David S. Miller	return err;
2551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
2561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void __exit sparcspkr_exit(void)
2581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
259a2bd4fd17926d715a470fbe0ebe05128ba410984David S. Miller	of_unregister_driver(&ebus_beep_driver);
260a2bd4fd17926d715a470fbe0ebe05128ba410984David S. Miller	of_unregister_driver(&isa_beep_driver);
2611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
2621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmodule_init(sparcspkr_init);
2641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmodule_exit(sparcspkr_exit);
265