diff options
author | Linus Torvalds <torvalds@ppc970.osdl.org> | 2005-04-16 18:20:36 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@ppc970.osdl.org> | 2005-04-16 18:20:36 -0400 |
commit | 1da177e4c3f41524e886b7f1b8a0c1fc7321cac2 (patch) | |
tree | 0bba044c4ce775e45a88a51686b5d9f90697ea9d /sound/oss/kahlua.c |
Linux-2.6.12-rc2v2.6.12-rc2
Initial git repository build. I'm not bothering with the full history,
even though we have it. We can create a separate "historical" git
archive of that later if we want to, and in the meantime it's about
3.2GB when imported into git - space that would just make the early
git days unnecessarily complicated, when we don't have a lot of good
infrastructure for it.
Let it rip!
Diffstat (limited to 'sound/oss/kahlua.c')
-rw-r--r-- | sound/oss/kahlua.c | 232 |
1 files changed, 232 insertions, 0 deletions
diff --git a/sound/oss/kahlua.c b/sound/oss/kahlua.c new file mode 100644 index 000000000000..808c5ef969be --- /dev/null +++ b/sound/oss/kahlua.c | |||
@@ -0,0 +1,232 @@ | |||
1 | /* | ||
2 | * Initialisation code for Cyrix/NatSemi VSA1 softaudio | ||
3 | * | ||
4 | * (C) Copyright 2003 Red Hat Inc <alan@redhat.com> | ||
5 | * | ||
6 | * XpressAudio(tm) is used on the Cyrix MediaGX (now NatSemi Geode) systems. | ||
7 | * The older version (VSA1) provides fairly good soundblaster emulation | ||
8 | * although there are a couple of bugs: large DMA buffers break record, | ||
9 | * and the MPU event handling seems suspect. VSA2 allows the native driver | ||
10 | * to control the AC97 audio engine directly and requires a different driver. | ||
11 | * | ||
12 | * Thanks to National Semiconductor for providing the needed information | ||
13 | * on the XpressAudio(tm) internals. | ||
14 | * | ||
15 | * This program is free software; you can redistribute it and/or modify it | ||
16 | * under the terms of the GNU General Public License as published by the | ||
17 | * Free Software Foundation; either version 2, or (at your option) any | ||
18 | * later version. | ||
19 | * | ||
20 | * This program is distributed in the hope that it will be useful, but | ||
21 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
22 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
23 | * General Public License for more details. | ||
24 | * | ||
25 | * TO DO: | ||
26 | * Investigate whether we can portably support Cognac (5520) in the | ||
27 | * same manner. | ||
28 | */ | ||
29 | |||
30 | #include <linux/config.h> | ||
31 | #include <linux/delay.h> | ||
32 | #include <linux/init.h> | ||
33 | #include <linux/module.h> | ||
34 | #include <linux/pci.h> | ||
35 | |||
36 | #include "sound_config.h" | ||
37 | |||
38 | #include "sb.h" | ||
39 | |||
40 | /* | ||
41 | * Read a soundblaster compatible mixer register. | ||
42 | * In this case we are actually reading an SMI trap | ||
43 | * not real hardware. | ||
44 | */ | ||
45 | |||
46 | static u8 __devinit mixer_read(unsigned long io, u8 reg) | ||
47 | { | ||
48 | outb(reg, io + 4); | ||
49 | udelay(20); | ||
50 | reg = inb(io + 5); | ||
51 | udelay(20); | ||
52 | return reg; | ||
53 | } | ||
54 | |||
55 | static int __devinit probe_one(struct pci_dev *pdev, const struct pci_device_id *ent) | ||
56 | { | ||
57 | struct address_info *hw_config; | ||
58 | unsigned long base; | ||
59 | void __iomem *mem; | ||
60 | unsigned long io; | ||
61 | u16 map; | ||
62 | u8 irq, dma8, dma16; | ||
63 | int oldquiet; | ||
64 | extern int sb_be_quiet; | ||
65 | |||
66 | base = pci_resource_start(pdev, 0); | ||
67 | if(base == 0UL) | ||
68 | return 1; | ||
69 | |||
70 | mem = ioremap(base, 128); | ||
71 | if(mem == 0UL) | ||
72 | return 1; | ||
73 | map = readw(mem + 0x18); /* Read the SMI enables */ | ||
74 | iounmap(mem); | ||
75 | |||
76 | /* Map bits | ||
77 | 0:1 * 0x20 + 0x200 = sb base | ||
78 | 2 sb enable | ||
79 | 3 adlib enable | ||
80 | 5 MPU enable 0x330 | ||
81 | 6 MPU enable 0x300 | ||
82 | |||
83 | The other bits may be used internally so must be masked */ | ||
84 | |||
85 | io = 0x220 + 0x20 * (map & 3); | ||
86 | |||
87 | if(map & (1<<2)) | ||
88 | printk(KERN_INFO "kahlua: XpressAudio at 0x%lx\n", io); | ||
89 | else | ||
90 | return 1; | ||
91 | |||
92 | if(map & (1<<5)) | ||
93 | printk(KERN_INFO "kahlua: MPU at 0x300\n"); | ||
94 | else if(map & (1<<6)) | ||
95 | printk(KERN_INFO "kahlua: MPU at 0x330\n"); | ||
96 | |||
97 | irq = mixer_read(io, 0x80) & 0x0F; | ||
98 | dma8 = mixer_read(io, 0x81); | ||
99 | |||
100 | // printk("IRQ=%x MAP=%x DMA=%x\n", irq, map, dma8); | ||
101 | |||
102 | if(dma8 & 0x20) | ||
103 | dma16 = 5; | ||
104 | else if(dma8 & 0x40) | ||
105 | dma16 = 6; | ||
106 | else if(dma8 & 0x80) | ||
107 | dma16 = 7; | ||
108 | else | ||
109 | { | ||
110 | printk(KERN_ERR "kahlua: No 16bit DMA enabled.\n"); | ||
111 | return 1; | ||
112 | } | ||
113 | |||
114 | if(dma8 & 0x01) | ||
115 | dma8 = 0; | ||
116 | else if(dma8 & 0x02) | ||
117 | dma8 = 1; | ||
118 | else if(dma8 & 0x08) | ||
119 | dma8 = 3; | ||
120 | else | ||
121 | { | ||
122 | printk(KERN_ERR "kahlua: No 8bit DMA enabled.\n"); | ||
123 | return 1; | ||
124 | } | ||
125 | |||
126 | if(irq & 1) | ||
127 | irq = 9; | ||
128 | else if(irq & 2) | ||
129 | irq = 5; | ||
130 | else if(irq & 4) | ||
131 | irq = 7; | ||
132 | else if(irq & 8) | ||
133 | irq = 10; | ||
134 | else | ||
135 | { | ||
136 | printk(KERN_ERR "kahlua: SB IRQ not set.\n"); | ||
137 | return 1; | ||
138 | } | ||
139 | |||
140 | printk(KERN_INFO "kahlua: XpressAudio on IRQ %d, DMA %d, %d\n", | ||
141 | irq, dma8, dma16); | ||
142 | |||
143 | hw_config = kmalloc(sizeof(struct address_info), GFP_KERNEL); | ||
144 | if(hw_config == NULL) | ||
145 | { | ||
146 | printk(KERN_ERR "kahlua: out of memory.\n"); | ||
147 | return 1; | ||
148 | } | ||
149 | memset(hw_config, 0, sizeof(*hw_config)); | ||
150 | |||
151 | pci_set_drvdata(pdev, hw_config); | ||
152 | |||
153 | hw_config->io_base = io; | ||
154 | hw_config->irq = irq; | ||
155 | hw_config->dma = dma8; | ||
156 | hw_config->dma2 = dma16; | ||
157 | hw_config->name = "Cyrix XpressAudio"; | ||
158 | hw_config->driver_use_1 = SB_NO_MIDI | SB_PCI_IRQ; | ||
159 | |||
160 | if (!request_region(io, 16, "soundblaster")) | ||
161 | goto err_out_free; | ||
162 | |||
163 | if(sb_dsp_detect(hw_config, 0, 0, NULL)==0) | ||
164 | { | ||
165 | printk(KERN_ERR "kahlua: audio not responding.\n"); | ||
166 | release_region(io, 16); | ||
167 | goto err_out_free; | ||
168 | } | ||
169 | |||
170 | oldquiet = sb_be_quiet; | ||
171 | sb_be_quiet = 1; | ||
172 | if(sb_dsp_init(hw_config, THIS_MODULE)) | ||
173 | { | ||
174 | sb_be_quiet = oldquiet; | ||
175 | goto err_out_free; | ||
176 | } | ||
177 | sb_be_quiet = oldquiet; | ||
178 | |||
179 | return 0; | ||
180 | |||
181 | err_out_free: | ||
182 | pci_set_drvdata(pdev, NULL); | ||
183 | kfree(hw_config); | ||
184 | return 1; | ||
185 | } | ||
186 | |||
187 | static void __devexit remove_one(struct pci_dev *pdev) | ||
188 | { | ||
189 | struct address_info *hw_config = pci_get_drvdata(pdev); | ||
190 | sb_dsp_unload(hw_config, 0); | ||
191 | pci_set_drvdata(pdev, NULL); | ||
192 | kfree(hw_config); | ||
193 | } | ||
194 | |||
195 | MODULE_AUTHOR("Alan Cox"); | ||
196 | MODULE_DESCRIPTION("Kahlua VSA1 PCI Audio"); | ||
197 | MODULE_LICENSE("GPL"); | ||
198 | |||
199 | /* | ||
200 | * 5530 only. The 5510/5520 decode is different. | ||
201 | */ | ||
202 | |||
203 | static struct pci_device_id id_tbl[] = { | ||
204 | { PCI_VENDOR_ID_CYRIX, PCI_DEVICE_ID_CYRIX_5530_AUDIO, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, | ||
205 | { } | ||
206 | }; | ||
207 | |||
208 | MODULE_DEVICE_TABLE(pci, id_tbl); | ||
209 | |||
210 | static struct pci_driver kahlua_driver = { | ||
211 | .name = "kahlua", | ||
212 | .id_table = id_tbl, | ||
213 | .probe = probe_one, | ||
214 | .remove = __devexit_p(remove_one), | ||
215 | }; | ||
216 | |||
217 | |||
218 | static int __init kahlua_init_module(void) | ||
219 | { | ||
220 | printk(KERN_INFO "Cyrix Kahlua VSA1 XpressAudio support (c) Copyright 2003 Red Hat Inc\n"); | ||
221 | return pci_module_init(&kahlua_driver); | ||
222 | } | ||
223 | |||
224 | static void __devexit kahlua_cleanup_module(void) | ||
225 | { | ||
226 | pci_unregister_driver(&kahlua_driver); | ||
227 | } | ||
228 | |||
229 | |||
230 | module_init(kahlua_init_module); | ||
231 | module_exit(kahlua_cleanup_module); | ||
232 | |||