]> pilppa.org Git - linux-2.6-omap-h63xx.git/blob - drivers/input/misc/sparcspkr.c
Merge branch 'master'
[linux-2.6-omap-h63xx.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 David S. Miller (davem@redhat.com)
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
13 #include <asm/io.h>
14 #include <asm/ebus.h>
15 #ifdef CONFIG_SPARC64
16 #include <asm/isa.h>
17 #endif
18
19 MODULE_AUTHOR("David S. Miller <davem@redhat.com>");
20 MODULE_DESCRIPTION("Sparc Speaker beeper driver");
21 MODULE_LICENSE("GPL");
22
23 static unsigned long beep_iobase;
24 static struct input_dev *sparcspkr_dev;
25
26 DEFINE_SPINLOCK(beep_lock);
27
28 static void __init init_sparcspkr_struct(void)
29 {
30         sparcspkr_dev->evbit[0] = BIT(EV_SND);
31         sparcspkr_dev->sndbit[0] = BIT(SND_BELL) | BIT(SND_TONE);
32
33         sparcspkr_dev->phys = "sparc/input0";
34         sparcspkr_dev->id.bustype = BUS_ISA;
35         sparcspkr_dev->id.vendor = 0x001f;
36         sparcspkr_dev->id.product = 0x0001;
37         sparcspkr_dev->id.version = 0x0100;
38 }
39
40 static int ebus_spkr_event(struct input_dev *dev, unsigned int type, unsigned int code, int value)
41 {
42         unsigned int count = 0;
43         unsigned long flags;
44
45         if (type != EV_SND)
46                 return -1;
47
48         switch (code) {
49                 case SND_BELL: if (value) value = 1000;
50                 case SND_TONE: break;
51                 default: return -1;
52         }
53
54         if (value > 20 && value < 32767)
55                 count = 1193182 / value;
56
57         spin_lock_irqsave(&beep_lock, flags);
58
59         /* EBUS speaker only has on/off state, the frequency does not
60          * appear to be programmable.
61          */
62         if (count) {
63                 if (beep_iobase & 0x2UL)
64                         outb(1, beep_iobase);
65                 else
66                         outl(1, beep_iobase);
67         } else {
68                 if (beep_iobase & 0x2UL)
69                         outb(0, beep_iobase);
70                 else
71                         outl(0, beep_iobase);
72         }
73
74         spin_unlock_irqrestore(&beep_lock, flags);
75
76         return 0;
77 }
78
79 static int __init init_ebus_beep(struct linux_ebus_device *edev)
80 {
81         beep_iobase = edev->resource[0].start;
82
83         sparcspkr_dev = input_allocate_device();
84         if (!sparcspkr_dev)
85                 return -ENOMEM;
86
87         sparcspkr_dev->name = "Sparc EBUS Speaker";
88         sparcspkr_dev->event = ebus_spkr_event;
89
90         input_register_device(sparcspkr_dev);
91
92         return 0;
93 }
94
95 #ifdef CONFIG_SPARC64
96 static int isa_spkr_event(struct input_dev *dev, unsigned int type, unsigned int code, int value)
97 {
98         unsigned int count = 0;
99         unsigned long flags;
100
101         if (type != EV_SND)
102                 return -1;
103
104         switch (code) {
105                 case SND_BELL: if (value) value = 1000;
106                 case SND_TONE: break;
107                 default: return -1;
108         }
109
110         if (value > 20 && value < 32767)
111                 count = 1193182 / value;
112
113         spin_lock_irqsave(&beep_lock, flags);
114
115         if (count) {
116                 /* enable counter 2 */
117                 outb(inb(beep_iobase + 0x61) | 3, beep_iobase + 0x61);
118                 /* set command for counter 2, 2 byte write */
119                 outb(0xB6, beep_iobase + 0x43);
120                 /* select desired HZ */
121                 outb(count & 0xff, beep_iobase + 0x42);
122                 outb((count >> 8) & 0xff, beep_iobase + 0x42);
123         } else {
124                 /* disable counter 2 */
125                 outb(inb_p(beep_iobase + 0x61) & 0xFC, beep_iobase + 0x61);
126         }
127
128         spin_unlock_irqrestore(&beep_lock, flags);
129
130         return 0;
131 }
132
133 static int __init init_isa_beep(struct sparc_isa_device *isa_dev)
134 {
135         beep_iobase = isa_dev->resource.start;
136
137         sparcspkr_dev = input_allocate_device();
138         if (!sparcspkr_dev)
139                 return -ENOMEM;
140
141         init_sparcspkr_struct();
142
143         sparcspkr_dev->name = "Sparc ISA Speaker";
144         sparcspkr_dev->event = isa_spkr_event;
145
146         input_register_device(sparcspkr_dev);
147
148         return 0;
149 }
150 #endif
151
152 static int __init sparcspkr_init(void)
153 {
154         struct linux_ebus *ebus;
155         struct linux_ebus_device *edev = NULL;
156 #ifdef CONFIG_SPARC64
157         struct sparc_isa_bridge *isa_br;
158         struct sparc_isa_device *isa_dev;
159 #endif
160
161         for_each_ebus(ebus) {
162                 for_each_ebusdev(edev, ebus) {
163                         if (!strcmp(edev->prom_name, "beep"))
164                                 return init_ebus_beep(edev);
165                 }
166         }
167 #ifdef CONFIG_SPARC64
168         for_each_isa(isa_br) {
169                 for_each_isadev(isa_dev, isa_br) {
170                         /* A hack, the beep device's base lives in
171                          * the DMA isa node.
172                          */
173                         if (!strcmp(isa_dev->prom_name, "dma"))
174                                 return init_isa_beep(isa_dev);
175                 }
176         }
177 #endif
178
179         return -ENODEV;
180 }
181
182 static void __exit sparcspkr_exit(void)
183 {
184         input_unregister_device(sparcspkr_dev);
185 }
186
187 module_init(sparcspkr_init);
188 module_exit(sparcspkr_exit);