aboutsummaryrefslogtreecommitdiffstats
path: root/sound/isa
diff options
context:
space:
mode:
Diffstat (limited to 'sound/isa')
-rw-r--r--sound/isa/Kconfig377
-rw-r--r--sound/isa/Makefile26
-rw-r--r--sound/isa/ad1816a/Makefile10
-rw-r--r--sound/isa/ad1816a/ad1816a.c312
-rw-r--r--sound/isa/ad1816a/ad1816a_lib.c974
-rw-r--r--sound/isa/ad1848/Makefile15
-rw-r--r--sound/isa/ad1848/ad1848.c151
-rw-r--r--sound/isa/ad1848/ad1848_lib.c1279
-rw-r--r--sound/isa/als100.c336
-rw-r--r--sound/isa/azt2320.c366
-rw-r--r--sound/isa/cmi8330.c633
-rw-r--r--sound/isa/cs423x/Makefile25
-rw-r--r--sound/isa/cs423x/cs4231.c169
-rw-r--r--sound/isa/cs423x/cs4231_lib.c1964
-rw-r--r--sound/isa/cs423x/cs4232.c2
-rw-r--r--sound/isa/cs423x/cs4236.c608
-rw-r--r--sound/isa/cs423x/cs4236_lib.c970
-rw-r--r--sound/isa/dt019x.c327
-rw-r--r--sound/isa/es1688/Makefile11
-rw-r--r--sound/isa/es1688/es1688.c204
-rw-r--r--sound/isa/es1688/es1688_lib.c1062
-rw-r--r--sound/isa/es18xx.c2224
-rw-r--r--sound/isa/gus/Makefile36
-rw-r--r--sound/isa/gus/gus_dma.c244
-rw-r--r--sound/isa/gus/gus_dram.c103
-rw-r--r--sound/isa/gus/gus_instr.c173
-rw-r--r--sound/isa/gus/gus_io.c531
-rw-r--r--sound/isa/gus/gus_irq.c142
-rw-r--r--sound/isa/gus/gus_main.c514
-rw-r--r--sound/isa/gus/gus_mem.c353
-rw-r--r--sound/isa/gus/gus_mem_proc.c135
-rw-r--r--sound/isa/gus/gus_mixer.c199
-rw-r--r--sound/isa/gus/gus_pcm.c903
-rw-r--r--sound/isa/gus/gus_reset.c413
-rw-r--r--sound/isa/gus/gus_sample.c155
-rw-r--r--sound/isa/gus/gus_simple.c634
-rw-r--r--sound/isa/gus/gus_synth.c329
-rw-r--r--sound/isa/gus/gus_tables.h86
-rw-r--r--sound/isa/gus/gus_timer.c204
-rw-r--r--sound/isa/gus/gus_uart.c257
-rw-r--r--sound/isa/gus/gus_volume.c210
-rw-r--r--sound/isa/gus/gusclassic.c260
-rw-r--r--sound/isa/gus/gusextreme.c374
-rw-r--r--sound/isa/gus/gusmax.c400
-rw-r--r--sound/isa/gus/interwave-stb.c2
-rw-r--r--sound/isa/gus/interwave.c969
-rw-r--r--sound/isa/opl3sa2.c860
-rw-r--r--sound/isa/opti9xx/Makefile13
-rw-r--r--sound/isa/opti9xx/opti92x-ad1848.c2226
-rw-r--r--sound/isa/opti9xx/opti92x-cs4231.c2
-rw-r--r--sound/isa/opti9xx/opti93x.c3
-rw-r--r--sound/isa/sb/Makefile39
-rw-r--r--sound/isa/sb/emu8000.c1170
-rw-r--r--sound/isa/sb/emu8000_callback.c543
-rw-r--r--sound/isa/sb/emu8000_local.h43
-rw-r--r--sound/isa/sb/emu8000_patch.c303
-rw-r--r--sound/isa/sb/emu8000_pcm.c704
-rw-r--r--sound/isa/sb/emu8000_synth.c134
-rw-r--r--sound/isa/sb/es968.c235
-rw-r--r--sound/isa/sb/sb16.c678
-rw-r--r--sound/isa/sb/sb16_csp.c1175
-rw-r--r--sound/isa/sb/sb16_csp_codecs.h949
-rw-r--r--sound/isa/sb/sb16_main.c916
-rw-r--r--sound/isa/sb/sb8.c223
-rw-r--r--sound/isa/sb/sb8_main.c565
-rw-r--r--sound/isa/sb/sb8_midi.c293
-rw-r--r--sound/isa/sb/sb_common.c313
-rw-r--r--sound/isa/sb/sb_mixer.c844
-rw-r--r--sound/isa/sb/sbawe.c2
-rw-r--r--sound/isa/sgalaxy.c322
-rw-r--r--sound/isa/sscape.c1517
-rw-r--r--sound/isa/wavefront/Makefile9
-rw-r--r--sound/isa/wavefront/wavefront.c716
-rw-r--r--sound/isa/wavefront/wavefront_fx.c1019
-rw-r--r--sound/isa/wavefront/wavefront_midi.c570
-rw-r--r--sound/isa/wavefront/wavefront_synth.c2243
76 files changed, 38300 insertions, 0 deletions
diff --git a/sound/isa/Kconfig b/sound/isa/Kconfig
new file mode 100644
index 000000000000..4a6be966bd9f
--- /dev/null
+++ b/sound/isa/Kconfig
@@ -0,0 +1,377 @@
1# ALSA ISA drivers
2
3menu "ISA devices"
4 depends on SND!=n && ISA
5
6config SND_AD1848_LIB
7 tristate
8 select SND_PCM
9 select SND_GENERIC_PM
10
11config SND_CS4231_LIB
12 tristate
13 select SND_PCM
14 select SND_GENERIC_PM
15
16config SND_AD1816A
17 tristate "Analog Devices SoundPort AD1816A"
18 depends on SND && ISAPNP
19 select SND_OPL3_LIB
20 select SND_MPU401_UART
21 select SND_PCM
22 help
23 Say Y here to include support for Analog Devices SoundPort
24 AD1816A or compatible sound chips.
25
26 To compile this driver as a module, choose M here: the module
27 will be called snd-ad1816a.
28
29config SND_AD1848
30 tristate "Generic AD1848/CS4248 driver"
31 depends on SND
32 select SND_AD1848_LIB
33 help
34 Say Y here to include support for AD1848 (Analog Devices) or
35 CS4248 (Cirrus Logic - Crystal Semiconductors) chips.
36
37 For newer chips from Cirrus Logic, use the CS4231, CS4232 or
38 CS4236+ drivers.
39
40 To compile this driver as a module, choose M here: the module
41 will be called snd-ad1848.
42
43config SND_CS4231
44 tristate "Generic Cirrus Logic CS4231 driver"
45 depends on SND
46 select SND_MPU401_UART
47 select SND_CS4231_LIB
48 help
49 Say Y here to include support for CS4231 chips from Cirrus
50 Logic - Crystal Semiconductors.
51
52 To compile this driver as a module, choose M here: the module
53 will be called snd-cs4231.
54
55config SND_CS4232
56 tristate "Generic Cirrus Logic CS4232 driver"
57 depends on SND
58 select SND_OPL3_LIB
59 select SND_MPU401_UART
60 select SND_CS4231_LIB
61 help
62 Say Y here to include support for CS4232 chips from Cirrus
63 Logic - Crystal Semiconductors.
64
65 To compile this driver as a module, choose M here: the module
66 will be called snd-cs4232.
67
68config SND_CS4236
69 tristate "Generic Cirrus Logic CS4236+ driver"
70 depends on SND
71 select SND_OPL3_LIB
72 select SND_MPU401_UART
73 select SND_CS4231_LIB
74 help
75 Say Y to include support for CS4235,CS4236,CS4237B,CS4238B,
76 CS4239 chips from Cirrus Logic - Crystal Semiconductors.
77
78 To compile this driver as a module, choose M here: the module
79 will be called snd-cs4236.
80
81config SND_ES968
82 tristate "Generic ESS ES968 driver"
83 depends on SND && ISAPNP
84 select SND_MPU401_UART
85 select SND_PCM
86 help
87 Say Y here to include support for ESS AudioDrive ES968 chips.
88
89 To compile this driver as a module, choose M here: the module
90 will be called snd-es968.
91
92config SND_ES1688
93 tristate "Generic ESS ES688/ES1688 driver"
94 depends on SND
95 select SND_OPL3_LIB
96 select SND_MPU401_UART
97 select SND_PCM
98 help
99 Say Y here to include support for ESS AudioDrive ES688 or
100 ES1688 chips.
101
102 To compile this driver as a module, choose M here: the module
103 will be called snd-es1688.
104
105config SND_ES18XX
106 tristate "Generic ESS ES18xx driver"
107 depends on SND
108 select SND_OPL3_LIB
109 select SND_MPU401_UART
110 select SND_PCM
111 select SND_GENERIC_PM
112 help
113 Say Y here to include support for ESS AudioDrive ES18xx chips.
114
115 To compile this driver as a module, choose M here: the module
116 will be called snd-es18xx.
117
118config SND_GUS_SYNTH
119 tristate
120
121config SND_GUSCLASSIC
122 tristate "Gravis UltraSound Classic"
123 depends on SND
124 select SND_RAWMIDI
125 select SND_PCM
126 select SND_GUS_SYNTH
127 help
128 Say Y here to include support for Gravis UltraSound Classic
129 soundcards.
130
131 To compile this driver as a module, choose M here: the module
132 will be called snd-gusclassic.
133
134config SND_GUSEXTREME
135 tristate "Gravis UltraSound Extreme"
136 depends on SND
137 select SND_HWDEP
138 select SND_MPU401_UART
139 select SND_PCM
140 select SND_GUS_SYNTH
141 help
142 Say Y here to include support for Gravis UltraSound Extreme
143 soundcards.
144
145 To compile this driver as a module, choose M here: the module
146 will be called snd-gusextreme.
147
148config SND_GUSMAX
149 tristate "Gravis UltraSound MAX"
150 depends on SND
151 select SND_RAWMIDI
152 select SND_CS4231_LIB
153 select SND_GUS_SYNTH
154 help
155 Say Y here to include support for Gravis UltraSound MAX
156 soundcards.
157
158 To compile this driver as a module, choose M here: the module
159 will be called snd-gusmax.
160
161config SND_INTERWAVE
162 tristate "AMD InterWave, Gravis UltraSound PnP"
163 depends on SND
164 select SND_RAWMIDI
165 select SND_CS4231_LIB
166 select SND_GUS_SYNTH
167 help
168 Say Y here to include support for AMD InterWave based
169 soundcards (Gravis UltraSound Plug & Play, STB SoundRage32,
170 MED3210, Dynasonic Pro, Panasonic PCA761AW).
171
172 To compile this driver as a module, choose M here: the module
173 will be called snd-interwave.
174
175config SND_INTERWAVE_STB
176 tristate "AMD InterWave + TEA6330T (UltraSound 32-Pro)"
177 depends on SND
178 select SND_RAWMIDI
179 select SND_CS4231_LIB
180 select SND_GUS_SYNTH
181 help
182 Say Y here to include support for AMD InterWave based
183 soundcards with a TEA6330T bass and treble regulator
184 (UltraSound 32-Pro).
185
186 To compile this driver as a module, choose M here: the module
187 will be called snd-interwave-stb.
188
189config SND_OPTI92X_AD1848
190 tristate "OPTi 82C92x - AD1848"
191 depends on SND
192 select SND_OPL3_LIB
193 select SND_OPL4_LIB
194 select SND_MPU401_UART
195 select SND_AD1848_LIB
196 help
197 Say Y here to include support for soundcards based on Opti
198 82C92x or OTI-601 chips and using an AD1848 codec.
199
200 To compile this driver as a module, choose M here: the module
201 will be called snd-opti92x-ad1848.
202
203config SND_OPTI92X_CS4231
204 tristate "OPTi 82C92x - CS4231"
205 depends on SND
206 select SND_OPL3_LIB
207 select SND_OPL4_LIB
208 select SND_MPU401_UART
209 select SND_CS4231_LIB
210 help
211 Say Y here to include support for soundcards based on Opti
212 82C92x chips and using a CS4231 codec.
213
214 To compile this driver as a module, choose M here: the module
215 will be called snd-opti92x-cs4231.
216
217config SND_OPTI93X
218 tristate "OPTi 82C93x"
219 depends on SND
220 select SND_OPL3_LIB
221 select SND_MPU401_UART
222 select SND_PCM
223 help
224 Say Y here to include support for soundcards based on Opti
225 82C93x chips.
226
227 To compile this driver as a module, choose M here: the module
228 will be called snd-opti93x.
229
230config SND_SB8
231 tristate "Sound Blaster 1.0/2.0/Pro (8-bit)"
232 depends on SND
233 select SND_OPL3_LIB
234 select SND_RAWMIDI
235 select SND_PCM
236 help
237 Say Y here to include support for Creative Sound Blaster 1.0/
238 2.0/Pro (8-bit) or 100% compatible soundcards.
239
240 To compile this driver as a module, choose M here: the module
241 will be called snd-sb8.
242
243config SND_SB16
244 tristate "Sound Blaster 16 (PnP)"
245 depends on SND
246 select SND_OPL3_LIB
247 select SND_MPU401_UART
248 select SND_PCM
249 help
250 Say Y here to include support for Sound Blaster 16 soundcards
251 (including the Plug and Play version).
252
253 To compile this driver as a module, choose M here: the module
254 will be called snd-sb16.
255
256config SND_SBAWE
257 tristate "Sound Blaster AWE (32,64) (PnP)"
258 depends on SND
259 select SND_OPL3_LIB
260 select SND_MPU401_UART
261 select SND_PCM
262 help
263 Say Y here to include support for Sound Blaster AWE soundcards
264 (including the Plug and Play version).
265
266 To compile this driver as a module, choose M here: the module
267 will be called snd-sbawe.
268
269config SND_SB16_CSP
270 bool "Sound Blaster 16/AWE CSP support"
271 depends on (SND_SB16 || SND_SBAWE) && (BROKEN || !PPC)
272 help
273 Say Y here to include support for the CSP core. This special
274 coprocessor can do variable tasks like various compression and
275 decompression algorithms.
276
277config SND_WAVEFRONT
278 tristate "Turtle Beach Maui,Tropez,Tropez+ (Wavefront)"
279 depends on SND
280 select SND_OPL3_LIB
281 select SND_MPU401_UART
282 select SND_CS4231_LIB
283 help
284 Say Y here to include support for Turtle Beach Maui, Tropez
285 and Tropez+ soundcards based on the Wavefront chip.
286
287 To compile this driver as a module, choose M here: the module
288 will be called snd-wavefront.
289
290config SND_ALS100
291 tristate "Avance Logic ALS100/ALS120"
292 depends on SND && ISAPNP
293 select SND_OPL3_LIB
294 select SND_MPU401_UART
295 select SND_PCM
296 help
297 Say Y here to include support for soundcards based on Avance
298 Logic ALS100, ALS110, ALS120 and ALS200 chips.
299
300 To compile this driver as a module, choose M here: the module
301 will be called snd-als100.
302
303config SND_AZT2320
304 tristate "Aztech Systems AZT2320"
305 depends on SND && ISAPNP
306 select SND_OPL3_LIB
307 select SND_MPU401_UART
308 select SND_CS4231_LIB
309 help
310 Say Y here to include support for soundcards based on the
311 Aztech Systems AZT2320 chip.
312
313 To compile this driver as a module, choose M here: the module
314 will be called snd-azt2320.
315
316config SND_CMI8330
317 tristate "C-Media CMI8330"
318 depends on SND
319 select SND_AD1848_LIB
320 help
321 Say Y here to include support for soundcards based on the
322 C-Media CMI8330 chip.
323
324 To compile this driver as a module, choose M here: the module
325 will be called snd-cmi8330.
326
327config SND_DT019X
328 tristate "Diamond Technologies DT-019X, Avance Logic ALS-007"
329 depends on SND && ISAPNP
330 select SND_OPL3_LIB
331 select SND_MPU401_UART
332 select SND_PCM
333 help
334 Say Y here to include support for soundcards based on the
335 Diamond Technologies DT-019X or Avance Logic ALS-007 chips.
336
337 To compile this driver as a module, choose M here: the module
338 will be called snd-dt019x.
339
340config SND_OPL3SA2
341 tristate "Yamaha OPL3-SA2/SA3"
342 depends on SND
343 select SND_OPL3_LIB
344 select SND_MPU401_UART
345 select SND_CS4231_LIB
346 help
347 Say Y here to include support for Yamaha OPL3-SA2 and OPL3-SA3
348 chips.
349
350 To compile this driver as a module, choose M here: the module
351 will be called snd-opl3sa2.
352
353config SND_SGALAXY
354 tristate "Aztech Sound Galaxy"
355 depends on SND
356 select SND_AD1848_LIB
357 help
358 Say Y here to include support for Aztech Sound Galaxy
359 soundcards.
360
361 To compile this driver as a module, choose M here: the module
362 will be called snd-sgalaxy.
363
364config SND_SSCAPE
365 tristate "Ensoniq SoundScape PnP driver"
366 depends on SND
367 select SND_HWDEP
368 select SND_MPU401_UART
369 select SND_CS4231_LIB
370 help
371 Say Y here to include support for Ensoniq SoundScape PnP
372 soundcards.
373
374 To compile this driver as a module, choose M here: the module
375 will be called snd-sscape.
376
377endmenu
diff --git a/sound/isa/Makefile b/sound/isa/Makefile
new file mode 100644
index 000000000000..05724eb7bfe4
--- /dev/null
+++ b/sound/isa/Makefile
@@ -0,0 +1,26 @@
1#
2# Makefile for ALSA
3# Copyright (c) 2001 by Jaroslav Kysela <perex@suse.cz>
4#
5
6snd-als100-objs := als100.o
7snd-azt2320-objs := azt2320.o
8snd-cmi8330-objs := cmi8330.o
9snd-dt019x-objs := dt019x.o
10snd-es18xx-objs := es18xx.o
11snd-opl3sa2-objs := opl3sa2.o
12snd-sgalaxy-objs := sgalaxy.o
13snd-sscape-objs := sscape.o
14
15# Toplevel Module Dependency
16obj-$(CONFIG_SND_ALS100) += snd-als100.o
17obj-$(CONFIG_SND_AZT2320) += snd-azt2320.o
18obj-$(CONFIG_SND_CMI8330) += snd-cmi8330.o
19obj-$(CONFIG_SND_DT019X) += snd-dt019x.o
20obj-$(CONFIG_SND_ES18XX) += snd-es18xx.o
21obj-$(CONFIG_SND_OPL3SA2) += snd-opl3sa2.o
22obj-$(CONFIG_SND_SGALAXY) += snd-sgalaxy.o
23obj-$(CONFIG_SND_SSCAPE) += snd-sscape.o
24
25obj-$(CONFIG_SND) += ad1816a/ ad1848/ cs423x/ es1688/ gus/ opti9xx/ \
26 sb/ wavefront/
diff --git a/sound/isa/ad1816a/Makefile b/sound/isa/ad1816a/Makefile
new file mode 100644
index 000000000000..a42b29cf8549
--- /dev/null
+++ b/sound/isa/ad1816a/Makefile
@@ -0,0 +1,10 @@
1#
2# Makefile for ALSA
3# Copyright (c) 2001 by Jaroslav Kysela <perex@suse.cz>
4#
5
6snd-ad1816a-lib-objs := ad1816a_lib.o
7snd-ad1816a-objs := ad1816a.o
8
9# Toplevel Module Dependency
10obj-$(CONFIG_SND_AD1816A) += snd-ad1816a.o snd-ad1816a-lib.o
diff --git a/sound/isa/ad1816a/ad1816a.c b/sound/isa/ad1816a/ad1816a.c
new file mode 100644
index 000000000000..9fa7a78da6c3
--- /dev/null
+++ b/sound/isa/ad1816a/ad1816a.c
@@ -0,0 +1,312 @@
1
2/*
3 card-ad1816a.c - driver for ADI SoundPort AD1816A based soundcards.
4 Copyright (C) 2000 by Massimo Piccioni <dafastidio@libero.it>
5
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
10
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19*/
20
21#include <sound/driver.h>
22#include <linux/init.h>
23#include <linux/time.h>
24#include <linux/wait.h>
25#include <linux/pnp.h>
26#include <linux/moduleparam.h>
27#include <sound/core.h>
28#include <sound/initval.h>
29#include <sound/ad1816a.h>
30#include <sound/mpu401.h>
31#include <sound/opl3.h>
32
33#define PFX "ad1816a: "
34
35MODULE_AUTHOR("Massimo Piccioni <dafastidio@libero.it>");
36MODULE_DESCRIPTION("AD1816A, AD1815");
37MODULE_LICENSE("GPL");
38MODULE_SUPPORTED_DEVICE("{{Highscreen,Sound-Boostar 16 3D},"
39 "{Analog Devices,AD1815},"
40 "{Analog Devices,AD1816A},"
41 "{TerraTec,Base 64},"
42 "{TerraTec,AudioSystem EWS64S},"
43 "{Aztech/Newcom SC-16 3D},"
44 "{Shark Predator ISA}}");
45
46static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 1-MAX */
47static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* ID for this card */
48static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_ISAPNP; /* Enable this card */
49static long port[SNDRV_CARDS] = SNDRV_DEFAULT_PORT; /* PnP setup */
50static long mpu_port[SNDRV_CARDS] = SNDRV_DEFAULT_PORT; /* PnP setup */
51static long fm_port[SNDRV_CARDS] = SNDRV_DEFAULT_PORT; /* PnP setup */
52static int irq[SNDRV_CARDS] = SNDRV_DEFAULT_IRQ; /* Pnp setup */
53static int mpu_irq[SNDRV_CARDS] = SNDRV_DEFAULT_IRQ; /* Pnp setup */
54static int dma1[SNDRV_CARDS] = SNDRV_DEFAULT_DMA; /* PnP setup */
55static int dma2[SNDRV_CARDS] = SNDRV_DEFAULT_DMA; /* PnP setup */
56
57module_param_array(index, int, NULL, 0444);
58MODULE_PARM_DESC(index, "Index value for ad1816a based soundcard.");
59module_param_array(id, charp, NULL, 0444);
60MODULE_PARM_DESC(id, "ID string for ad1816a based soundcard.");
61module_param_array(enable, bool, NULL, 0444);
62MODULE_PARM_DESC(enable, "Enable ad1816a based soundcard.");
63module_param_array(port, long, NULL, 0444);
64MODULE_PARM_DESC(port, "Port # for ad1816a driver.");
65module_param_array(mpu_port, long, NULL, 0444);
66MODULE_PARM_DESC(mpu_port, "MPU-401 port # for ad1816a driver.");
67module_param_array(fm_port, long, NULL, 0444);
68MODULE_PARM_DESC(fm_port, "FM port # for ad1816a driver.");
69module_param_array(irq, int, NULL, 0444);
70MODULE_PARM_DESC(irq, "IRQ # for ad1816a driver.");
71module_param_array(mpu_irq, int, NULL, 0444);
72MODULE_PARM_DESC(mpu_irq, "MPU-401 IRQ # for ad1816a driver.");
73module_param_array(dma1, int, NULL, 0444);
74MODULE_PARM_DESC(dma1, "1st DMA # for ad1816a driver.");
75module_param_array(dma2, int, NULL, 0444);
76MODULE_PARM_DESC(dma2, "2nd DMA # for ad1816a driver.");
77
78struct snd_card_ad1816a {
79 struct pnp_dev *dev;
80 struct pnp_dev *devmpu;
81};
82
83static struct pnp_card_device_id snd_ad1816a_pnpids[] = {
84 /* Analog Devices AD1815 */
85 { .id = "ADS7150", .devs = { { .id = "ADS7150" }, { .id = "ADS7151" } } },
86 /* Analog Devices AD1816A - added by Kenneth Platz <kxp@atl.hp.com> */
87 { .id = "ADS7181", .devs = { { .id = "ADS7180" }, { .id = "ADS7181" } } },
88 /* Analog Devices AD1816A - Aztech/Newcom SC-16 3D */
89 { .id = "AZT1022", .devs = { { .id = "AZT1018" }, { .id = "AZT2002" } } },
90 /* Highscreen Sound-Boostar 16 3D - added by Stefan Behnel */
91 { .id = "LWC1061", .devs = { { .id = "ADS7180" }, { .id = "ADS7181" } } },
92 /* Highscreen Sound-Boostar 16 3D */
93 { .id = "MDK1605", .devs = { { .id = "ADS7180" }, { .id = "ADS7181" } } },
94 /* Shark Predator ISA - added by Ken Arromdee */
95 { .id = "SMM7180", .devs = { { .id = "ADS7180" }, { .id = "ADS7181" } } },
96 /* Analog Devices AD1816A - Terratec AudioSystem EWS64S */
97 { .id = "TER1112", .devs = { { .id = "ADS7180" }, { .id = "ADS7181" } } },
98 /* Analog Devices AD1816A - Terratec Base 64 */
99 { .id = "TER1411", .devs = { { .id = "ADS7180" }, { .id = "ADS7181" } } },
100 /* end */
101 { .id = "" }
102};
103
104MODULE_DEVICE_TABLE(pnp_card, snd_ad1816a_pnpids);
105
106
107#define DRIVER_NAME "snd-card-ad1816a"
108
109
110static int __devinit snd_card_ad1816a_pnp(int dev, struct snd_card_ad1816a *acard,
111 struct pnp_card_link *card,
112 const struct pnp_card_device_id *id)
113{
114 struct pnp_dev *pdev;
115 struct pnp_resource_table *cfg = kmalloc(sizeof(*cfg), GFP_KERNEL);
116 int err;
117
118 acard->dev = pnp_request_card_device(card, id->devs[0].id, NULL);
119 if (acard->dev == NULL) {
120 kfree(cfg);
121 return -EBUSY;
122 }
123 acard->devmpu = pnp_request_card_device(card, id->devs[1].id, NULL);
124 if (acard->devmpu == NULL) {
125 kfree(cfg);
126 return -EBUSY;
127 }
128
129 pdev = acard->dev;
130 pnp_init_resource_table(cfg);
131
132 if (port[dev] != SNDRV_AUTO_PORT)
133 pnp_resource_change(&cfg->port_resource[2], port[dev], 16);
134 if (fm_port[dev] != SNDRV_AUTO_PORT)
135 pnp_resource_change(&cfg->port_resource[1], fm_port[dev], 4);
136 if (dma1[dev] != SNDRV_AUTO_DMA)
137 pnp_resource_change(&cfg->dma_resource[0], dma1[dev], 1);
138 if (dma2[dev] != SNDRV_AUTO_DMA)
139 pnp_resource_change(&cfg->dma_resource[1], dma2[dev], 1);
140 if (irq[dev] != SNDRV_AUTO_IRQ)
141 pnp_resource_change(&cfg->irq_resource[0], irq[dev], 1);
142
143 if (pnp_manual_config_dev(pdev, cfg, 0) < 0)
144 snd_printk(KERN_ERR PFX "AUDIO the requested resources are invalid, using auto config\n");
145 err = pnp_activate_dev(pdev);
146 if (err < 0) {
147 printk(KERN_ERR PFX "AUDIO PnP configure failure\n");
148 kfree(cfg);
149 return -EBUSY;
150 }
151
152 port[dev] = pnp_port_start(pdev, 2);
153 fm_port[dev] = pnp_port_start(pdev, 1);
154 dma1[dev] = pnp_dma(pdev, 0);
155 dma2[dev] = pnp_dma(pdev, 1);
156 irq[dev] = pnp_irq(pdev, 0);
157
158 pdev = acard->devmpu;
159 pnp_init_resource_table(cfg);
160
161 if (mpu_port[dev] != SNDRV_AUTO_PORT)
162 pnp_resource_change(&cfg->port_resource[0], mpu_port[dev], 2);
163 if (mpu_irq[dev] != SNDRV_AUTO_IRQ)
164 pnp_resource_change(&cfg->irq_resource[0], mpu_irq[dev], 1);
165
166 if (pnp_manual_config_dev(pdev, cfg, 0) < 0)
167 snd_printk(KERN_ERR PFX "AUDIO the requested resources are invalid, using auto config\n");
168 err = pnp_activate_dev(pdev);
169 if (err < 0) {
170 printk(KERN_ERR PFX "MPU401 PnP configure failure\n");
171 mpu_port[dev] = -1;
172 acard->devmpu = NULL;
173 } else {
174 mpu_port[dev] = pnp_port_start(pdev, 0);
175 mpu_irq[dev] = pnp_irq(pdev, 0);
176 }
177
178 kfree(cfg);
179 return 0;
180}
181
182static int __devinit snd_card_ad1816a_probe(int dev, struct pnp_card_link *pcard,
183 const struct pnp_card_device_id *pid)
184{
185 int error;
186 snd_card_t *card;
187 struct snd_card_ad1816a *acard;
188 ad1816a_t *chip;
189 opl3_t *opl3;
190
191 if ((card = snd_card_new(index[dev], id[dev], THIS_MODULE,
192 sizeof(struct snd_card_ad1816a))) == NULL)
193 return -ENOMEM;
194 acard = (struct snd_card_ad1816a *)card->private_data;
195
196 if ((error = snd_card_ad1816a_pnp(dev, acard, pcard, pid))) {
197 snd_card_free(card);
198 return error;
199 }
200 snd_card_set_dev(card, &pcard->card->dev);
201
202 if ((error = snd_ad1816a_create(card, port[dev],
203 irq[dev],
204 dma1[dev],
205 dma2[dev],
206 &chip)) < 0) {
207 snd_card_free(card);
208 return error;
209 }
210
211 strcpy(card->driver, "AD1816A");
212 strcpy(card->shortname, "ADI SoundPort AD1816A");
213 sprintf(card->longname, "%s, SS at 0x%lx, irq %d, dma %d&%d",
214 card->shortname, chip->port, irq[dev], dma1[dev], dma2[dev]);
215
216 if ((error = snd_ad1816a_pcm(chip, 0, NULL)) < 0) {
217 snd_card_free(card);
218 return error;
219 }
220
221 if ((error = snd_ad1816a_mixer(chip)) < 0) {
222 snd_card_free(card);
223 return error;
224 }
225
226 if (mpu_port[dev] > 0) {
227 if (snd_mpu401_uart_new(card, 0, MPU401_HW_MPU401,
228 mpu_port[dev], 0, mpu_irq[dev], SA_INTERRUPT,
229 NULL) < 0)
230 printk(KERN_ERR PFX "no MPU-401 device at 0x%lx.\n", mpu_port[dev]);
231 }
232
233 if (fm_port[dev] > 0) {
234 if (snd_opl3_create(card,
235 fm_port[dev], fm_port[dev] + 2,
236 OPL3_HW_AUTO, 0, &opl3) < 0) {
237 printk(KERN_ERR PFX "no OPL device at 0x%lx-0x%lx.\n", fm_port[dev], fm_port[dev] + 2);
238 } else {
239 if ((error = snd_opl3_timer_new(opl3, 1, 2)) < 0) {
240 snd_card_free(card);
241 return error;
242 }
243 if ((error = snd_opl3_hwdep_new(opl3, 0, 1, NULL)) < 0) {
244 snd_card_free(card);
245 return error;
246 }
247 }
248 }
249
250 if ((error = snd_card_register(card)) < 0) {
251 snd_card_free(card);
252 return error;
253 }
254 pnp_set_card_drvdata(pcard, card);
255 return 0;
256}
257
258static int __devinit snd_ad1816a_pnp_detect(struct pnp_card_link *card,
259 const struct pnp_card_device_id *id)
260{
261 static int dev;
262 int res;
263
264 for ( ; dev < SNDRV_CARDS; dev++) {
265 if (!enable[dev])
266 continue;
267 res = snd_card_ad1816a_probe(dev, card, id);
268 if (res < 0)
269 return res;
270 dev++;
271 return 0;
272 }
273 return -ENODEV;
274}
275
276static void __devexit snd_ad1816a_pnp_remove(struct pnp_card_link * pcard)
277{
278 snd_card_t *card = (snd_card_t *) pnp_get_card_drvdata(pcard);
279
280 snd_card_disconnect(card);
281 snd_card_free_in_thread(card);
282}
283
284static struct pnp_card_driver ad1816a_pnpc_driver = {
285 .flags = PNP_DRIVER_RES_DISABLE,
286 .name = "ad1816a",
287 .id_table = snd_ad1816a_pnpids,
288 .probe = snd_ad1816a_pnp_detect,
289 .remove = __devexit_p(snd_ad1816a_pnp_remove),
290};
291
292static int __init alsa_card_ad1816a_init(void)
293{
294 int cards = 0;
295
296 cards += pnp_register_card_driver(&ad1816a_pnpc_driver);
297#ifdef MODULE
298 if (!cards) {
299 pnp_unregister_card_driver(&ad1816a_pnpc_driver);
300 printk(KERN_ERR "no AD1816A based soundcards found.\n");
301 }
302#endif /* MODULE */
303 return cards ? 0 : -ENODEV;
304}
305
306static void __exit alsa_card_ad1816a_exit(void)
307{
308 pnp_unregister_card_driver(&ad1816a_pnpc_driver);
309}
310
311module_init(alsa_card_ad1816a_init)
312module_exit(alsa_card_ad1816a_exit)
diff --git a/sound/isa/ad1816a/ad1816a_lib.c b/sound/isa/ad1816a/ad1816a_lib.c
new file mode 100644
index 000000000000..625b2eff14a1
--- /dev/null
+++ b/sound/isa/ad1816a/ad1816a_lib.c
@@ -0,0 +1,974 @@
1
2/*
3 ad1816a.c - lowlevel code for Analog Devices AD1816A chip.
4 Copyright (C) 1999-2000 by Massimo Piccioni <dafastidio@libero.it>
5
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
10
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19*/
20
21#include <sound/driver.h>
22#include <linux/delay.h>
23#include <linux/init.h>
24#include <linux/interrupt.h>
25#include <linux/slab.h>
26#include <linux/ioport.h>
27#include <sound/core.h>
28#include <sound/ad1816a.h>
29
30#include <asm/io.h>
31#include <asm/dma.h>
32
33MODULE_AUTHOR("Massimo Piccioni <dafastidio@libero.it>");
34MODULE_DESCRIPTION("lowlevel code for Analog Devices AD1816A chip");
35MODULE_LICENSE("GPL");
36
37static inline int snd_ad1816a_busy_wait(ad1816a_t *chip)
38{
39 int timeout;
40
41 for (timeout = 1000; timeout-- > 0; udelay(10))
42 if (inb(AD1816A_REG(AD1816A_CHIP_STATUS)) & AD1816A_READY)
43 return 0;
44
45 snd_printk("chip busy.\n");
46 return -EBUSY;
47}
48
49static inline unsigned char snd_ad1816a_in(ad1816a_t *chip, unsigned char reg)
50{
51 snd_ad1816a_busy_wait(chip);
52 return inb(AD1816A_REG(reg));
53}
54
55static inline void snd_ad1816a_out(ad1816a_t *chip, unsigned char reg,
56 unsigned char value)
57{
58 snd_ad1816a_busy_wait(chip);
59 outb(value, AD1816A_REG(reg));
60}
61
62static inline void snd_ad1816a_out_mask(ad1816a_t *chip, unsigned char reg,
63 unsigned char mask, unsigned char value)
64{
65 snd_ad1816a_out(chip, reg,
66 (value & mask) | (snd_ad1816a_in(chip, reg) & ~mask));
67}
68
69static unsigned short snd_ad1816a_read(ad1816a_t *chip, unsigned char reg)
70{
71 snd_ad1816a_out(chip, AD1816A_INDIR_ADDR, reg & 0x3f);
72 return snd_ad1816a_in(chip, AD1816A_INDIR_DATA_LOW) |
73 (snd_ad1816a_in(chip, AD1816A_INDIR_DATA_HIGH) << 8);
74}
75
76static void snd_ad1816a_write(ad1816a_t *chip, unsigned char reg,
77 unsigned short value)
78{
79 snd_ad1816a_out(chip, AD1816A_INDIR_ADDR, reg & 0x3f);
80 snd_ad1816a_out(chip, AD1816A_INDIR_DATA_LOW, value & 0xff);
81 snd_ad1816a_out(chip, AD1816A_INDIR_DATA_HIGH, (value >> 8) & 0xff);
82}
83
84static void snd_ad1816a_write_mask(ad1816a_t *chip, unsigned char reg,
85 unsigned short mask, unsigned short value)
86{
87 snd_ad1816a_write(chip, reg,
88 (value & mask) | (snd_ad1816a_read(chip, reg) & ~mask));
89}
90
91
92static unsigned char snd_ad1816a_get_format(ad1816a_t *chip,
93 unsigned int format, int channels)
94{
95 unsigned char retval = AD1816A_FMT_LINEAR_8;
96
97 switch (format) {
98 case SNDRV_PCM_FORMAT_MU_LAW:
99 retval = AD1816A_FMT_ULAW_8;
100 break;
101 case SNDRV_PCM_FORMAT_A_LAW:
102 retval = AD1816A_FMT_ALAW_8;
103 break;
104 case SNDRV_PCM_FORMAT_S16_LE:
105 retval = AD1816A_FMT_LINEAR_16_LIT;
106 break;
107 case SNDRV_PCM_FORMAT_S16_BE:
108 retval = AD1816A_FMT_LINEAR_16_BIG;
109 }
110 return (channels > 1) ? (retval | AD1816A_FMT_STEREO) : retval;
111}
112
113static int snd_ad1816a_open(ad1816a_t *chip, unsigned int mode)
114{
115 unsigned long flags;
116
117 spin_lock_irqsave(&chip->lock, flags);
118
119 if (chip->mode & mode) {
120 spin_unlock_irqrestore(&chip->lock, flags);
121 return -EAGAIN;
122 }
123
124 switch ((mode &= AD1816A_MODE_OPEN)) {
125 case AD1816A_MODE_PLAYBACK:
126 snd_ad1816a_out_mask(chip, AD1816A_INTERRUPT_STATUS,
127 AD1816A_PLAYBACK_IRQ_PENDING, 0x00);
128 snd_ad1816a_write_mask(chip, AD1816A_INTERRUPT_ENABLE,
129 AD1816A_PLAYBACK_IRQ_ENABLE, 0xffff);
130 break;
131 case AD1816A_MODE_CAPTURE:
132 snd_ad1816a_out_mask(chip, AD1816A_INTERRUPT_STATUS,
133 AD1816A_CAPTURE_IRQ_PENDING, 0x00);
134 snd_ad1816a_write_mask(chip, AD1816A_INTERRUPT_ENABLE,
135 AD1816A_CAPTURE_IRQ_ENABLE, 0xffff);
136 break;
137 case AD1816A_MODE_TIMER:
138 snd_ad1816a_out_mask(chip, AD1816A_INTERRUPT_STATUS,
139 AD1816A_TIMER_IRQ_PENDING, 0x00);
140 snd_ad1816a_write_mask(chip, AD1816A_INTERRUPT_ENABLE,
141 AD1816A_TIMER_IRQ_ENABLE, 0xffff);
142 }
143 chip->mode |= mode;
144
145 spin_unlock_irqrestore(&chip->lock, flags);
146 return 0;
147}
148
149static void snd_ad1816a_close(ad1816a_t *chip, unsigned int mode)
150{
151 unsigned long flags;
152
153 spin_lock_irqsave(&chip->lock, flags);
154
155 switch ((mode &= AD1816A_MODE_OPEN)) {
156 case AD1816A_MODE_PLAYBACK:
157 snd_ad1816a_out_mask(chip, AD1816A_INTERRUPT_STATUS,
158 AD1816A_PLAYBACK_IRQ_PENDING, 0x00);
159 snd_ad1816a_write_mask(chip, AD1816A_INTERRUPT_ENABLE,
160 AD1816A_PLAYBACK_IRQ_ENABLE, 0x0000);
161 break;
162 case AD1816A_MODE_CAPTURE:
163 snd_ad1816a_out_mask(chip, AD1816A_INTERRUPT_STATUS,
164 AD1816A_CAPTURE_IRQ_PENDING, 0x00);
165 snd_ad1816a_write_mask(chip, AD1816A_INTERRUPT_ENABLE,
166 AD1816A_CAPTURE_IRQ_ENABLE, 0x0000);
167 break;
168 case AD1816A_MODE_TIMER:
169 snd_ad1816a_out_mask(chip, AD1816A_INTERRUPT_STATUS,
170 AD1816A_TIMER_IRQ_PENDING, 0x00);
171 snd_ad1816a_write_mask(chip, AD1816A_INTERRUPT_ENABLE,
172 AD1816A_TIMER_IRQ_ENABLE, 0x0000);
173 }
174 if (!((chip->mode &= ~mode) & AD1816A_MODE_OPEN))
175 chip->mode = 0;
176
177 spin_unlock_irqrestore(&chip->lock, flags);
178}
179
180
181static int snd_ad1816a_trigger(ad1816a_t *chip, unsigned char what,
182 int channel, int cmd)
183{
184 int error = 0;
185
186 switch (cmd) {
187 case SNDRV_PCM_TRIGGER_START:
188 case SNDRV_PCM_TRIGGER_STOP:
189 spin_lock(&chip->lock);
190 cmd = (cmd == SNDRV_PCM_TRIGGER_START) ? 0xff: 0x00;
191 if (what & AD1816A_PLAYBACK_ENABLE)
192 snd_ad1816a_out_mask(chip, AD1816A_PLAYBACK_CONFIG,
193 AD1816A_PLAYBACK_ENABLE, cmd);
194 if (what & AD1816A_CAPTURE_ENABLE)
195 snd_ad1816a_out_mask(chip, AD1816A_CAPTURE_CONFIG,
196 AD1816A_CAPTURE_ENABLE, cmd);
197 spin_unlock(&chip->lock);
198 break;
199 default:
200 snd_printk("invalid trigger mode 0x%x.\n", what);
201 error = -EINVAL;
202 }
203
204 return error;
205}
206
207static int snd_ad1816a_playback_trigger(snd_pcm_substream_t *substream, int cmd)
208{
209 ad1816a_t *chip = snd_pcm_substream_chip(substream);
210 return snd_ad1816a_trigger(chip, AD1816A_PLAYBACK_ENABLE,
211 SNDRV_PCM_STREAM_PLAYBACK, cmd);
212}
213
214static int snd_ad1816a_capture_trigger(snd_pcm_substream_t *substream, int cmd)
215{
216 ad1816a_t *chip = snd_pcm_substream_chip(substream);
217 return snd_ad1816a_trigger(chip, AD1816A_CAPTURE_ENABLE,
218 SNDRV_PCM_STREAM_CAPTURE, cmd);
219}
220
221static int snd_ad1816a_hw_params(snd_pcm_substream_t * substream,
222 snd_pcm_hw_params_t * hw_params)
223{
224 return snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(hw_params));
225}
226
227static int snd_ad1816a_hw_free(snd_pcm_substream_t * substream)
228{
229 return snd_pcm_lib_free_pages(substream);
230}
231
232static int snd_ad1816a_playback_prepare(snd_pcm_substream_t *substream)
233{
234 ad1816a_t *chip = snd_pcm_substream_chip(substream);
235 unsigned long flags;
236 snd_pcm_runtime_t *runtime = substream->runtime;
237 unsigned int size;
238
239 spin_lock_irqsave(&chip->lock, flags);
240
241 chip->p_dma_size = size = snd_pcm_lib_buffer_bytes(substream);
242 snd_ad1816a_out_mask(chip, AD1816A_PLAYBACK_CONFIG,
243 AD1816A_PLAYBACK_ENABLE | AD1816A_PLAYBACK_PIO, 0x00);
244
245 snd_dma_program(chip->dma1, runtime->dma_addr, size,
246 DMA_MODE_WRITE | DMA_AUTOINIT);
247
248 snd_ad1816a_write(chip, AD1816A_PLAYBACK_SAMPLE_RATE, runtime->rate);
249 snd_ad1816a_out_mask(chip, AD1816A_PLAYBACK_CONFIG,
250 AD1816A_FMT_ALL | AD1816A_FMT_STEREO,
251 snd_ad1816a_get_format(chip, runtime->format,
252 runtime->channels));
253
254 snd_ad1816a_write(chip, AD1816A_PLAYBACK_BASE_COUNT,
255 snd_pcm_lib_period_bytes(substream) / 4 - 1);
256
257 spin_unlock_irqrestore(&chip->lock, flags);
258 return 0;
259}
260
261static int snd_ad1816a_capture_prepare(snd_pcm_substream_t *substream)
262{
263 ad1816a_t *chip = snd_pcm_substream_chip(substream);
264 unsigned long flags;
265 snd_pcm_runtime_t *runtime = substream->runtime;
266 unsigned int size;
267
268 spin_lock_irqsave(&chip->lock, flags);
269
270 chip->c_dma_size = size = snd_pcm_lib_buffer_bytes(substream);
271 snd_ad1816a_out_mask(chip, AD1816A_CAPTURE_CONFIG,
272 AD1816A_CAPTURE_ENABLE | AD1816A_CAPTURE_PIO, 0x00);
273
274 snd_dma_program(chip->dma2, runtime->dma_addr, size,
275 DMA_MODE_READ | DMA_AUTOINIT);
276
277 snd_ad1816a_write(chip, AD1816A_CAPTURE_SAMPLE_RATE, runtime->rate);
278 snd_ad1816a_out_mask(chip, AD1816A_CAPTURE_CONFIG,
279 AD1816A_FMT_ALL | AD1816A_FMT_STEREO,
280 snd_ad1816a_get_format(chip, runtime->format,
281 runtime->channels));
282
283 snd_ad1816a_write(chip, AD1816A_CAPTURE_BASE_COUNT,
284 snd_pcm_lib_period_bytes(substream) / 4 - 1);
285
286 spin_unlock_irqrestore(&chip->lock, flags);
287 return 0;
288}
289
290
291static snd_pcm_uframes_t snd_ad1816a_playback_pointer(snd_pcm_substream_t *substream)
292{
293 ad1816a_t *chip = snd_pcm_substream_chip(substream);
294 size_t ptr;
295 if (!(chip->mode & AD1816A_MODE_PLAYBACK))
296 return 0;
297 ptr = snd_dma_pointer(chip->dma1, chip->p_dma_size);
298 return bytes_to_frames(substream->runtime, ptr);
299}
300
301static snd_pcm_uframes_t snd_ad1816a_capture_pointer(snd_pcm_substream_t *substream)
302{
303 ad1816a_t *chip = snd_pcm_substream_chip(substream);
304 size_t ptr;
305 if (!(chip->mode & AD1816A_MODE_CAPTURE))
306 return 0;
307 ptr = snd_dma_pointer(chip->dma2, chip->c_dma_size);
308 return bytes_to_frames(substream->runtime, ptr);
309}
310
311
312static irqreturn_t snd_ad1816a_interrupt(int irq, void *dev_id, struct pt_regs *regs)
313{
314 ad1816a_t *chip = dev_id;
315 unsigned char status;
316
317 spin_lock(&chip->lock);
318 status = snd_ad1816a_in(chip, AD1816A_INTERRUPT_STATUS);
319 spin_unlock(&chip->lock);
320
321 if ((status & AD1816A_PLAYBACK_IRQ_PENDING) && chip->playback_substream)
322 snd_pcm_period_elapsed(chip->playback_substream);
323
324 if ((status & AD1816A_CAPTURE_IRQ_PENDING) && chip->capture_substream)
325 snd_pcm_period_elapsed(chip->capture_substream);
326
327 if ((status & AD1816A_TIMER_IRQ_PENDING) && chip->timer)
328 snd_timer_interrupt(chip->timer, chip->timer->sticks);
329
330 spin_lock(&chip->lock);
331 snd_ad1816a_out(chip, AD1816A_INTERRUPT_STATUS, 0x00);
332 spin_unlock(&chip->lock);
333 return IRQ_HANDLED;
334}
335
336
337static snd_pcm_hardware_t snd_ad1816a_playback = {
338 .info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED |
339 SNDRV_PCM_INFO_MMAP_VALID),
340 .formats = (SNDRV_PCM_FMTBIT_MU_LAW | SNDRV_PCM_FMTBIT_A_LAW |
341 SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S16_LE |
342 SNDRV_PCM_FMTBIT_S16_BE),
343 .rates = SNDRV_PCM_RATE_CONTINUOUS | SNDRV_PCM_RATE_8000_48000,
344 .rate_min = 4000,
345 .rate_max = 55200,
346 .channels_min = 1,
347 .channels_max = 2,
348 .buffer_bytes_max = (128*1024),
349 .period_bytes_min = 64,
350 .period_bytes_max = (128*1024),
351 .periods_min = 1,
352 .periods_max = 1024,
353 .fifo_size = 0,
354};
355
356static snd_pcm_hardware_t snd_ad1816a_capture = {
357 .info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED |
358 SNDRV_PCM_INFO_MMAP_VALID),
359 .formats = (SNDRV_PCM_FMTBIT_MU_LAW | SNDRV_PCM_FMTBIT_A_LAW |
360 SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S16_LE |
361 SNDRV_PCM_FMTBIT_S16_BE),
362 .rates = SNDRV_PCM_RATE_CONTINUOUS | SNDRV_PCM_RATE_8000_48000,
363 .rate_min = 4000,
364 .rate_max = 55200,
365 .channels_min = 1,
366 .channels_max = 2,
367 .buffer_bytes_max = (128*1024),
368 .period_bytes_min = 64,
369 .period_bytes_max = (128*1024),
370 .periods_min = 1,
371 .periods_max = 1024,
372 .fifo_size = 0,
373};
374
375#if 0 /* not used now */
376static int snd_ad1816a_timer_close(snd_timer_t *timer)
377{
378 ad1816a_t *chip = snd_timer_chip(timer);
379 snd_ad1816a_close(chip, AD1816A_MODE_TIMER);
380 return 0;
381}
382
383static int snd_ad1816a_timer_open(snd_timer_t *timer)
384{
385 ad1816a_t *chip = snd_timer_chip(timer);
386 snd_ad1816a_open(chip, AD1816A_MODE_TIMER);
387 return 0;
388}
389
390static unsigned long snd_ad1816a_timer_resolution(snd_timer_t *timer)
391{
392 snd_assert(timer != NULL, return 0);
393
394 return 10000;
395}
396
397static int snd_ad1816a_timer_start(snd_timer_t *timer)
398{
399 unsigned short bits;
400 unsigned long flags;
401 ad1816a_t *chip = snd_timer_chip(timer);
402 spin_lock_irqsave(&chip->lock, flags);
403 bits = snd_ad1816a_read(chip, AD1816A_INTERRUPT_ENABLE);
404
405 if (!(bits & AD1816A_TIMER_ENABLE)) {
406 snd_ad1816a_write(chip, AD1816A_TIMER_BASE_COUNT,
407 timer->sticks & 0xffff);
408
409 snd_ad1816a_write_mask(chip, AD1816A_INTERRUPT_ENABLE,
410 AD1816A_TIMER_ENABLE, 0xffff);
411 }
412 spin_unlock_irqrestore(&chip->lock, flags);
413 return 0;
414}
415
416static int snd_ad1816a_timer_stop(snd_timer_t *timer)
417{
418 unsigned long flags;
419 ad1816a_t *chip = snd_timer_chip(timer);
420 spin_lock_irqsave(&chip->lock, flags);
421
422 snd_ad1816a_write_mask(chip, AD1816A_INTERRUPT_ENABLE,
423 AD1816A_TIMER_ENABLE, 0x0000);
424
425 spin_unlock_irqrestore(&chip->lock, flags);
426 return 0;
427}
428
429static struct _snd_timer_hardware snd_ad1816a_timer_table = {
430 .flags = SNDRV_TIMER_HW_AUTO,
431 .resolution = 10000,
432 .ticks = 65535,
433 .open = snd_ad1816a_timer_open,
434 .close = snd_ad1816a_timer_close,
435 .c_resolution = snd_ad1816a_timer_resolution,
436 .start = snd_ad1816a_timer_start,
437 .stop = snd_ad1816a_timer_stop,
438};
439#endif /* not used now */
440
441
442static int snd_ad1816a_playback_open(snd_pcm_substream_t *substream)
443{
444 ad1816a_t *chip = snd_pcm_substream_chip(substream);
445 snd_pcm_runtime_t *runtime = substream->runtime;
446 int error;
447
448 if ((error = snd_ad1816a_open(chip, AD1816A_MODE_PLAYBACK)) < 0)
449 return error;
450 snd_pcm_set_sync(substream);
451 runtime->hw = snd_ad1816a_playback;
452 snd_pcm_limit_isa_dma_size(chip->dma1, &runtime->hw.buffer_bytes_max);
453 snd_pcm_limit_isa_dma_size(chip->dma1, &runtime->hw.period_bytes_max);
454 chip->playback_substream = substream;
455 return 0;
456}
457
458static int snd_ad1816a_capture_open(snd_pcm_substream_t *substream)
459{
460 ad1816a_t *chip = snd_pcm_substream_chip(substream);
461 snd_pcm_runtime_t *runtime = substream->runtime;
462 int error;
463
464 if ((error = snd_ad1816a_open(chip, AD1816A_MODE_CAPTURE)) < 0)
465 return error;
466 snd_pcm_set_sync(substream);
467 runtime->hw = snd_ad1816a_capture;
468 snd_pcm_limit_isa_dma_size(chip->dma2, &runtime->hw.buffer_bytes_max);
469 snd_pcm_limit_isa_dma_size(chip->dma2, &runtime->hw.period_bytes_max);
470 chip->capture_substream = substream;
471 return 0;
472}
473
474static int snd_ad1816a_playback_close(snd_pcm_substream_t *substream)
475{
476 ad1816a_t *chip = snd_pcm_substream_chip(substream);
477
478 chip->playback_substream = NULL;
479 snd_ad1816a_close(chip, AD1816A_MODE_PLAYBACK);
480 return 0;
481}
482
483static int snd_ad1816a_capture_close(snd_pcm_substream_t *substream)
484{
485 ad1816a_t *chip = snd_pcm_substream_chip(substream);
486
487 chip->capture_substream = NULL;
488 snd_ad1816a_close(chip, AD1816A_MODE_CAPTURE);
489 return 0;
490}
491
492
493static void snd_ad1816a_init(ad1816a_t *chip)
494{
495 unsigned long flags;
496
497 spin_lock_irqsave(&chip->lock, flags);
498
499 snd_ad1816a_out(chip, AD1816A_INTERRUPT_STATUS, 0x00);
500 snd_ad1816a_out_mask(chip, AD1816A_PLAYBACK_CONFIG,
501 AD1816A_PLAYBACK_ENABLE | AD1816A_PLAYBACK_PIO, 0x00);
502 snd_ad1816a_out_mask(chip, AD1816A_CAPTURE_CONFIG,
503 AD1816A_CAPTURE_ENABLE | AD1816A_CAPTURE_PIO, 0x00);
504 snd_ad1816a_write(chip, AD1816A_INTERRUPT_ENABLE, 0x0000);
505 snd_ad1816a_write_mask(chip, AD1816A_CHIP_CONFIG,
506 AD1816A_CAPTURE_NOT_EQUAL | AD1816A_WSS_ENABLE, 0xffff);
507 snd_ad1816a_write(chip, AD1816A_DSP_CONFIG, 0x0000);
508 snd_ad1816a_write(chip, AD1816A_POWERDOWN_CTRL, 0x0000);
509
510 spin_unlock_irqrestore(&chip->lock, flags);
511}
512
513static int snd_ad1816a_probe(ad1816a_t *chip)
514{
515 unsigned long flags;
516
517 spin_lock_irqsave(&chip->lock, flags);
518
519 switch (chip->version = snd_ad1816a_read(chip, AD1816A_VERSION_ID)) {
520 case 0:
521 chip->hardware = AD1816A_HW_AD1815;
522 break;
523 case 1:
524 chip->hardware = AD1816A_HW_AD18MAX10;
525 break;
526 case 3:
527 chip->hardware = AD1816A_HW_AD1816A;
528 break;
529 default:
530 chip->hardware = AD1816A_HW_AUTO;
531 }
532
533 spin_unlock_irqrestore(&chip->lock, flags);
534 return 0;
535}
536
537static int snd_ad1816a_free(ad1816a_t *chip)
538{
539 if (chip->res_port) {
540 release_resource(chip->res_port);
541 kfree_nocheck(chip->res_port);
542 }
543 if (chip->irq >= 0)
544 free_irq(chip->irq, (void *) chip);
545 if (chip->dma1 >= 0) {
546 snd_dma_disable(chip->dma1);
547 free_dma(chip->dma1);
548 }
549 if (chip->dma2 >= 0) {
550 snd_dma_disable(chip->dma2);
551 free_dma(chip->dma2);
552 }
553 kfree(chip);
554 return 0;
555}
556
557static int snd_ad1816a_dev_free(snd_device_t *device)
558{
559 ad1816a_t *chip = device->device_data;
560 return snd_ad1816a_free(chip);
561}
562
563static const char *snd_ad1816a_chip_id(ad1816a_t *chip)
564{
565 switch (chip->hardware) {
566 case AD1816A_HW_AD1816A: return "AD1816A";
567 case AD1816A_HW_AD1815: return "AD1815";
568 case AD1816A_HW_AD18MAX10: return "AD18max10";
569 default:
570 snd_printk("Unknown chip version %d:%d.\n",
571 chip->version, chip->hardware);
572 return "AD1816A - unknown";
573 }
574}
575
576int snd_ad1816a_create(snd_card_t *card,
577 unsigned long port, int irq, int dma1, int dma2,
578 ad1816a_t **rchip)
579{
580 static snd_device_ops_t ops = {
581 .dev_free = snd_ad1816a_dev_free,
582 };
583 int error;
584 ad1816a_t *chip;
585
586 *rchip = NULL;
587
588 chip = kcalloc(1, sizeof(*chip), GFP_KERNEL);
589 if (chip == NULL)
590 return -ENOMEM;
591 chip->irq = -1;
592 chip->dma1 = -1;
593 chip->dma2 = -1;
594
595 if ((chip->res_port = request_region(port, 16, "AD1816A")) == NULL) {
596 snd_printk(KERN_ERR "ad1816a: can't grab port 0x%lx\n", port);
597 snd_ad1816a_free(chip);
598 return -EBUSY;
599 }
600 if (request_irq(irq, snd_ad1816a_interrupt, SA_INTERRUPT, "AD1816A", (void *) chip)) {
601 snd_printk(KERN_ERR "ad1816a: can't grab IRQ %d\n", irq);
602 snd_ad1816a_free(chip);
603 return -EBUSY;
604 }
605 chip->irq = irq;
606 if (request_dma(dma1, "AD1816A - 1")) {
607 snd_printk(KERN_ERR "ad1816a: can't grab DMA1 %d\n", dma1);
608 snd_ad1816a_free(chip);
609 return -EBUSY;
610 }
611 chip->dma1 = dma1;
612 if (request_dma(dma2, "AD1816A - 2")) {
613 snd_printk(KERN_ERR "ad1816a: can't grab DMA2 %d\n", dma2);
614 snd_ad1816a_free(chip);
615 return -EBUSY;
616 }
617 chip->dma2 = dma2;
618
619 chip->card = card;
620 chip->port = port;
621 spin_lock_init(&chip->lock);
622
623 if ((error = snd_ad1816a_probe(chip))) {
624 snd_ad1816a_free(chip);
625 return error;
626 }
627
628 snd_ad1816a_init(chip);
629
630 /* Register device */
631 if ((error = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops)) < 0) {
632 snd_ad1816a_free(chip);
633 return error;
634 }
635
636 *rchip = chip;
637 return 0;
638}
639
640static snd_pcm_ops_t snd_ad1816a_playback_ops = {
641 .open = snd_ad1816a_playback_open,
642 .close = snd_ad1816a_playback_close,
643 .ioctl = snd_pcm_lib_ioctl,
644 .hw_params = snd_ad1816a_hw_params,
645 .hw_free = snd_ad1816a_hw_free,
646 .prepare = snd_ad1816a_playback_prepare,
647 .trigger = snd_ad1816a_playback_trigger,
648 .pointer = snd_ad1816a_playback_pointer,
649};
650
651static snd_pcm_ops_t snd_ad1816a_capture_ops = {
652 .open = snd_ad1816a_capture_open,
653 .close = snd_ad1816a_capture_close,
654 .ioctl = snd_pcm_lib_ioctl,
655 .hw_params = snd_ad1816a_hw_params,
656 .hw_free = snd_ad1816a_hw_free,
657 .prepare = snd_ad1816a_capture_prepare,
658 .trigger = snd_ad1816a_capture_trigger,
659 .pointer = snd_ad1816a_capture_pointer,
660};
661
662static void snd_ad1816a_pcm_free(snd_pcm_t *pcm)
663{
664 ad1816a_t *chip = pcm->private_data;
665 chip->pcm = NULL;
666 snd_pcm_lib_preallocate_free_for_all(pcm);
667}
668
669int snd_ad1816a_pcm(ad1816a_t *chip, int device, snd_pcm_t **rpcm)
670{
671 int error;
672 snd_pcm_t *pcm;
673
674 if ((error = snd_pcm_new(chip->card, "AD1816A", device, 1, 1, &pcm)))
675 return error;
676
677 snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_ad1816a_playback_ops);
678 snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_ad1816a_capture_ops);
679
680 pcm->private_data = chip;
681 pcm->private_free = snd_ad1816a_pcm_free;
682 pcm->info_flags = (chip->dma1 == chip->dma2 ) ? SNDRV_PCM_INFO_JOINT_DUPLEX : 0;
683
684 strcpy(pcm->name, snd_ad1816a_chip_id(chip));
685 snd_ad1816a_init(chip);
686
687 snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV,
688 snd_dma_isa_data(),
689 64*1024, chip->dma1 > 3 || chip->dma2 > 3 ? 128*1024 : 64*1024);
690
691 chip->pcm = pcm;
692 if (rpcm)
693 *rpcm = pcm;
694 return 0;
695}
696
697#if 0 /* not used now */
698static void snd_ad1816a_timer_free(snd_timer_t *timer)
699{
700 ad1816a_t *chip = timer->private_data;
701 chip->timer = NULL;
702}
703
704int snd_ad1816a_timer(ad1816a_t *chip, int device, snd_timer_t **rtimer)
705{
706 snd_timer_t *timer;
707 snd_timer_id_t tid;
708 int error;
709
710 tid.dev_class = SNDRV_TIMER_CLASS_CARD;
711 tid.dev_sclass = SNDRV_TIMER_SCLASS_NONE;
712 tid.card = chip->card->number;
713 tid.device = device;
714 tid.subdevice = 0;
715 if ((error = snd_timer_new(chip->card, "AD1816A", &tid, &timer)) < 0)
716 return error;
717 strcpy(timer->name, snd_ad1816a_chip_id(chip));
718 timer->private_data = chip;
719 timer->private_free = snd_ad1816a_timer_free;
720 chip->timer = timer;
721 timer->hw = snd_ad1816a_timer_table;
722 if (rtimer)
723 *rtimer = timer;
724 return 0;
725}
726#endif /* not used now */
727
728/*
729 *
730 */
731
732static int snd_ad1816a_info_mux(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
733{
734 static char *texts[8] = {
735 "Line", "Mix", "CD", "Synth", "Video",
736 "Mic", "Phone",
737 };
738
739 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
740 uinfo->count = 2;
741 uinfo->value.enumerated.items = 7;
742 if (uinfo->value.enumerated.item > 6)
743 uinfo->value.enumerated.item = 6;
744 strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]);
745 return 0;
746}
747
748static int snd_ad1816a_get_mux(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
749{
750 ad1816a_t *chip = snd_kcontrol_chip(kcontrol);
751 unsigned long flags;
752 unsigned short val;
753
754 spin_lock_irqsave(&chip->lock, flags);
755 val = snd_ad1816a_read(chip, AD1816A_ADC_SOURCE_SEL);
756 spin_unlock_irqrestore(&chip->lock, flags);
757 ucontrol->value.enumerated.item[0] = (val >> 12) & 7;
758 ucontrol->value.enumerated.item[1] = (val >> 4) & 7;
759 return 0;
760}
761
762static int snd_ad1816a_put_mux(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
763{
764 ad1816a_t *chip = snd_kcontrol_chip(kcontrol);
765 unsigned long flags;
766 unsigned short val;
767 int change;
768
769 if (ucontrol->value.enumerated.item[0] > 6 ||
770 ucontrol->value.enumerated.item[1] > 6)
771 return -EINVAL;
772 val = (ucontrol->value.enumerated.item[0] << 12) |
773 (ucontrol->value.enumerated.item[1] << 4);
774 spin_lock_irqsave(&chip->lock, flags);
775 change = snd_ad1816a_read(chip, AD1816A_ADC_SOURCE_SEL) != val;
776 snd_ad1816a_write(chip, AD1816A_ADC_SOURCE_SEL, val);
777 spin_unlock_irqrestore(&chip->lock, flags);
778 return change;
779}
780
781#define AD1816A_SINGLE(xname, reg, shift, mask, invert) \
782{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .info = snd_ad1816a_info_single, \
783 .get = snd_ad1816a_get_single, .put = snd_ad1816a_put_single, \
784 .private_value = reg | (shift << 8) | (mask << 16) | (invert << 24) }
785
786static int snd_ad1816a_info_single(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
787{
788 int mask = (kcontrol->private_value >> 16) & 0xff;
789
790 uinfo->type = mask == 1 ? SNDRV_CTL_ELEM_TYPE_BOOLEAN : SNDRV_CTL_ELEM_TYPE_INTEGER;
791 uinfo->count = 1;
792 uinfo->value.integer.min = 0;
793 uinfo->value.integer.max = mask;
794 return 0;
795}
796
797static int snd_ad1816a_get_single(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
798{
799 ad1816a_t *chip = snd_kcontrol_chip(kcontrol);
800 unsigned long flags;
801 int reg = kcontrol->private_value & 0xff;
802 int shift = (kcontrol->private_value >> 8) & 0xff;
803 int mask = (kcontrol->private_value >> 16) & 0xff;
804 int invert = (kcontrol->private_value >> 24) & 0xff;
805
806 spin_lock_irqsave(&chip->lock, flags);
807 ucontrol->value.integer.value[0] = (snd_ad1816a_read(chip, reg) >> shift) & mask;
808 spin_unlock_irqrestore(&chip->lock, flags);
809 if (invert)
810 ucontrol->value.integer.value[0] = mask - ucontrol->value.integer.value[0];
811 return 0;
812}
813
814static int snd_ad1816a_put_single(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
815{
816 ad1816a_t *chip = snd_kcontrol_chip(kcontrol);
817 unsigned long flags;
818 int reg = kcontrol->private_value & 0xff;
819 int shift = (kcontrol->private_value >> 8) & 0xff;
820 int mask = (kcontrol->private_value >> 16) & 0xff;
821 int invert = (kcontrol->private_value >> 24) & 0xff;
822 int change;
823 unsigned short old_val, val;
824
825 val = (ucontrol->value.integer.value[0] & mask);
826 if (invert)
827 val = mask - val;
828 val <<= shift;
829 spin_lock_irqsave(&chip->lock, flags);
830 old_val = snd_ad1816a_read(chip, reg);
831 val = (old_val & ~(mask << shift)) | val;
832 change = val != old_val;
833 snd_ad1816a_write(chip, reg, val);
834 spin_unlock_irqrestore(&chip->lock, flags);
835 return change;
836}
837
838#define AD1816A_DOUBLE(xname, reg, shift_left, shift_right, mask, invert) \
839{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .info = snd_ad1816a_info_double, \
840 .get = snd_ad1816a_get_double, .put = snd_ad1816a_put_double, \
841 .private_value = reg | (shift_left << 8) | (shift_right << 12) | (mask << 16) | (invert << 24) }
842
843static int snd_ad1816a_info_double(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
844{
845 int mask = (kcontrol->private_value >> 16) & 0xff;
846
847 uinfo->type = mask == 1 ? SNDRV_CTL_ELEM_TYPE_BOOLEAN : SNDRV_CTL_ELEM_TYPE_INTEGER;
848 uinfo->count = 2;
849 uinfo->value.integer.min = 0;
850 uinfo->value.integer.max = mask;
851 return 0;
852}
853
854static int snd_ad1816a_get_double(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
855{
856 ad1816a_t *chip = snd_kcontrol_chip(kcontrol);
857 unsigned long flags;
858 int reg = kcontrol->private_value & 0xff;
859 int shift_left = (kcontrol->private_value >> 8) & 0x0f;
860 int shift_right = (kcontrol->private_value >> 12) & 0x0f;
861 int mask = (kcontrol->private_value >> 16) & 0xff;
862 int invert = (kcontrol->private_value >> 24) & 0xff;
863 unsigned short val;
864
865 spin_lock_irqsave(&chip->lock, flags);
866 val = snd_ad1816a_read(chip, reg);
867 ucontrol->value.integer.value[0] = (val >> shift_left) & mask;
868 ucontrol->value.integer.value[1] = (val >> shift_right) & mask;
869 spin_unlock_irqrestore(&chip->lock, flags);
870 if (invert) {
871 ucontrol->value.integer.value[0] = mask - ucontrol->value.integer.value[0];
872 ucontrol->value.integer.value[1] = mask - ucontrol->value.integer.value[1];
873 }
874 return 0;
875}
876
877static int snd_ad1816a_put_double(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
878{
879 ad1816a_t *chip = snd_kcontrol_chip(kcontrol);
880 unsigned long flags;
881 int reg = kcontrol->private_value & 0xff;
882 int shift_left = (kcontrol->private_value >> 8) & 0x0f;
883 int shift_right = (kcontrol->private_value >> 12) & 0x0f;
884 int mask = (kcontrol->private_value >> 16) & 0xff;
885 int invert = (kcontrol->private_value >> 24) & 0xff;
886 int change;
887 unsigned short old_val, val1, val2;
888
889 val1 = ucontrol->value.integer.value[0] & mask;
890 val2 = ucontrol->value.integer.value[1] & mask;
891 if (invert) {
892 val1 = mask - val1;
893 val2 = mask - val2;
894 }
895 val1 <<= shift_left;
896 val2 <<= shift_right;
897 spin_lock_irqsave(&chip->lock, flags);
898 old_val = snd_ad1816a_read(chip, reg);
899 val1 = (old_val & ~((mask << shift_left) | (mask << shift_right))) | val1 | val2;
900 change = val1 != old_val;
901 snd_ad1816a_write(chip, reg, val1);
902 spin_unlock_irqrestore(&chip->lock, flags);
903 return change;
904}
905
906static snd_kcontrol_new_t snd_ad1816a_controls[] = {
907AD1816A_DOUBLE("Master Playback Switch", AD1816A_MASTER_ATT, 15, 7, 1, 1),
908AD1816A_DOUBLE("Master Playback Volume", AD1816A_MASTER_ATT, 8, 0, 31, 1),
909AD1816A_DOUBLE("PCM Playback Switch", AD1816A_VOICE_ATT, 15, 7, 1, 1),
910AD1816A_DOUBLE("PCM Playback Volume", AD1816A_VOICE_ATT, 8, 0, 63, 1),
911AD1816A_DOUBLE("Line Playback Switch", AD1816A_LINE_GAIN_ATT, 15, 7, 1, 1),
912AD1816A_DOUBLE("Line Playback Volume", AD1816A_LINE_GAIN_ATT, 8, 0, 31, 1),
913AD1816A_DOUBLE("CD Playback Switch", AD1816A_CD_GAIN_ATT, 15, 7, 1, 1),
914AD1816A_DOUBLE("CD Playback Volume", AD1816A_CD_GAIN_ATT, 8, 0, 31, 1),
915AD1816A_DOUBLE("Synth Playback Switch", AD1816A_SYNTH_GAIN_ATT, 15, 7, 1, 1),
916AD1816A_DOUBLE("Synth Playback Volume", AD1816A_SYNTH_GAIN_ATT, 8, 0, 31, 1),
917AD1816A_DOUBLE("FM Playback Switch", AD1816A_FM_ATT, 15, 7, 1, 1),
918AD1816A_DOUBLE("FM Playback Volume", AD1816A_FM_ATT, 8, 0, 63, 1),
919AD1816A_SINGLE("Mic Playback Switch", AD1816A_MIC_GAIN_ATT, 15, 1, 1),
920AD1816A_SINGLE("Mic Playback Volume", AD1816A_MIC_GAIN_ATT, 8, 31, 1),
921AD1816A_SINGLE("Mic Boost", AD1816A_MIC_GAIN_ATT, 14, 1, 0),
922AD1816A_DOUBLE("Video Playback Switch", AD1816A_VID_GAIN_ATT, 15, 7, 1, 1),
923AD1816A_DOUBLE("Video Playback Volume", AD1816A_VID_GAIN_ATT, 8, 0, 31, 1),
924AD1816A_SINGLE("Phone Capture Switch", AD1816A_PHONE_IN_GAIN_ATT, 15, 1, 1),
925AD1816A_SINGLE("Phone Capture Volume", AD1816A_PHONE_IN_GAIN_ATT, 0, 15, 1),
926AD1816A_SINGLE("Phone Playback Switch", AD1816A_PHONE_OUT_ATT, 7, 1, 1),
927AD1816A_SINGLE("Phone Playback Volume", AD1816A_PHONE_OUT_ATT, 0, 31, 1),
928{
929 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
930 .name = "Capture Source",
931 .info = snd_ad1816a_info_mux,
932 .get = snd_ad1816a_get_mux,
933 .put = snd_ad1816a_put_mux,
934},
935AD1816A_DOUBLE("Capture Switch", AD1816A_ADC_PGA, 15, 7, 1, 1),
936AD1816A_DOUBLE("Capture Volume", AD1816A_ADC_PGA, 8, 0, 15, 0),
937AD1816A_SINGLE("3D Control - Switch", AD1816A_3D_PHAT_CTRL, 15, 1, 1),
938AD1816A_SINGLE("3D Control - Level", AD1816A_3D_PHAT_CTRL, 0, 15, 0),
939};
940
941int snd_ad1816a_mixer(ad1816a_t *chip)
942{
943 snd_card_t *card;
944 unsigned int idx;
945 int err;
946
947 snd_assert(chip != NULL && chip->card != NULL, return -EINVAL);
948
949 card = chip->card;
950
951 strcpy(card->mixername, snd_ad1816a_chip_id(chip));
952
953 for (idx = 0; idx < ARRAY_SIZE(snd_ad1816a_controls); idx++) {
954 if ((err = snd_ctl_add(card, snd_ctl_new1(&snd_ad1816a_controls[idx], chip))) < 0)
955 return err;
956 }
957 return 0;
958}
959
960EXPORT_SYMBOL(snd_ad1816a_create);
961EXPORT_SYMBOL(snd_ad1816a_pcm);
962EXPORT_SYMBOL(snd_ad1816a_mixer);
963
964static int __init alsa_ad1816a_init(void)
965{
966 return 0;
967}
968
969static void __exit alsa_ad1816a_exit(void)
970{
971}
972
973module_init(alsa_ad1816a_init)
974module_exit(alsa_ad1816a_exit)
diff --git a/sound/isa/ad1848/Makefile b/sound/isa/ad1848/Makefile
new file mode 100644
index 000000000000..45d59998aa69
--- /dev/null
+++ b/sound/isa/ad1848/Makefile
@@ -0,0 +1,15 @@
1#
2# Makefile for ALSA
3# Copyright (c) 2001 by Jaroslav Kysela <perex@suse.cz>
4#
5
6snd-ad1848-lib-objs := ad1848_lib.o
7snd-ad1848-objs := ad1848.o
8
9# Toplevel Module Dependency
10obj-$(CONFIG_SND_CMI8330) += snd-ad1848-lib.o
11obj-$(CONFIG_SND_SGALAXY) += snd-ad1848-lib.o
12obj-$(CONFIG_SND_AD1848) += snd-ad1848.o snd-ad1848-lib.o
13obj-$(CONFIG_SND_OPTI92X_AD1848) += snd-ad1848-lib.o
14
15obj-m := $(sort $(obj-m))
diff --git a/sound/isa/ad1848/ad1848.c b/sound/isa/ad1848/ad1848.c
new file mode 100644
index 000000000000..8c399340cd72
--- /dev/null
+++ b/sound/isa/ad1848/ad1848.c
@@ -0,0 +1,151 @@
1/*
2 * Generic driver for AD1848/AD1847/CS4248 chips (0.1 Alpha)
3 * Copyright (c) by Tugrul Galatali <galatalt@stuy.edu>,
4 * Jaroslav Kysela <perex@suse.cz>
5 * Based on card-4232.c by Jaroslav Kysela <perex@suse.cz>
6 *
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21 *
22 */
23
24#include <sound/driver.h>
25#include <linux/init.h>
26#include <linux/time.h>
27#include <linux/wait.h>
28#include <linux/moduleparam.h>
29#include <sound/core.h>
30#include <sound/ad1848.h>
31#include <sound/initval.h>
32
33MODULE_AUTHOR("Tugrul Galatali <galatalt@stuy.edu>, Jaroslav Kysela <perex@suse.cz>");
34MODULE_DESCRIPTION("AD1848/AD1847/CS4248");
35MODULE_LICENSE("GPL");
36MODULE_SUPPORTED_DEVICE("{{Analog Devices,AD1848},"
37 "{Analog Devices,AD1847},"
38 "{Crystal Semiconductors,CS4248}}");
39
40static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-MAX */
41static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* ID for this card */
42static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE; /* Enable this card */
43static long port[SNDRV_CARDS] = SNDRV_DEFAULT_PORT; /* PnP setup */
44static int irq[SNDRV_CARDS] = SNDRV_DEFAULT_IRQ; /* 5,7,9,11,12,15 */
45static int dma1[SNDRV_CARDS] = SNDRV_DEFAULT_DMA; /* 0,1,3,5,6,7 */
46static int thinkpad[SNDRV_CARDS]; /* Thinkpad special case */
47
48module_param_array(index, int, NULL, 0444);
49MODULE_PARM_DESC(index, "Index value for AD1848 soundcard.");
50module_param_array(id, charp, NULL, 0444);
51MODULE_PARM_DESC(id, "ID string for AD1848 soundcard.");
52module_param_array(enable, bool, NULL, 0444);
53MODULE_PARM_DESC(enable, "Enable AD1848 soundcard.");
54module_param_array(port, long, NULL, 0444);
55MODULE_PARM_DESC(port, "Port # for AD1848 driver.");
56module_param_array(irq, int, NULL, 0444);
57MODULE_PARM_DESC(irq, "IRQ # for AD1848 driver.");
58module_param_array(dma1, int, NULL, 0444);
59MODULE_PARM_DESC(dma1, "DMA1 # for AD1848 driver.");
60module_param_array(thinkpad, bool, NULL, 0444);
61MODULE_PARM_DESC(thinkpad, "Enable only for the onboard CS4248 of IBM Thinkpad 360/750/755 series.");
62
63static snd_card_t *snd_ad1848_cards[SNDRV_CARDS] = SNDRV_DEFAULT_PTR;
64
65
66static int __init snd_card_ad1848_probe(int dev)
67{
68 snd_card_t *card;
69 ad1848_t *chip;
70 snd_pcm_t *pcm;
71 int err;
72
73 if (port[dev] == SNDRV_AUTO_PORT) {
74 snd_printk(KERN_ERR "ad1848: specify port\n");
75 return -EINVAL;
76 }
77 if (irq[dev] == SNDRV_AUTO_IRQ) {
78 snd_printk(KERN_ERR "ad1848: specify irq\n");
79 return -EINVAL;
80 }
81 if (dma1[dev] == SNDRV_AUTO_DMA) {
82 snd_printk(KERN_ERR "ad1848: specify dma1\n");
83 return -EINVAL;
84 }
85
86 card = snd_card_new(index[dev], id[dev], THIS_MODULE, 0);
87 if (card == NULL)
88 return -ENOMEM;
89
90 if ((err = snd_ad1848_create(card, port[dev],
91 irq[dev],
92 dma1[dev],
93 thinkpad[dev] ? AD1848_HW_THINKPAD : AD1848_HW_DETECT,
94 &chip)) < 0) {
95 snd_card_free(card);
96 return err;
97 }
98
99 if ((err = snd_ad1848_pcm(chip, 0, &pcm)) < 0) {
100 snd_card_free(card);
101 return err;
102 }
103 if ((err = snd_ad1848_mixer(chip)) < 0) {
104 snd_card_free(card);
105 return err;
106 }
107 strcpy(card->driver, "AD1848");
108 strcpy(card->shortname, pcm->name);
109
110 sprintf(card->longname, "%s at 0x%lx, irq %d, dma %d",
111 pcm->name, chip->port, irq[dev], dma1[dev]);
112
113 if (thinkpad[dev]) {
114 strcat(card->longname, " [Thinkpad]");
115 }
116
117 if ((err = snd_card_register(card)) < 0) {
118 snd_card_free(card);
119 return err;
120 }
121 snd_ad1848_cards[dev] = card;
122 return 0;
123}
124
125static int __init alsa_card_ad1848_init(void)
126{
127 int dev, cards;
128
129 for (dev = cards = 0; dev < SNDRV_CARDS && enable[dev]; dev++)
130 if (snd_card_ad1848_probe(dev) >= 0)
131 cards++;
132
133 if (!cards) {
134#ifdef MODULE
135 printk(KERN_ERR "AD1848 soundcard not found or device busy\n");
136#endif
137 return -ENODEV;
138 }
139 return 0;
140}
141
142static void __exit alsa_card_ad1848_exit(void)
143{
144 int idx;
145
146 for (idx = 0; idx < SNDRV_CARDS; idx++)
147 snd_card_free(snd_ad1848_cards[idx]);
148}
149
150module_init(alsa_card_ad1848_init)
151module_exit(alsa_card_ad1848_exit)
diff --git a/sound/isa/ad1848/ad1848_lib.c b/sound/isa/ad1848/ad1848_lib.c
new file mode 100644
index 000000000000..8fb3db103e48
--- /dev/null
+++ b/sound/isa/ad1848/ad1848_lib.c
@@ -0,0 +1,1279 @@
1/*
2 * Copyright (c) by Jaroslav Kysela <perex@suse.cz>
3 * Routines for control of AD1848/AD1847/CS4248
4 *
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 *
20 */
21
22#define SNDRV_MAIN_OBJECT_FILE
23#include <sound/driver.h>
24#include <linux/delay.h>
25#include <linux/init.h>
26#include <linux/interrupt.h>
27#include <linux/pm.h>
28#include <linux/slab.h>
29#include <linux/ioport.h>
30#include <sound/core.h>
31#include <sound/ad1848.h>
32#include <sound/control.h>
33#include <sound/pcm_params.h>
34
35#include <asm/io.h>
36#include <asm/dma.h>
37
38MODULE_AUTHOR("Jaroslav Kysela <perex@suse.cz>");
39MODULE_DESCRIPTION("Routines for control of AD1848/AD1847/CS4248");
40MODULE_LICENSE("GPL");
41
42#if 0
43#define SNDRV_DEBUG_MCE
44#endif
45
46/*
47 * Some variables
48 */
49
50static unsigned char freq_bits[14] = {
51 /* 5510 */ 0x00 | AD1848_XTAL2,
52 /* 6620 */ 0x0E | AD1848_XTAL2,
53 /* 8000 */ 0x00 | AD1848_XTAL1,
54 /* 9600 */ 0x0E | AD1848_XTAL1,
55 /* 11025 */ 0x02 | AD1848_XTAL2,
56 /* 16000 */ 0x02 | AD1848_XTAL1,
57 /* 18900 */ 0x04 | AD1848_XTAL2,
58 /* 22050 */ 0x06 | AD1848_XTAL2,
59 /* 27042 */ 0x04 | AD1848_XTAL1,
60 /* 32000 */ 0x06 | AD1848_XTAL1,
61 /* 33075 */ 0x0C | AD1848_XTAL2,
62 /* 37800 */ 0x08 | AD1848_XTAL2,
63 /* 44100 */ 0x0A | AD1848_XTAL2,
64 /* 48000 */ 0x0C | AD1848_XTAL1
65};
66
67static unsigned int rates[14] = {
68 5510, 6620, 8000, 9600, 11025, 16000, 18900, 22050,
69 27042, 32000, 33075, 37800, 44100, 48000
70};
71
72static snd_pcm_hw_constraint_list_t hw_constraints_rates = {
73 .count = 14,
74 .list = rates,
75 .mask = 0,
76};
77
78static unsigned char snd_ad1848_original_image[16] =
79{
80 0x00, /* 00 - lic */
81 0x00, /* 01 - ric */
82 0x9f, /* 02 - la1ic */
83 0x9f, /* 03 - ra1ic */
84 0x9f, /* 04 - la2ic */
85 0x9f, /* 05 - ra2ic */
86 0xbf, /* 06 - loc */
87 0xbf, /* 07 - roc */
88 0x20, /* 08 - dfr */
89 AD1848_AUTOCALIB, /* 09 - ic */
90 0x00, /* 0a - pc */
91 0x00, /* 0b - ti */
92 0x00, /* 0c - mi */
93 0x00, /* 0d - lbc */
94 0x00, /* 0e - dru */
95 0x00, /* 0f - drl */
96};
97
98/*
99 * Basic I/O functions
100 */
101
102void snd_ad1848_out(ad1848_t *chip,
103 unsigned char reg,
104 unsigned char value)
105{
106 int timeout;
107
108 for (timeout = 250; timeout > 0 && (inb(AD1848P(chip, REGSEL)) & AD1848_INIT); timeout--)
109 udelay(100);
110#ifdef CONFIG_SND_DEBUG
111 if (inb(AD1848P(chip, REGSEL)) & AD1848_INIT)
112 snd_printk("auto calibration time out - reg = 0x%x, value = 0x%x\n", reg, value);
113#endif
114 outb(chip->mce_bit | reg, AD1848P(chip, REGSEL));
115 outb(chip->image[reg] = value, AD1848P(chip, REG));
116 mb();
117#if 0
118 printk("codec out - reg 0x%x = 0x%x\n", chip->mce_bit | reg, value);
119#endif
120}
121
122static void snd_ad1848_dout(ad1848_t *chip,
123 unsigned char reg, unsigned char value)
124{
125 int timeout;
126
127 for (timeout = 250; timeout > 0 && (inb(AD1848P(chip, REGSEL)) & AD1848_INIT); timeout--)
128 udelay(100);
129 outb(chip->mce_bit | reg, AD1848P(chip, REGSEL));
130 outb(value, AD1848P(chip, REG));
131 mb();
132}
133
134static unsigned char snd_ad1848_in(ad1848_t *chip, unsigned char reg)
135{
136 int timeout;
137
138 for (timeout = 250; timeout > 0 && (inb(AD1848P(chip, REGSEL)) & AD1848_INIT); timeout--)
139 udelay(100);
140#ifdef CONFIG_SND_DEBUG
141 if (inb(AD1848P(chip, REGSEL)) & AD1848_INIT)
142 snd_printk("auto calibration time out - reg = 0x%x\n", reg);
143#endif
144 outb(chip->mce_bit | reg, AD1848P(chip, REGSEL));
145 mb();
146 return inb(AD1848P(chip, REG));
147}
148
149#if 0
150
151static void snd_ad1848_debug(ad1848_t *chip)
152{
153 printk("AD1848 REGS: INDEX = 0x%02x ", inb(AD1848P(chip, REGSEL)));
154 printk(" STATUS = 0x%02x\n", inb(AD1848P(chip, STATUS)));
155 printk(" 0x00: left input = 0x%02x ", snd_ad1848_in(chip, 0x00));
156 printk(" 0x08: playback format = 0x%02x\n", snd_ad1848_in(chip, 0x08));
157 printk(" 0x01: right input = 0x%02x ", snd_ad1848_in(chip, 0x01));
158 printk(" 0x09: iface (CFIG 1) = 0x%02x\n", snd_ad1848_in(chip, 0x09));
159 printk(" 0x02: AUXA left = 0x%02x ", snd_ad1848_in(chip, 0x02));
160 printk(" 0x0a: pin control = 0x%02x\n", snd_ad1848_in(chip, 0x0a));
161 printk(" 0x03: AUXA right = 0x%02x ", snd_ad1848_in(chip, 0x03));
162 printk(" 0x0b: init & status = 0x%02x\n", snd_ad1848_in(chip, 0x0b));
163 printk(" 0x04: AUXB left = 0x%02x ", snd_ad1848_in(chip, 0x04));
164 printk(" 0x0c: revision & mode = 0x%02x\n", snd_ad1848_in(chip, 0x0c));
165 printk(" 0x05: AUXB right = 0x%02x ", snd_ad1848_in(chip, 0x05));
166 printk(" 0x0d: loopback = 0x%02x\n", snd_ad1848_in(chip, 0x0d));
167 printk(" 0x06: left output = 0x%02x ", snd_ad1848_in(chip, 0x06));
168 printk(" 0x0e: data upr count = 0x%02x\n", snd_ad1848_in(chip, 0x0e));
169 printk(" 0x07: right output = 0x%02x ", snd_ad1848_in(chip, 0x07));
170 printk(" 0x0f: data lwr count = 0x%02x\n", snd_ad1848_in(chip, 0x0f));
171}
172
173#endif
174
175/*
176 * AD1848 detection / MCE routines
177 */
178
179static void snd_ad1848_mce_up(ad1848_t *chip)
180{
181 unsigned long flags;
182 int timeout;
183
184 for (timeout = 250; timeout > 0 && (inb(AD1848P(chip, REGSEL)) & AD1848_INIT); timeout--)
185 udelay(100);
186#ifdef CONFIG_SND_DEBUG
187 if (inb(AD1848P(chip, REGSEL)) & AD1848_INIT)
188 snd_printk("mce_up - auto calibration time out (0)\n");
189#endif
190 spin_lock_irqsave(&chip->reg_lock, flags);
191 chip->mce_bit |= AD1848_MCE;
192 timeout = inb(AD1848P(chip, REGSEL));
193 if (timeout == 0x80)
194 snd_printk("mce_up [0x%lx]: serious init problem - codec still busy\n", chip->port);
195 if (!(timeout & AD1848_MCE))
196 outb(chip->mce_bit | (timeout & 0x1f), AD1848P(chip, REGSEL));
197 spin_unlock_irqrestore(&chip->reg_lock, flags);
198}
199
200static void snd_ad1848_mce_down(ad1848_t *chip)
201{
202 unsigned long flags;
203 int timeout;
204 signed long time;
205
206 spin_lock_irqsave(&chip->reg_lock, flags);
207 for (timeout = 5; timeout > 0; timeout--)
208 inb(AD1848P(chip, REGSEL));
209 /* end of cleanup sequence */
210 for (timeout = 12000; timeout > 0 && (inb(AD1848P(chip, REGSEL)) & AD1848_INIT); timeout--)
211 udelay(100);
212#if 0
213 printk("(1) timeout = %i\n", timeout);
214#endif
215#ifdef CONFIG_SND_DEBUG
216 if (inb(AD1848P(chip, REGSEL)) & AD1848_INIT)
217 snd_printk("mce_down [0x%lx] - auto calibration time out (0)\n", AD1848P(chip, REGSEL));
218#endif
219 chip->mce_bit &= ~AD1848_MCE;
220 timeout = inb(AD1848P(chip, REGSEL));
221 outb(chip->mce_bit | (timeout & 0x1f), AD1848P(chip, REGSEL));
222 if (timeout == 0x80)
223 snd_printk("mce_down [0x%lx]: serious init problem - codec still busy\n", chip->port);
224 if ((timeout & AD1848_MCE) == 0) {
225 spin_unlock_irqrestore(&chip->reg_lock, flags);
226 return;
227 }
228 /* calibration process */
229
230 for (timeout = 500; timeout > 0 && (snd_ad1848_in(chip, AD1848_TEST_INIT) & AD1848_CALIB_IN_PROGRESS) == 0; timeout--);
231 if ((snd_ad1848_in(chip, AD1848_TEST_INIT) & AD1848_CALIB_IN_PROGRESS) == 0) {
232 snd_printd("mce_down - auto calibration time out (1)\n");
233 spin_unlock_irqrestore(&chip->reg_lock, flags);
234 return;
235 }
236#if 0
237 printk("(2) timeout = %i, jiffies = %li\n", timeout, jiffies);
238#endif
239 time = HZ / 4;
240 while (snd_ad1848_in(chip, AD1848_TEST_INIT) & AD1848_CALIB_IN_PROGRESS) {
241 spin_unlock_irqrestore(&chip->reg_lock, flags);
242 if (time <= 0) {
243 snd_printk("mce_down - auto calibration time out (2)\n");
244 return;
245 }
246 set_current_state(TASK_INTERRUPTIBLE);
247 time = schedule_timeout(time);
248 spin_lock_irqsave(&chip->reg_lock, flags);
249 }
250#if 0
251 printk("(3) jiffies = %li\n", jiffies);
252#endif
253 time = HZ / 10;
254 while (inb(AD1848P(chip, REGSEL)) & AD1848_INIT) {
255 spin_unlock_irqrestore(&chip->reg_lock, flags);
256 if (time <= 0) {
257 snd_printk("mce_down - auto calibration time out (3)\n");
258 return;
259 }
260 set_current_state(TASK_INTERRUPTIBLE);
261 time = schedule_timeout(time);
262 spin_lock_irqsave(&chip->reg_lock, flags);
263 }
264 spin_unlock_irqrestore(&chip->reg_lock, flags);
265#if 0
266 printk("(4) jiffies = %li\n", jiffies);
267 snd_printk("mce_down - exit = 0x%x\n", inb(AD1848P(chip, REGSEL)));
268#endif
269}
270
271static unsigned int snd_ad1848_get_count(unsigned char format,
272 unsigned int size)
273{
274 switch (format & 0xe0) {
275 case AD1848_LINEAR_16:
276 size >>= 1;
277 break;
278 }
279 if (format & AD1848_STEREO)
280 size >>= 1;
281 return size;
282}
283
284static int snd_ad1848_trigger(ad1848_t *chip, unsigned char what,
285 int channel, int cmd)
286{
287 int result = 0;
288
289#if 0
290 printk("codec trigger!!! - what = %i, enable = %i, status = 0x%x\n", what, enable, inb(AD1848P(card, STATUS)));
291#endif
292 spin_lock(&chip->reg_lock);
293 if (cmd == SNDRV_PCM_TRIGGER_START) {
294 if (chip->image[AD1848_IFACE_CTRL] & what) {
295 spin_unlock(&chip->reg_lock);
296 return 0;
297 }
298 snd_ad1848_out(chip, AD1848_IFACE_CTRL, chip->image[AD1848_IFACE_CTRL] |= what);
299 chip->mode |= AD1848_MODE_RUNNING;
300 } else if (cmd == SNDRV_PCM_TRIGGER_STOP) {
301 if (!(chip->image[AD1848_IFACE_CTRL] & what)) {
302 spin_unlock(&chip->reg_lock);
303 return 0;
304 }
305 snd_ad1848_out(chip, AD1848_IFACE_CTRL, chip->image[AD1848_IFACE_CTRL] &= ~what);
306 chip->mode &= ~AD1848_MODE_RUNNING;
307 } else {
308 result = -EINVAL;
309 }
310 spin_unlock(&chip->reg_lock);
311 return result;
312}
313
314/*
315 * CODEC I/O
316 */
317
318static unsigned char snd_ad1848_get_rate(unsigned int rate)
319{
320 int i;
321
322 for (i = 0; i < 14; i++)
323 if (rate == rates[i])
324 return freq_bits[i];
325 snd_BUG();
326 return freq_bits[13];
327}
328
329static int snd_ad1848_ioctl(snd_pcm_substream_t * substream,
330 unsigned int cmd, void *arg)
331{
332 return snd_pcm_lib_ioctl(substream, cmd, arg);
333}
334
335static unsigned char snd_ad1848_get_format(int format, int channels)
336{
337 unsigned char rformat;
338
339 rformat = AD1848_LINEAR_8;
340 switch (format) {
341 case SNDRV_PCM_FORMAT_A_LAW: rformat = AD1848_ALAW_8; break;
342 case SNDRV_PCM_FORMAT_MU_LAW: rformat = AD1848_ULAW_8; break;
343 case SNDRV_PCM_FORMAT_S16_LE: rformat = AD1848_LINEAR_16; break;
344 }
345 if (channels > 1)
346 rformat |= AD1848_STEREO;
347#if 0
348 snd_printk("get_format: 0x%x (mode=0x%x)\n", format, mode);
349#endif
350 return rformat;
351}
352
353static void snd_ad1848_calibrate_mute(ad1848_t *chip, int mute)
354{
355 unsigned long flags;
356
357 mute = mute ? 1 : 0;
358 spin_lock_irqsave(&chip->reg_lock, flags);
359 if (chip->calibrate_mute == mute) {
360 spin_unlock_irqrestore(&chip->reg_lock, flags);
361 return;
362 }
363 if (!mute) {
364 snd_ad1848_dout(chip, AD1848_LEFT_INPUT, chip->image[AD1848_LEFT_INPUT]);
365 snd_ad1848_dout(chip, AD1848_RIGHT_INPUT, chip->image[AD1848_RIGHT_INPUT]);
366 }
367 snd_ad1848_dout(chip, AD1848_AUX1_LEFT_INPUT, mute ? 0x80 : chip->image[AD1848_AUX1_LEFT_INPUT]);
368 snd_ad1848_dout(chip, AD1848_AUX1_RIGHT_INPUT, mute ? 0x80 : chip->image[AD1848_AUX1_RIGHT_INPUT]);
369 snd_ad1848_dout(chip, AD1848_AUX2_LEFT_INPUT, mute ? 0x80 : chip->image[AD1848_AUX2_LEFT_INPUT]);
370 snd_ad1848_dout(chip, AD1848_AUX2_RIGHT_INPUT, mute ? 0x80 : chip->image[AD1848_AUX2_RIGHT_INPUT]);
371 snd_ad1848_dout(chip, AD1848_LEFT_OUTPUT, mute ? 0x80 : chip->image[AD1848_LEFT_OUTPUT]);
372 snd_ad1848_dout(chip, AD1848_RIGHT_OUTPUT, mute ? 0x80 : chip->image[AD1848_RIGHT_OUTPUT]);
373 chip->calibrate_mute = mute;
374 spin_unlock_irqrestore(&chip->reg_lock, flags);
375}
376
377static void snd_ad1848_set_data_format(ad1848_t *chip, snd_pcm_hw_params_t *hw_params)
378{
379 if (hw_params == NULL) {
380 chip->image[AD1848_DATA_FORMAT] = 0x20;
381 } else {
382 chip->image[AD1848_DATA_FORMAT] =
383 snd_ad1848_get_format(params_format(hw_params), params_channels(hw_params)) |
384 snd_ad1848_get_rate(params_rate(hw_params));
385 }
386 // snd_printk(">>> pmode = 0x%x, dfr = 0x%x\n", pstr->mode, chip->image[AD1848_DATA_FORMAT]);
387}
388
389static int snd_ad1848_open(ad1848_t *chip, unsigned int mode)
390{
391 unsigned long flags;
392
393 down(&chip->open_mutex);
394 if (chip->mode & AD1848_MODE_OPEN) {
395 up(&chip->open_mutex);
396 return -EAGAIN;
397 }
398 snd_ad1848_mce_down(chip);
399
400#ifdef SNDRV_DEBUG_MCE
401 snd_printk("open: (1)\n");
402#endif
403 snd_ad1848_mce_up(chip);
404 spin_lock_irqsave(&chip->reg_lock, flags);
405 chip->image[AD1848_IFACE_CTRL] &= ~(AD1848_PLAYBACK_ENABLE | AD1848_PLAYBACK_PIO |
406 AD1848_CAPTURE_ENABLE | AD1848_CAPTURE_PIO |
407 AD1848_CALIB_MODE);
408 chip->image[AD1848_IFACE_CTRL] |= AD1848_AUTOCALIB;
409 snd_ad1848_out(chip, AD1848_IFACE_CTRL, chip->image[AD1848_IFACE_CTRL]);
410 spin_unlock_irqrestore(&chip->reg_lock, flags);
411 snd_ad1848_mce_down(chip);
412
413#ifdef SNDRV_DEBUG_MCE
414 snd_printk("open: (2)\n");
415#endif
416
417 snd_ad1848_set_data_format(chip, NULL);
418
419 snd_ad1848_mce_up(chip);
420 spin_lock_irqsave(&chip->reg_lock, flags);
421 snd_ad1848_out(chip, AD1848_DATA_FORMAT, chip->image[AD1848_DATA_FORMAT]);
422 spin_unlock_irqrestore(&chip->reg_lock, flags);
423 snd_ad1848_mce_down(chip);
424
425#ifdef SNDRV_DEBUG_MCE
426 snd_printk("open: (3)\n");
427#endif
428
429 /* ok. now enable and ack CODEC IRQ */
430 spin_lock_irqsave(&chip->reg_lock, flags);
431 outb(0, AD1848P(chip, STATUS)); /* clear IRQ */
432 outb(0, AD1848P(chip, STATUS)); /* clear IRQ */
433 chip->image[AD1848_PIN_CTRL] |= AD1848_IRQ_ENABLE;
434 snd_ad1848_out(chip, AD1848_PIN_CTRL, chip->image[AD1848_PIN_CTRL]);
435 spin_unlock_irqrestore(&chip->reg_lock, flags);
436
437 chip->mode = mode;
438 up(&chip->open_mutex);
439
440 return 0;
441}
442
443static void snd_ad1848_close(ad1848_t *chip)
444{
445 unsigned long flags;
446
447 down(&chip->open_mutex);
448 if (!chip->mode) {
449 up(&chip->open_mutex);
450 return;
451 }
452 /* disable IRQ */
453 spin_lock_irqsave(&chip->reg_lock, flags);
454 outb(0, AD1848P(chip, STATUS)); /* clear IRQ */
455 outb(0, AD1848P(chip, STATUS)); /* clear IRQ */
456 chip->image[AD1848_PIN_CTRL] &= ~AD1848_IRQ_ENABLE;
457 snd_ad1848_out(chip, AD1848_PIN_CTRL, chip->image[AD1848_PIN_CTRL]);
458 spin_unlock_irqrestore(&chip->reg_lock, flags);
459
460 /* now disable capture & playback */
461
462 snd_ad1848_mce_up(chip);
463 spin_lock_irqsave(&chip->reg_lock, flags);
464 chip->image[AD1848_IFACE_CTRL] &= ~(AD1848_PLAYBACK_ENABLE | AD1848_PLAYBACK_PIO |
465 AD1848_CAPTURE_ENABLE | AD1848_CAPTURE_PIO);
466 snd_ad1848_out(chip, AD1848_IFACE_CTRL, chip->image[AD1848_IFACE_CTRL]);
467 spin_unlock_irqrestore(&chip->reg_lock, flags);
468 snd_ad1848_mce_down(chip);
469
470 /* clear IRQ again */
471 spin_lock_irqsave(&chip->reg_lock, flags);
472 outb(0, AD1848P(chip, STATUS)); /* clear IRQ */
473 outb(0, AD1848P(chip, STATUS)); /* clear IRQ */
474 spin_unlock_irqrestore(&chip->reg_lock, flags);
475
476 chip->mode = 0;
477 up(&chip->open_mutex);
478}
479
480/*
481 * ok.. exported functions..
482 */
483
484static int snd_ad1848_playback_trigger(snd_pcm_substream_t * substream,
485 int cmd)
486{
487 ad1848_t *chip = snd_pcm_substream_chip(substream);
488 return snd_ad1848_trigger(chip, AD1848_PLAYBACK_ENABLE, SNDRV_PCM_STREAM_PLAYBACK, cmd);
489}
490
491static int snd_ad1848_capture_trigger(snd_pcm_substream_t * substream,
492 int cmd)
493{
494 ad1848_t *chip = snd_pcm_substream_chip(substream);
495 return snd_ad1848_trigger(chip, AD1848_CAPTURE_ENABLE, SNDRV_PCM_STREAM_CAPTURE, cmd);
496}
497
498static int snd_ad1848_playback_hw_params(snd_pcm_substream_t * substream,
499 snd_pcm_hw_params_t * hw_params)
500{
501 ad1848_t *chip = snd_pcm_substream_chip(substream);
502 unsigned long flags;
503 int err;
504
505 if ((err = snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(hw_params))) < 0)
506 return err;
507 snd_ad1848_calibrate_mute(chip, 1);
508 snd_ad1848_set_data_format(chip, hw_params);
509 snd_ad1848_mce_up(chip);
510 spin_lock_irqsave(&chip->reg_lock, flags);
511 snd_ad1848_out(chip, AD1848_DATA_FORMAT, chip->image[AD1848_DATA_FORMAT]);
512 spin_unlock_irqrestore(&chip->reg_lock, flags);
513 snd_ad1848_mce_down(chip);
514 snd_ad1848_calibrate_mute(chip, 0);
515 return 0;
516}
517
518static int snd_ad1848_playback_hw_free(snd_pcm_substream_t * substream)
519{
520 return snd_pcm_lib_free_pages(substream);
521}
522
523static int snd_ad1848_playback_prepare(snd_pcm_substream_t * substream)
524{
525 ad1848_t *chip = snd_pcm_substream_chip(substream);
526 snd_pcm_runtime_t *runtime = substream->runtime;
527 unsigned long flags;
528 unsigned int size = snd_pcm_lib_buffer_bytes(substream);
529 unsigned int count = snd_pcm_lib_period_bytes(substream);
530
531 chip->dma_size = size;
532 chip->image[AD1848_IFACE_CTRL] &= ~(AD1848_PLAYBACK_ENABLE | AD1848_PLAYBACK_PIO);
533 snd_dma_program(chip->dma, runtime->dma_addr, size, DMA_MODE_WRITE | DMA_AUTOINIT);
534 count = snd_ad1848_get_count(chip->image[AD1848_DATA_FORMAT], count) - 1;
535 spin_lock_irqsave(&chip->reg_lock, flags);
536 snd_ad1848_out(chip, AD1848_DATA_LWR_CNT, (unsigned char) count);
537 snd_ad1848_out(chip, AD1848_DATA_UPR_CNT, (unsigned char) (count >> 8));
538 spin_unlock_irqrestore(&chip->reg_lock, flags);
539 return 0;
540}
541
542static int snd_ad1848_capture_hw_params(snd_pcm_substream_t * substream,
543 snd_pcm_hw_params_t * hw_params)
544{
545 ad1848_t *chip = snd_pcm_substream_chip(substream);
546 unsigned long flags;
547 int err;
548
549 if ((err = snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(hw_params))) < 0)
550 return err;
551 snd_ad1848_calibrate_mute(chip, 1);
552 snd_ad1848_set_data_format(chip, hw_params);
553 snd_ad1848_mce_up(chip);
554 spin_lock_irqsave(&chip->reg_lock, flags);
555 snd_ad1848_out(chip, AD1848_DATA_FORMAT, chip->image[AD1848_DATA_FORMAT]);
556 spin_unlock_irqrestore(&chip->reg_lock, flags);
557 snd_ad1848_mce_down(chip);
558 snd_ad1848_calibrate_mute(chip, 0);
559 return 0;
560}
561
562static int snd_ad1848_capture_hw_free(snd_pcm_substream_t * substream)
563{
564 return snd_pcm_lib_free_pages(substream);
565}
566
567static int snd_ad1848_capture_prepare(snd_pcm_substream_t * substream)
568{
569 ad1848_t *chip = snd_pcm_substream_chip(substream);
570 snd_pcm_runtime_t *runtime = substream->runtime;
571 unsigned long flags;
572 unsigned int size = snd_pcm_lib_buffer_bytes(substream);
573 unsigned int count = snd_pcm_lib_period_bytes(substream);
574
575 chip->dma_size = size;
576 chip->image[AD1848_IFACE_CTRL] &= ~(AD1848_CAPTURE_ENABLE | AD1848_CAPTURE_PIO);
577 snd_dma_program(chip->dma, runtime->dma_addr, size, DMA_MODE_READ | DMA_AUTOINIT);
578 count = snd_ad1848_get_count(chip->image[AD1848_DATA_FORMAT], count) - 1;
579 spin_lock_irqsave(&chip->reg_lock, flags);
580 snd_ad1848_out(chip, AD1848_DATA_LWR_CNT, (unsigned char) count);
581 snd_ad1848_out(chip, AD1848_DATA_UPR_CNT, (unsigned char) (count >> 8));
582 spin_unlock_irqrestore(&chip->reg_lock, flags);
583 return 0;
584}
585
586static irqreturn_t snd_ad1848_interrupt(int irq, void *dev_id, struct pt_regs *regs)
587{
588 ad1848_t *chip = dev_id;
589
590 if ((chip->mode & AD1848_MODE_PLAY) && chip->playback_substream &&
591 (chip->mode & AD1848_MODE_RUNNING))
592 snd_pcm_period_elapsed(chip->playback_substream);
593 if ((chip->mode & AD1848_MODE_CAPTURE) && chip->capture_substream &&
594 (chip->mode & AD1848_MODE_RUNNING))
595 snd_pcm_period_elapsed(chip->capture_substream);
596 outb(0, AD1848P(chip, STATUS)); /* clear global interrupt bit */
597 return IRQ_HANDLED;
598}
599
600static snd_pcm_uframes_t snd_ad1848_playback_pointer(snd_pcm_substream_t * substream)
601{
602 ad1848_t *chip = snd_pcm_substream_chip(substream);
603 size_t ptr;
604
605 if (!(chip->image[AD1848_IFACE_CTRL] & AD1848_PLAYBACK_ENABLE))
606 return 0;
607 ptr = snd_dma_pointer(chip->dma, chip->dma_size);
608 return bytes_to_frames(substream->runtime, ptr);
609}
610
611static snd_pcm_uframes_t snd_ad1848_capture_pointer(snd_pcm_substream_t * substream)
612{
613 ad1848_t *chip = snd_pcm_substream_chip(substream);
614 size_t ptr;
615
616 if (!(chip->image[AD1848_IFACE_CTRL] & AD1848_CAPTURE_ENABLE))
617 return 0;
618 ptr = snd_dma_pointer(chip->dma, chip->dma_size);
619 return bytes_to_frames(substream->runtime, ptr);
620}
621
622/*
623
624 */
625
626static void snd_ad1848_thinkpad_twiddle(ad1848_t *chip, int on) {
627
628 int tmp;
629
630 if (!chip->thinkpad_flag) return;
631
632 outb(0x1c, AD1848_THINKPAD_CTL_PORT1);
633 tmp = inb(AD1848_THINKPAD_CTL_PORT2);
634
635 if (on)
636 /* turn it on */
637 tmp |= AD1848_THINKPAD_CS4248_ENABLE_BIT;
638 else
639 /* turn it off */
640 tmp &= ~AD1848_THINKPAD_CS4248_ENABLE_BIT;
641
642 outb(tmp, AD1848_THINKPAD_CTL_PORT2);
643
644}
645
646#ifdef CONFIG_PM
647static int snd_ad1848_suspend(snd_card_t *card, pm_message_t state)
648{
649 ad1848_t *chip = card->pm_private_data;
650
651 snd_pcm_suspend_all(chip->pcm);
652 /* FIXME: save registers? */
653
654 if (chip->thinkpad_flag)
655 snd_ad1848_thinkpad_twiddle(chip, 0);
656
657 return 0;
658}
659
660static int snd_ad1848_resume(snd_card_t *card)
661{
662 ad1848_t *chip = card->pm_private_data;
663
664 if (chip->thinkpad_flag)
665 snd_ad1848_thinkpad_twiddle(chip, 1);
666
667 /* FIXME: restore registers? */
668
669 return 0;
670}
671#endif /* CONFIG_PM */
672
673static int snd_ad1848_probe(ad1848_t * chip)
674{
675 unsigned long flags;
676 int i, id, rev, ad1847;
677 unsigned char *ptr;
678
679#if 0
680 snd_ad1848_debug(chip);
681#endif
682 id = ad1847 = 0;
683 for (i = 0; i < 1000; i++) {
684 mb();
685 if (inb(AD1848P(chip, REGSEL)) & AD1848_INIT)
686 udelay(500);
687 else {
688 spin_lock_irqsave(&chip->reg_lock, flags);
689 snd_ad1848_out(chip, AD1848_MISC_INFO, 0x00);
690 snd_ad1848_out(chip, AD1848_LEFT_INPUT, 0xaa);
691 snd_ad1848_out(chip, AD1848_RIGHT_INPUT, 0x45);
692 rev = snd_ad1848_in(chip, AD1848_RIGHT_INPUT);
693 if (rev == 0x65) {
694 spin_unlock_irqrestore(&chip->reg_lock, flags);
695 id = 1;
696 ad1847 = 1;
697 break;
698 }
699 if (snd_ad1848_in(chip, AD1848_LEFT_INPUT) == 0xaa && rev == 0x45) {
700 spin_unlock_irqrestore(&chip->reg_lock, flags);
701 id = 1;
702 break;
703 }
704 spin_unlock_irqrestore(&chip->reg_lock, flags);
705 }
706 }
707 if (id != 1)
708 return -ENODEV; /* no valid device found */
709 if (chip->hardware == AD1848_HW_DETECT) {
710 if (ad1847) {
711 chip->hardware = AD1848_HW_AD1847;
712 } else {
713 chip->hardware = AD1848_HW_AD1848;
714 rev = snd_ad1848_in(chip, AD1848_MISC_INFO);
715 if (rev & 0x80) {
716 chip->hardware = AD1848_HW_CS4248;
717 } else if ((rev & 0x0f) == 0x0a) {
718 snd_ad1848_out(chip, AD1848_MISC_INFO, 0x40);
719 for (i = 0; i < 16; ++i) {
720 if (snd_ad1848_in(chip, i) != snd_ad1848_in(chip, i + 16)) {
721 chip->hardware = AD1848_HW_CMI8330;
722 break;
723 }
724 }
725 snd_ad1848_out(chip, AD1848_MISC_INFO, 0x00);
726 }
727 }
728 }
729 spin_lock_irqsave(&chip->reg_lock, flags);
730 inb(AD1848P(chip, STATUS)); /* clear any pendings IRQ */
731 outb(0, AD1848P(chip, STATUS));
732 mb();
733 spin_unlock_irqrestore(&chip->reg_lock, flags);
734
735 chip->image[AD1848_MISC_INFO] = 0x00;
736 chip->image[AD1848_IFACE_CTRL] =
737 (chip->image[AD1848_IFACE_CTRL] & ~AD1848_SINGLE_DMA) | AD1848_SINGLE_DMA;
738 ptr = (unsigned char *) &chip->image;
739 snd_ad1848_mce_down(chip);
740 spin_lock_irqsave(&chip->reg_lock, flags);
741 for (i = 0; i < 16; i++) /* ok.. fill all AD1848 registers */
742 snd_ad1848_out(chip, i, *ptr++);
743 spin_unlock_irqrestore(&chip->reg_lock, flags);
744 snd_ad1848_mce_up(chip);
745 snd_ad1848_mce_down(chip);
746 return 0; /* all things are ok.. */
747}
748
749/*
750
751 */
752
753static snd_pcm_hardware_t snd_ad1848_playback =
754{
755 .info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED |
756 SNDRV_PCM_INFO_MMAP_VALID),
757 .formats = (SNDRV_PCM_FMTBIT_MU_LAW | SNDRV_PCM_FMTBIT_A_LAW |
758 SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S16_LE),
759 .rates = SNDRV_PCM_RATE_KNOT | SNDRV_PCM_RATE_8000_48000,
760 .rate_min = 5510,
761 .rate_max = 48000,
762 .channels_min = 1,
763 .channels_max = 2,
764 .buffer_bytes_max = (128*1024),
765 .period_bytes_min = 64,
766 .period_bytes_max = (128*1024),
767 .periods_min = 1,
768 .periods_max = 1024,
769 .fifo_size = 0,
770};
771
772static snd_pcm_hardware_t snd_ad1848_capture =
773{
774 .info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED |
775 SNDRV_PCM_INFO_MMAP_VALID),
776 .formats = (SNDRV_PCM_FMTBIT_MU_LAW | SNDRV_PCM_FMTBIT_A_LAW |
777 SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S16_LE),
778 .rates = SNDRV_PCM_RATE_KNOT | SNDRV_PCM_RATE_8000_48000,
779 .rate_min = 5510,
780 .rate_max = 48000,
781 .channels_min = 1,
782 .channels_max = 2,
783 .buffer_bytes_max = (128*1024),
784 .period_bytes_min = 64,
785 .period_bytes_max = (128*1024),
786 .periods_min = 1,
787 .periods_max = 1024,
788 .fifo_size = 0,
789};
790
791/*
792
793 */
794
795static int snd_ad1848_playback_open(snd_pcm_substream_t * substream)
796{
797 ad1848_t *chip = snd_pcm_substream_chip(substream);
798 snd_pcm_runtime_t *runtime = substream->runtime;
799 int err;
800
801 if ((err = snd_ad1848_open(chip, AD1848_MODE_PLAY)) < 0)
802 return err;
803 chip->playback_substream = substream;
804 runtime->hw = snd_ad1848_playback;
805 snd_pcm_limit_isa_dma_size(chip->dma, &runtime->hw.buffer_bytes_max);
806 snd_pcm_limit_isa_dma_size(chip->dma, &runtime->hw.period_bytes_max);
807 snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE, &hw_constraints_rates);
808 return 0;
809}
810
811static int snd_ad1848_capture_open(snd_pcm_substream_t * substream)
812{
813 ad1848_t *chip = snd_pcm_substream_chip(substream);
814 snd_pcm_runtime_t *runtime = substream->runtime;
815 int err;
816
817 if ((err = snd_ad1848_open(chip, AD1848_MODE_CAPTURE)) < 0)
818 return err;
819 chip->capture_substream = substream;
820 runtime->hw = snd_ad1848_capture;
821 snd_pcm_limit_isa_dma_size(chip->dma, &runtime->hw.buffer_bytes_max);
822 snd_pcm_limit_isa_dma_size(chip->dma, &runtime->hw.period_bytes_max);
823 snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE, &hw_constraints_rates);
824 return 0;
825}
826
827static int snd_ad1848_playback_close(snd_pcm_substream_t * substream)
828{
829 ad1848_t *chip = snd_pcm_substream_chip(substream);
830
831 chip->mode &= ~AD1848_MODE_PLAY;
832 chip->playback_substream = NULL;
833 snd_ad1848_close(chip);
834 return 0;
835}
836
837static int snd_ad1848_capture_close(snd_pcm_substream_t * substream)
838{
839 ad1848_t *chip = snd_pcm_substream_chip(substream);
840
841 chip->mode &= ~AD1848_MODE_CAPTURE;
842 chip->capture_substream = NULL;
843 snd_ad1848_close(chip);
844 return 0;
845}
846
847static int snd_ad1848_free(ad1848_t *chip)
848{
849 if (chip->res_port) {
850 release_resource(chip->res_port);
851 kfree_nocheck(chip->res_port);
852 }
853 if (chip->irq >= 0)
854 free_irq(chip->irq, (void *) chip);
855 if (chip->dma >= 0) {
856 snd_dma_disable(chip->dma);
857 free_dma(chip->dma);
858 }
859 kfree(chip);
860 return 0;
861}
862
863static int snd_ad1848_dev_free(snd_device_t *device)
864{
865 ad1848_t *chip = device->device_data;
866 return snd_ad1848_free(chip);
867}
868
869static const char *snd_ad1848_chip_id(ad1848_t *chip)
870{
871 switch (chip->hardware) {
872 case AD1848_HW_AD1847: return "AD1847";
873 case AD1848_HW_AD1848: return "AD1848";
874 case AD1848_HW_CS4248: return "CS4248";
875 case AD1848_HW_CMI8330: return "CMI8330/C3D";
876 default: return "???";
877 }
878}
879
880int snd_ad1848_create(snd_card_t * card,
881 unsigned long port,
882 int irq, int dma,
883 unsigned short hardware,
884 ad1848_t ** rchip)
885{
886 static snd_device_ops_t ops = {
887 .dev_free = snd_ad1848_dev_free,
888 };
889 ad1848_t *chip;
890 int err;
891
892 *rchip = NULL;
893 chip = kcalloc(1, sizeof(*chip), GFP_KERNEL);
894 if (chip == NULL)
895 return -ENOMEM;
896 spin_lock_init(&chip->reg_lock);
897 init_MUTEX(&chip->open_mutex);
898 chip->card = card;
899 chip->port = port;
900 chip->irq = -1;
901 chip->dma = -1;
902 chip->hardware = hardware;
903 memcpy(&chip->image, &snd_ad1848_original_image, sizeof(snd_ad1848_original_image));
904
905 if ((chip->res_port = request_region(port, 4, "AD1848")) == NULL) {
906 snd_printk(KERN_ERR "ad1848: can't grab port 0x%lx\n", port);
907 snd_ad1848_free(chip);
908 return -EBUSY;
909 }
910 if (request_irq(irq, snd_ad1848_interrupt, SA_INTERRUPT, "AD1848", (void *) chip)) {
911 snd_printk(KERN_ERR "ad1848: can't grab IRQ %d\n", irq);
912 snd_ad1848_free(chip);
913 return -EBUSY;
914 }
915 chip->irq = irq;
916 if (request_dma(dma, "AD1848")) {
917 snd_printk(KERN_ERR "ad1848: can't grab DMA %d\n", dma);
918 snd_ad1848_free(chip);
919 return -EBUSY;
920 }
921 chip->dma = dma;
922
923 if (hardware == AD1848_HW_THINKPAD) {
924 chip->thinkpad_flag = 1;
925 chip->hardware = AD1848_HW_DETECT; /* reset */
926 snd_ad1848_thinkpad_twiddle(chip, 1);
927 snd_card_set_isa_pm_callback(card, snd_ad1848_suspend, snd_ad1848_resume, chip);
928 }
929
930 if (snd_ad1848_probe(chip) < 0) {
931 snd_ad1848_free(chip);
932 return -ENODEV;
933 }
934
935 /* Register device */
936 if ((err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops)) < 0) {
937 snd_ad1848_free(chip);
938 return err;
939 }
940
941 *rchip = chip;
942 return 0;
943}
944
945static snd_pcm_ops_t snd_ad1848_playback_ops = {
946 .open = snd_ad1848_playback_open,
947 .close = snd_ad1848_playback_close,
948 .ioctl = snd_ad1848_ioctl,
949 .hw_params = snd_ad1848_playback_hw_params,
950 .hw_free = snd_ad1848_playback_hw_free,
951 .prepare = snd_ad1848_playback_prepare,
952 .trigger = snd_ad1848_playback_trigger,
953 .pointer = snd_ad1848_playback_pointer,
954};
955
956static snd_pcm_ops_t snd_ad1848_capture_ops = {
957 .open = snd_ad1848_capture_open,
958 .close = snd_ad1848_capture_close,
959 .ioctl = snd_ad1848_ioctl,
960 .hw_params = snd_ad1848_capture_hw_params,
961 .hw_free = snd_ad1848_capture_hw_free,
962 .prepare = snd_ad1848_capture_prepare,
963 .trigger = snd_ad1848_capture_trigger,
964 .pointer = snd_ad1848_capture_pointer,
965};
966
967static void snd_ad1848_pcm_free(snd_pcm_t *pcm)
968{
969 ad1848_t *chip = pcm->private_data;
970 chip->pcm = NULL;
971 snd_pcm_lib_preallocate_free_for_all(pcm);
972}
973
974int snd_ad1848_pcm(ad1848_t *chip, int device, snd_pcm_t **rpcm)
975{
976 snd_pcm_t *pcm;
977 int err;
978
979 if ((err = snd_pcm_new(chip->card, "AD1848", device, 1, 1, &pcm)) < 0)
980 return err;
981
982 snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_ad1848_playback_ops);
983 snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_ad1848_capture_ops);
984
985 pcm->private_free = snd_ad1848_pcm_free;
986 pcm->private_data = chip;
987 pcm->info_flags = SNDRV_PCM_INFO_HALF_DUPLEX;
988 strcpy(pcm->name, snd_ad1848_chip_id(chip));
989
990 snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV,
991 snd_dma_isa_data(),
992 64*1024, chip->dma > 3 ? 128*1024 : 64*1024);
993
994 chip->pcm = pcm;
995 if (rpcm)
996 *rpcm = pcm;
997 return 0;
998}
999
1000const snd_pcm_ops_t *snd_ad1848_get_pcm_ops(int direction)
1001{
1002 return direction == SNDRV_PCM_STREAM_PLAYBACK ?
1003 &snd_ad1848_playback_ops : &snd_ad1848_capture_ops;
1004}
1005
1006/*
1007 * MIXER part
1008 */
1009
1010static int snd_ad1848_info_mux(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
1011{
1012 static char *texts[4] = {
1013 "Line", "Aux", "Mic", "Mix"
1014 };
1015
1016 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
1017 uinfo->count = 2;
1018 uinfo->value.enumerated.items = 4;
1019 if (uinfo->value.enumerated.item > 3)
1020 uinfo->value.enumerated.item = 3;
1021 strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]);
1022 return 0;
1023}
1024
1025static int snd_ad1848_get_mux(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
1026{
1027 ad1848_t *chip = snd_kcontrol_chip(kcontrol);
1028 unsigned long flags;
1029
1030 spin_lock_irqsave(&chip->reg_lock, flags);
1031 ucontrol->value.enumerated.item[0] = (chip->image[AD1848_LEFT_INPUT] & AD1848_MIXS_ALL) >> 6;
1032 ucontrol->value.enumerated.item[1] = (chip->image[AD1848_RIGHT_INPUT] & AD1848_MIXS_ALL) >> 6;
1033 spin_unlock_irqrestore(&chip->reg_lock, flags);
1034 return 0;
1035}
1036
1037static int snd_ad1848_put_mux(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
1038{
1039 ad1848_t *chip = snd_kcontrol_chip(kcontrol);
1040 unsigned long flags;
1041 unsigned short left, right;
1042 int change;
1043
1044 if (ucontrol->value.enumerated.item[0] > 3 ||
1045 ucontrol->value.enumerated.item[1] > 3)
1046 return -EINVAL;
1047 left = ucontrol->value.enumerated.item[0] << 6;
1048 right = ucontrol->value.enumerated.item[1] << 6;
1049 spin_lock_irqsave(&chip->reg_lock, flags);
1050 left = (chip->image[AD1848_LEFT_INPUT] & ~AD1848_MIXS_ALL) | left;
1051 right = (chip->image[AD1848_RIGHT_INPUT] & ~AD1848_MIXS_ALL) | right;
1052 change = left != chip->image[AD1848_LEFT_INPUT] ||
1053 right != chip->image[AD1848_RIGHT_INPUT];
1054 snd_ad1848_out(chip, AD1848_LEFT_INPUT, left);
1055 snd_ad1848_out(chip, AD1848_RIGHT_INPUT, right);
1056 spin_unlock_irqrestore(&chip->reg_lock, flags);
1057 return change;
1058}
1059
1060static int snd_ad1848_info_single(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
1061{
1062 int mask = (kcontrol->private_value >> 16) & 0xff;
1063
1064 uinfo->type = mask == 1 ? SNDRV_CTL_ELEM_TYPE_BOOLEAN : SNDRV_CTL_ELEM_TYPE_INTEGER;
1065 uinfo->count = 1;
1066 uinfo->value.integer.min = 0;
1067 uinfo->value.integer.max = mask;
1068 return 0;
1069}
1070
1071static int snd_ad1848_get_single(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
1072{
1073 ad1848_t *chip = snd_kcontrol_chip(kcontrol);
1074 unsigned long flags;
1075 int reg = kcontrol->private_value & 0xff;
1076 int shift = (kcontrol->private_value >> 8) & 0xff;
1077 int mask = (kcontrol->private_value >> 16) & 0xff;
1078 int invert = (kcontrol->private_value >> 24) & 0xff;
1079
1080 spin_lock_irqsave(&chip->reg_lock, flags);
1081 ucontrol->value.integer.value[0] = (chip->image[reg] >> shift) & mask;
1082 spin_unlock_irqrestore(&chip->reg_lock, flags);
1083 if (invert)
1084 ucontrol->value.integer.value[0] = mask - ucontrol->value.integer.value[0];
1085 return 0;
1086}
1087
1088static int snd_ad1848_put_single(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
1089{
1090 ad1848_t *chip = snd_kcontrol_chip(kcontrol);
1091 unsigned long flags;
1092 int reg = kcontrol->private_value & 0xff;
1093 int shift = (kcontrol->private_value >> 8) & 0xff;
1094 int mask = (kcontrol->private_value >> 16) & 0xff;
1095 int invert = (kcontrol->private_value >> 24) & 0xff;
1096 int change;
1097 unsigned short val;
1098
1099 val = (ucontrol->value.integer.value[0] & mask);
1100 if (invert)
1101 val = mask - val;
1102 val <<= shift;
1103 spin_lock_irqsave(&chip->reg_lock, flags);
1104 val = (chip->image[reg] & ~(mask << shift)) | val;
1105 change = val != chip->image[reg];
1106 snd_ad1848_out(chip, reg, val);
1107 spin_unlock_irqrestore(&chip->reg_lock, flags);
1108 return change;
1109}
1110
1111static int snd_ad1848_info_double(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
1112{
1113 int mask = (kcontrol->private_value >> 24) & 0xff;
1114
1115 uinfo->type = mask == 1 ? SNDRV_CTL_ELEM_TYPE_BOOLEAN : SNDRV_CTL_ELEM_TYPE_INTEGER;
1116 uinfo->count = 2;
1117 uinfo->value.integer.min = 0;
1118 uinfo->value.integer.max = mask;
1119 return 0;
1120}
1121
1122static int snd_ad1848_get_double(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
1123{
1124 ad1848_t *chip = snd_kcontrol_chip(kcontrol);
1125 unsigned long flags;
1126 int left_reg = kcontrol->private_value & 0xff;
1127 int right_reg = (kcontrol->private_value >> 8) & 0xff;
1128 int shift_left = (kcontrol->private_value >> 16) & 0x07;
1129 int shift_right = (kcontrol->private_value >> 19) & 0x07;
1130 int mask = (kcontrol->private_value >> 24) & 0xff;
1131 int invert = (kcontrol->private_value >> 22) & 1;
1132
1133 spin_lock_irqsave(&chip->reg_lock, flags);
1134 ucontrol->value.integer.value[0] = (chip->image[left_reg] >> shift_left) & mask;
1135 ucontrol->value.integer.value[1] = (chip->image[right_reg] >> shift_right) & mask;
1136 spin_unlock_irqrestore(&chip->reg_lock, flags);
1137 if (invert) {
1138 ucontrol->value.integer.value[0] = mask - ucontrol->value.integer.value[0];
1139 ucontrol->value.integer.value[1] = mask - ucontrol->value.integer.value[1];
1140 }
1141 return 0;
1142}
1143
1144static int snd_ad1848_put_double(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
1145{
1146 ad1848_t *chip = snd_kcontrol_chip(kcontrol);
1147 unsigned long flags;
1148 int left_reg = kcontrol->private_value & 0xff;
1149 int right_reg = (kcontrol->private_value >> 8) & 0xff;
1150 int shift_left = (kcontrol->private_value >> 16) & 0x07;
1151 int shift_right = (kcontrol->private_value >> 19) & 0x07;
1152 int mask = (kcontrol->private_value >> 24) & 0xff;
1153 int invert = (kcontrol->private_value >> 22) & 1;
1154 int change;
1155 unsigned short val1, val2;
1156
1157 val1 = ucontrol->value.integer.value[0] & mask;
1158 val2 = ucontrol->value.integer.value[1] & mask;
1159 if (invert) {
1160 val1 = mask - val1;
1161 val2 = mask - val2;
1162 }
1163 val1 <<= shift_left;
1164 val2 <<= shift_right;
1165 spin_lock_irqsave(&chip->reg_lock, flags);
1166 if (left_reg != right_reg) {
1167 val1 = (chip->image[left_reg] & ~(mask << shift_left)) | val1;
1168 val2 = (chip->image[right_reg] & ~(mask << shift_right)) | val2;
1169 change = val1 != chip->image[left_reg] || val2 != chip->image[right_reg];
1170 snd_ad1848_out(chip, left_reg, val1);
1171 snd_ad1848_out(chip, right_reg, val2);
1172 } else {
1173 val1 = (chip->image[left_reg] & ~((mask << shift_left) | (mask << shift_right))) | val1 | val2;
1174 change = val1 != chip->image[left_reg];
1175 snd_ad1848_out(chip, left_reg, val1);
1176 }
1177 spin_unlock_irqrestore(&chip->reg_lock, flags);
1178 return change;
1179}
1180
1181/*
1182 */
1183int snd_ad1848_add_ctl(ad1848_t *chip, const char *name, int index, int type, unsigned long value)
1184{
1185 static snd_kcontrol_new_t newctls[] = {
1186 [AD1848_MIX_SINGLE] = {
1187 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1188 .info = snd_ad1848_info_single,
1189 .get = snd_ad1848_get_single,
1190 .put = snd_ad1848_put_single,
1191 },
1192 [AD1848_MIX_DOUBLE] = {
1193 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1194 .info = snd_ad1848_info_double,
1195 .get = snd_ad1848_get_double,
1196 .put = snd_ad1848_put_double,
1197 },
1198 [AD1848_MIX_CAPTURE] = {
1199 .info = snd_ad1848_info_mux,
1200 .get = snd_ad1848_get_mux,
1201 .put = snd_ad1848_put_mux,
1202 },
1203 };
1204 snd_kcontrol_t *ctl;
1205 int err;
1206
1207 ctl = snd_ctl_new1(&newctls[type], chip);
1208 if (! ctl)
1209 return -ENOMEM;
1210 strlcpy(ctl->id.name, name, sizeof(ctl->id.name));
1211 ctl->id.index = index;
1212 ctl->private_value = value;
1213 if ((err = snd_ctl_add(chip->card, ctl)) < 0) {
1214 snd_ctl_free_one(ctl);
1215 return err;
1216 }
1217 return 0;
1218}
1219
1220
1221static struct ad1848_mix_elem snd_ad1848_controls[] = {
1222AD1848_DOUBLE("PCM Playback Switch", 0, AD1848_LEFT_OUTPUT, AD1848_RIGHT_OUTPUT, 7, 7, 1, 1),
1223AD1848_DOUBLE("PCM Playback Volume", 0, AD1848_LEFT_OUTPUT, AD1848_RIGHT_OUTPUT, 0, 0, 63, 1),
1224AD1848_DOUBLE("Aux Playback Switch", 0, AD1848_AUX1_LEFT_INPUT, AD1848_AUX1_RIGHT_INPUT, 7, 7, 1, 1),
1225AD1848_DOUBLE("Aux Playback Volume", 0, AD1848_AUX1_LEFT_INPUT, AD1848_AUX1_RIGHT_INPUT, 0, 0, 31, 1),
1226AD1848_DOUBLE("Aux Playback Switch", 1, AD1848_AUX2_LEFT_INPUT, AD1848_AUX2_RIGHT_INPUT, 7, 7, 1, 1),
1227AD1848_DOUBLE("Aux Playback Volume", 1, AD1848_AUX2_LEFT_INPUT, AD1848_AUX2_RIGHT_INPUT, 0, 0, 31, 1),
1228AD1848_DOUBLE("Capture Volume", 0, AD1848_LEFT_INPUT, AD1848_RIGHT_INPUT, 0, 0, 15, 0),
1229{
1230 .name = "Capture Source",
1231 .type = AD1848_MIX_CAPTURE,
1232},
1233AD1848_SINGLE("Loopback Capture Switch", 0, AD1848_LOOPBACK, 0, 1, 0),
1234AD1848_SINGLE("Loopback Capture Volume", 0, AD1848_LOOPBACK, 1, 63, 0)
1235};
1236
1237int snd_ad1848_mixer(ad1848_t *chip)
1238{
1239 snd_card_t *card;
1240 snd_pcm_t *pcm;
1241 unsigned int idx;
1242 int err;
1243
1244 snd_assert(chip != NULL && chip->pcm != NULL, return -EINVAL);
1245
1246 pcm = chip->pcm;
1247 card = chip->card;
1248
1249 strcpy(card->mixername, pcm->name);
1250
1251 for (idx = 0; idx < ARRAY_SIZE(snd_ad1848_controls); idx++)
1252 if ((err = snd_ad1848_add_ctl_elem(chip, &snd_ad1848_controls[idx])) < 0)
1253 return err;
1254
1255 return 0;
1256}
1257
1258EXPORT_SYMBOL(snd_ad1848_out);
1259EXPORT_SYMBOL(snd_ad1848_create);
1260EXPORT_SYMBOL(snd_ad1848_pcm);
1261EXPORT_SYMBOL(snd_ad1848_get_pcm_ops);
1262EXPORT_SYMBOL(snd_ad1848_mixer);
1263EXPORT_SYMBOL(snd_ad1848_add_ctl);
1264
1265/*
1266 * INIT part
1267 */
1268
1269static int __init alsa_ad1848_init(void)
1270{
1271 return 0;
1272}
1273
1274static void __exit alsa_ad1848_exit(void)
1275{
1276}
1277
1278module_init(alsa_ad1848_init)
1279module_exit(alsa_ad1848_exit)
diff --git a/sound/isa/als100.c b/sound/isa/als100.c
new file mode 100644
index 000000000000..ac8f13664983
--- /dev/null
+++ b/sound/isa/als100.c
@@ -0,0 +1,336 @@
1
2/*
3 card-als100.c - driver for Avance Logic ALS100 based soundcards.
4 Copyright (C) 1999-2000 by Massimo Piccioni <dafastidio@libero.it>
5
6 Thanks to Pierfrancesco 'qM2' Passerini.
7
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 2 of the License, or
11 (at your option) any later version.
12
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
17
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21*/
22
23#include <sound/driver.h>
24#include <linux/init.h>
25#include <linux/wait.h>
26#include <linux/time.h>
27#include <linux/pnp.h>
28#include <linux/moduleparam.h>
29#include <sound/core.h>
30#include <sound/initval.h>
31#include <sound/mpu401.h>
32#include <sound/opl3.h>
33#include <sound/sb.h>
34
35#define PFX "als100: "
36
37MODULE_AUTHOR("Massimo Piccioni <dafastidio@libero.it>");
38MODULE_DESCRIPTION("Avance Logic ALS1X0");
39MODULE_LICENSE("GPL");
40MODULE_SUPPORTED_DEVICE("{{Avance Logic,ALS100 - PRO16PNP},"
41 "{Avance Logic,ALS110},"
42 "{Avance Logic,ALS120},"
43 "{Avance Logic,ALS200},"
44 "{3D Melody,MF1000},"
45 "{Digimate,3D Sound},"
46 "{Avance Logic,ALS120},"
47 "{RTL,RTL3000}}");
48
49static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-MAX */
50static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* ID for this card */
51static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_ISAPNP; /* Enable this card */
52static long port[SNDRV_CARDS] = SNDRV_DEFAULT_PORT; /* PnP setup */
53static long mpu_port[SNDRV_CARDS] = SNDRV_DEFAULT_PORT; /* PnP setup */
54static long fm_port[SNDRV_CARDS] = SNDRV_DEFAULT_PORT; /* PnP setup */
55static int irq[SNDRV_CARDS] = SNDRV_DEFAULT_IRQ; /* PnP setup */
56static int mpu_irq[SNDRV_CARDS] = SNDRV_DEFAULT_IRQ; /* PnP setup */
57static int dma8[SNDRV_CARDS] = SNDRV_DEFAULT_DMA; /* PnP setup */
58static int dma16[SNDRV_CARDS] = SNDRV_DEFAULT_DMA; /* PnP setup */
59
60module_param_array(index, int, NULL, 0444);
61MODULE_PARM_DESC(index, "Index value for als100 based soundcard.");
62module_param_array(id, charp, NULL, 0444);
63MODULE_PARM_DESC(id, "ID string for als100 based soundcard.");
64module_param_array(enable, bool, NULL, 0444);
65MODULE_PARM_DESC(enable, "Enable als100 based soundcard.");
66module_param_array(port, long, NULL, 0444);
67MODULE_PARM_DESC(port, "Port # for als100 driver.");
68module_param_array(mpu_port, long, NULL, 0444);
69MODULE_PARM_DESC(mpu_port, "MPU-401 port # for als100 driver.");
70module_param_array(fm_port, long, NULL, 0444);
71MODULE_PARM_DESC(fm_port, "FM port # for als100 driver.");
72module_param_array(irq, int, NULL, 0444);
73MODULE_PARM_DESC(irq, "IRQ # for als100 driver.");
74module_param_array(mpu_irq, int, NULL, 0444);
75MODULE_PARM_DESC(mpu_irq, "MPU-401 IRQ # for als100 driver.");
76module_param_array(dma8, int, NULL, 0444);
77MODULE_PARM_DESC(dma8, "8-bit DMA # for als100 driver.");
78module_param_array(dma16, int, NULL, 0444);
79MODULE_PARM_DESC(dma16, "16-bit DMA # for als100 driver.");
80
81struct snd_card_als100 {
82 int dev_no;
83 struct pnp_dev *dev;
84 struct pnp_dev *devmpu;
85 struct pnp_dev *devopl;
86};
87
88static struct pnp_card_device_id snd_als100_pnpids[] = {
89 /* ALS100 - PRO16PNP */
90 { .id = "ALS0001", .devs = { { "@@@0001" }, { "@X@0001" }, { "@H@0001" } } },
91 /* ALS110 - MF1000 - Digimate 3D Sound */
92 { .id = "ALS0110", .devs = { { "@@@1001" }, { "@X@1001" }, { "@H@1001" } } },
93 /* ALS120 */
94 { .id = "ALS0120", .devs = { { "@@@2001" }, { "@X@2001" }, { "@H@2001" } } },
95 /* ALS200 */
96 { .id = "ALS0200", .devs = { { "@@@0020" }, { "@X@0020" }, { "@H@0001" } } },
97 /* ALS200 OEM */
98 { .id = "ALS0200", .devs = { { "@@@0020" }, { "@X@0020" }, { "@H@0020" } } },
99 /* RTL3000 */
100 { .id = "RTL3000", .devs = { { "@@@2001" }, { "@X@2001" }, { "@H@2001" } } },
101 { .id = "", } /* end */
102};
103
104MODULE_DEVICE_TABLE(pnp_card, snd_als100_pnpids);
105
106#define DRIVER_NAME "snd-card-als100"
107
108static int __devinit snd_card_als100_pnp(int dev, struct snd_card_als100 *acard,
109 struct pnp_card_link *card,
110 const struct pnp_card_device_id *id)
111{
112 struct pnp_dev *pdev;
113 struct pnp_resource_table *cfg = kmalloc(sizeof(*cfg), GFP_KERNEL);
114 int err;
115
116 if (!cfg)
117 return -ENOMEM;
118 acard->dev = pnp_request_card_device(card, id->devs[0].id, NULL);
119 if (acard->dev == NULL) {
120 kfree(cfg);
121 return -ENODEV;
122 }
123 acard->devmpu = pnp_request_card_device(card, id->devs[1].id, acard->dev);
124 acard->devopl = pnp_request_card_device(card, id->devs[2].id, acard->dev);
125
126 pdev = acard->dev;
127
128 pnp_init_resource_table(cfg);
129
130 /* override resources */
131 if (port[dev] != SNDRV_AUTO_PORT)
132 pnp_resource_change(&cfg->port_resource[0], port[dev], 16);
133 if (dma8[dev] != SNDRV_AUTO_DMA)
134 pnp_resource_change(&cfg->dma_resource[0], dma8[dev], 1);
135 if (dma16[dev] != SNDRV_AUTO_DMA)
136 pnp_resource_change(&cfg->dma_resource[1], dma16[dev], 1);
137 if (irq[dev] != SNDRV_AUTO_IRQ)
138 pnp_resource_change(&cfg->irq_resource[0], irq[dev], 1);
139 if (pnp_manual_config_dev(pdev, cfg, 0) < 0)
140 snd_printk(KERN_ERR PFX "AUDIO the requested resources are invalid, using auto config\n");
141 err = pnp_activate_dev(pdev);
142 if (err < 0) {
143 snd_printk(KERN_ERR PFX "AUDIO pnp configure failure\n");
144 kfree(cfg);
145 return err;
146 }
147 port[dev] = pnp_port_start(pdev, 0);
148 dma8[dev] = pnp_dma(pdev, 1);
149 dma16[dev] = pnp_dma(pdev, 0);
150 irq[dev] = pnp_irq(pdev, 0);
151
152 pdev = acard->devmpu;
153 if (pdev != NULL) {
154 pnp_init_resource_table(cfg);
155 if (mpu_port[dev] != SNDRV_AUTO_PORT)
156 pnp_resource_change(&cfg->port_resource[0], mpu_port[dev], 2);
157 if (mpu_irq[dev] != SNDRV_AUTO_IRQ)
158 pnp_resource_change(&cfg->irq_resource[0], mpu_irq[dev], 1);
159 if ((pnp_manual_config_dev(pdev, cfg, 0)) < 0)
160 snd_printk(KERN_ERR PFX "MPU401 the requested resources are invalid, using auto config\n");
161 err = pnp_activate_dev(pdev);
162 if (err < 0)
163 goto __mpu_error;
164 mpu_port[dev] = pnp_port_start(pdev, 0);
165 mpu_irq[dev] = pnp_irq(pdev, 0);
166 } else {
167 __mpu_error:
168 if (pdev) {
169 pnp_release_card_device(pdev);
170 snd_printk(KERN_ERR PFX "MPU401 pnp configure failure, skipping\n");
171 }
172 acard->devmpu = NULL;
173 mpu_port[dev] = -1;
174 }
175
176 pdev = acard->devopl;
177 if (pdev != NULL) {
178 pnp_init_resource_table(cfg);
179 if (fm_port[dev] != SNDRV_AUTO_PORT)
180 pnp_resource_change(&cfg->port_resource[0], fm_port[dev], 4);
181 if ((pnp_manual_config_dev(pdev, cfg, 0)) < 0)
182 snd_printk(KERN_ERR PFX "OPL3 the requested resources are invalid, using auto config\n");
183 err = pnp_activate_dev(pdev);
184 if (err < 0)
185 goto __fm_error;
186 fm_port[dev] = pnp_port_start(pdev, 0);
187 } else {
188 __fm_error:
189 if (pdev) {
190 pnp_release_card_device(pdev);
191 snd_printk(KERN_ERR PFX "OPL3 pnp configure failure, skipping\n");
192 }
193 acard->devopl = NULL;
194 fm_port[dev] = -1;
195 }
196
197 kfree(cfg);
198 return 0;
199}
200
201static int __init snd_card_als100_probe(int dev,
202 struct pnp_card_link *pcard,
203 const struct pnp_card_device_id *pid)
204{
205 int error;
206 sb_t *chip;
207 snd_card_t *card;
208 struct snd_card_als100 *acard;
209 opl3_t *opl3;
210
211 if ((card = snd_card_new(index[dev], id[dev], THIS_MODULE,
212 sizeof(struct snd_card_als100))) == NULL)
213 return -ENOMEM;
214 acard = (struct snd_card_als100 *)card->private_data;
215
216 if ((error = snd_card_als100_pnp(dev, acard, pcard, pid))) {
217 snd_card_free(card);
218 return error;
219 }
220 snd_card_set_dev(card, &pcard->card->dev);
221
222 if ((error = snd_sbdsp_create(card, port[dev],
223 irq[dev],
224 snd_sb16dsp_interrupt,
225 dma8[dev],
226 dma16[dev],
227 SB_HW_ALS100, &chip)) < 0) {
228 snd_card_free(card);
229 return error;
230 }
231
232 strcpy(card->driver, "ALS100");
233 strcpy(card->shortname, "Avance Logic ALS100");
234 sprintf(card->longname, "%s, %s at 0x%lx, irq %d, dma %d&%d",
235 card->shortname, chip->name, chip->port,
236 irq[dev], dma8[dev], dma16[dev]);
237
238 if ((error = snd_sb16dsp_pcm(chip, 0, NULL)) < 0) {
239 snd_card_free(card);
240 return error;
241 }
242
243 if ((error = snd_sbmixer_new(chip)) < 0) {
244 snd_card_free(card);
245 return error;
246 }
247
248 if (mpu_port[dev] > 0 && mpu_port[dev] != SNDRV_AUTO_PORT) {
249 if (snd_mpu401_uart_new(card, 0, MPU401_HW_ALS100,
250 mpu_port[dev], 0,
251 mpu_irq[dev], SA_INTERRUPT,
252 NULL) < 0)
253 snd_printk(KERN_ERR PFX "no MPU-401 device at 0x%lx\n", mpu_port[dev]);
254 }
255
256 if (fm_port[dev] > 0 && fm_port[dev] != SNDRV_AUTO_PORT) {
257 if (snd_opl3_create(card,
258 fm_port[dev], fm_port[dev] + 2,
259 OPL3_HW_AUTO, 0, &opl3) < 0) {
260 snd_printk(KERN_ERR PFX "no OPL device at 0x%lx-0x%lx\n",
261 fm_port[dev], fm_port[dev] + 2);
262 } else {
263 if ((error = snd_opl3_timer_new(opl3, 0, 1)) < 0) {
264 snd_card_free(card);
265 return error;
266 }
267 if ((error = snd_opl3_hwdep_new(opl3, 0, 1, NULL)) < 0) {
268 snd_card_free(card);
269 return error;
270 }
271 }
272 }
273
274 if ((error = snd_card_register(card)) < 0) {
275 snd_card_free(card);
276 return error;
277 }
278 pnp_set_card_drvdata(pcard, card);
279 return 0;
280}
281
282static int __devinit snd_als100_pnp_detect(struct pnp_card_link *card,
283 const struct pnp_card_device_id *id)
284{
285 static int dev;
286 int res;
287
288 for ( ; dev < SNDRV_CARDS; dev++) {
289 if (!enable[dev])
290 continue;
291 res = snd_card_als100_probe(dev, card, id);
292 if (res < 0)
293 return res;
294 dev++;
295 return 0;
296 }
297 return -ENODEV;
298}
299
300static void __devexit snd_als100_pnp_remove(struct pnp_card_link * pcard)
301{
302 snd_card_t *card = (snd_card_t *) pnp_get_card_drvdata(pcard);
303
304 snd_card_disconnect(card);
305 snd_card_free_in_thread(card);
306}
307
308static struct pnp_card_driver als100_pnpc_driver = {
309 .flags = PNP_DRIVER_RES_DISABLE,
310 .name = "als100",
311 .id_table = snd_als100_pnpids,
312 .probe = snd_als100_pnp_detect,
313 .remove = __devexit_p(snd_als100_pnp_remove),
314};
315
316static int __init alsa_card_als100_init(void)
317{
318 int cards = 0;
319
320 cards += pnp_register_card_driver(&als100_pnpc_driver);
321#ifdef MODULE
322 if (!cards) {
323 pnp_unregister_card_driver(&als100_pnpc_driver);
324 snd_printk(KERN_ERR "no ALS100 based soundcards found\n");
325 }
326#endif
327 return cards ? 0 : -ENODEV;
328}
329
330static void __exit alsa_card_als100_exit(void)
331{
332 pnp_unregister_card_driver(&als100_pnpc_driver);
333}
334
335module_init(alsa_card_als100_init)
336module_exit(alsa_card_als100_exit)
diff --git a/sound/isa/azt2320.c b/sound/isa/azt2320.c
new file mode 100644
index 000000000000..bb41c6ec2f43
--- /dev/null
+++ b/sound/isa/azt2320.c
@@ -0,0 +1,366 @@
1/*
2 card-azt2320.c - driver for Aztech Systems AZT2320 based soundcards.
3 Copyright (C) 1999-2000 by Massimo Piccioni <dafastidio@libero.it>
4
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 2 of the License, or
8 (at your option) any later version.
9
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18*/
19
20/*
21 This driver should provide support for most Aztech AZT2320 based cards.
22 Several AZT2316 chips are also supported/tested, but autoprobe doesn't
23 work: all module option have to be set.
24
25 No docs available for us at Aztech headquarters !!! Unbelievable ...
26 No other help obtained.
27
28 Thanks to Rainer Wiesner <rainer.wiesner@01019freenet.de> for the WSS
29 activation method (full-duplex audio!).
30*/
31
32#include <sound/driver.h>
33#include <asm/io.h>
34#include <linux/delay.h>
35#include <linux/init.h>
36#include <linux/time.h>
37#include <linux/wait.h>
38#include <linux/pnp.h>
39#include <linux/moduleparam.h>
40#include <sound/core.h>
41#include <sound/initval.h>
42#include <sound/cs4231.h>
43#include <sound/mpu401.h>
44#include <sound/opl3.h>
45
46#define PFX "azt2320: "
47
48MODULE_AUTHOR("Massimo Piccioni <dafastidio@libero.it>");
49MODULE_DESCRIPTION("Aztech Systems AZT2320");
50MODULE_LICENSE("GPL");
51MODULE_SUPPORTED_DEVICE("{{Aztech Systems,PRO16V},"
52 "{Aztech Systems,AZT2320},"
53 "{Aztech Systems,AZT3300},"
54 "{Aztech Systems,AZT2320},"
55 "{Aztech Systems,AZT3000}}");
56
57static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-MAX */
58static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* ID for this card */
59static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_ISAPNP; /* Enable this card */
60static long port[SNDRV_CARDS] = SNDRV_DEFAULT_PORT; /* PnP setup */
61static long wss_port[SNDRV_CARDS] = SNDRV_DEFAULT_PORT; /* PnP setup */
62static long mpu_port[SNDRV_CARDS] = SNDRV_DEFAULT_PORT; /* PnP setup */
63static long fm_port[SNDRV_CARDS] = SNDRV_DEFAULT_PORT; /* PnP setup */
64static int irq[SNDRV_CARDS] = SNDRV_DEFAULT_IRQ; /* Pnp setup */
65static int mpu_irq[SNDRV_CARDS] = SNDRV_DEFAULT_IRQ; /* Pnp setup */
66static int dma1[SNDRV_CARDS] = SNDRV_DEFAULT_DMA; /* PnP setup */
67static int dma2[SNDRV_CARDS] = SNDRV_DEFAULT_DMA; /* PnP setup */
68
69module_param_array(index, int, NULL, 0444);
70MODULE_PARM_DESC(index, "Index value for azt2320 based soundcard.");
71module_param_array(id, charp, NULL, 0444);
72MODULE_PARM_DESC(id, "ID string for azt2320 based soundcard.");
73module_param_array(enable, bool, NULL, 0444);
74MODULE_PARM_DESC(enable, "Enable azt2320 based soundcard.");
75module_param_array(port, long, NULL, 0444);
76MODULE_PARM_DESC(port, "Port # for azt2320 driver.");
77module_param_array(wss_port, long, NULL, 0444);
78MODULE_PARM_DESC(wss_port, "WSS Port # for azt2320 driver.");
79module_param_array(mpu_port, long, NULL, 0444);
80MODULE_PARM_DESC(mpu_port, "MPU-401 port # for azt2320 driver.");
81module_param_array(fm_port, long, NULL, 0444);
82MODULE_PARM_DESC(fm_port, "FM port # for azt2320 driver.");
83module_param_array(irq, int, NULL, 0444);
84MODULE_PARM_DESC(irq, "IRQ # for azt2320 driver.");
85module_param_array(mpu_irq, int, NULL, 0444);
86MODULE_PARM_DESC(mpu_irq, "MPU-401 IRQ # for azt2320 driver.");
87module_param_array(dma1, int, NULL, 0444);
88MODULE_PARM_DESC(dma1, "1st DMA # for azt2320 driver.");
89module_param_array(dma2, int, NULL, 0444);
90MODULE_PARM_DESC(dma2, "2nd DMA # for azt2320 driver.");
91
92struct snd_card_azt2320 {
93 int dev_no;
94 struct pnp_dev *dev;
95 struct pnp_dev *devmpu;
96};
97
98static struct pnp_card_device_id snd_azt2320_pnpids[] = {
99 /* PRO16V */
100 { .id = "AZT1008", .devs = { { "AZT1008" }, { "AZT2001" }, } },
101 /* Aztech Sound Galaxy 16 */
102 { .id = "AZT2320", .devs = { { "AZT0001" }, { "AZT0002" }, } },
103 /* Packard Bell Sound III 336 AM/SP */
104 { .id = "AZT3000", .devs = { { "AZT1003" }, { "AZT2001" }, } },
105 /* AT3300 */
106 { .id = "AZT3002", .devs = { { "AZT1004" }, { "AZT2001" }, } },
107 /* --- */
108 { .id = "AZT3005", .devs = { { "AZT1003" }, { "AZT2001" }, } },
109 /* --- */
110 { .id = "AZT3011", .devs = { { "AZT1003" }, { "AZT2001" }, } },
111 { .id = "" } /* end */
112};
113
114MODULE_DEVICE_TABLE(pnp_card, snd_azt2320_pnpids);
115
116#define DRIVER_NAME "snd-card-azt2320"
117
118static int __devinit snd_card_azt2320_pnp(int dev, struct snd_card_azt2320 *acard,
119 struct pnp_card_link *card,
120 const struct pnp_card_device_id *id)
121{
122 struct pnp_dev *pdev;
123 struct pnp_resource_table * cfg = kmalloc(sizeof(struct pnp_resource_table), GFP_KERNEL);
124 int err;
125
126 if (!cfg)
127 return -ENOMEM;
128
129 acard->dev = pnp_request_card_device(card, id->devs[0].id, NULL);
130 if (acard->dev == NULL) {
131 kfree(cfg);
132 return -ENODEV;
133 }
134
135 acard->devmpu = pnp_request_card_device(card, id->devs[1].id, NULL);
136
137 pdev = acard->dev;
138 pnp_init_resource_table(cfg);
139
140 /* override resources */
141 if (port[dev] != SNDRV_AUTO_PORT)
142 pnp_resource_change(&cfg->port_resource[0], port[dev], 16);
143 if (fm_port[dev] != SNDRV_AUTO_PORT)
144 pnp_resource_change(&cfg->port_resource[1], fm_port[dev], 4);
145 if (wss_port[dev] != SNDRV_AUTO_PORT)
146 pnp_resource_change(&cfg->port_resource[2], wss_port[dev], 4);
147 if (dma1[dev] != SNDRV_AUTO_DMA)
148 pnp_resource_change(&cfg->dma_resource[0], dma1[dev], 1);
149 if (dma2[dev] != SNDRV_AUTO_DMA)
150 pnp_resource_change(&cfg->dma_resource[1], dma2[dev], 1);
151 if (irq[dev] != SNDRV_AUTO_IRQ)
152 pnp_resource_change(&cfg->irq_resource[0], irq[dev], 1);
153 if ((pnp_manual_config_dev(pdev, cfg, 0)) < 0)
154 snd_printk(KERN_ERR PFX "AUDIO the requested resources are invalid, using auto config\n");
155
156 err = pnp_activate_dev(pdev);
157 if (err < 0) {
158 snd_printk(KERN_ERR PFX "AUDIO pnp configure failure\n");
159 kfree(cfg);
160 return err;
161 }
162 port[dev] = pnp_port_start(pdev, 0);
163 fm_port[dev] = pnp_port_start(pdev, 1);
164 wss_port[dev] = pnp_port_start(pdev, 2);
165 dma1[dev] = pnp_dma(pdev, 0);
166 dma2[dev] = pnp_dma(pdev, 1);
167 irq[dev] = pnp_irq(pdev, 0);
168
169 pdev = acard->devmpu;
170 if (pdev != NULL) {
171 pnp_init_resource_table(cfg);
172 if (mpu_port[dev] != SNDRV_AUTO_PORT)
173 pnp_resource_change(&cfg->port_resource[0], mpu_port[dev], 2);
174 if (mpu_irq[dev] != SNDRV_AUTO_IRQ)
175 pnp_resource_change(&cfg->irq_resource[0], mpu_irq[dev], 1);
176 if ((pnp_manual_config_dev(pdev, cfg, 0)) < 0)
177 snd_printk(KERN_ERR PFX "MPU401 the requested resources are invalid, using auto config\n");
178 err = pnp_activate_dev(pdev);
179 if (err < 0)
180 goto __mpu_error;
181 mpu_port[dev] = pnp_port_start(pdev, 0);
182 mpu_irq[dev] = pnp_irq(pdev, 0);
183 } else {
184 __mpu_error:
185 if (pdev) {
186 pnp_release_card_device(pdev);
187 snd_printk(KERN_ERR PFX "MPU401 pnp configure failure, skipping\n");
188 }
189 acard->devmpu = NULL;
190 mpu_port[dev] = -1;
191 }
192
193 kfree (cfg);
194 return 0;
195}
196
197/* same of snd_sbdsp_command by Jaroslav Kysela */
198static int __devinit snd_card_azt2320_command(unsigned long port, unsigned char val)
199{
200 int i;
201 unsigned long limit;
202
203 limit = jiffies + HZ / 10;
204 for (i = 50000; i && time_after(limit, jiffies); i--)
205 if (!(inb(port + 0x0c) & 0x80)) {
206 outb(val, port + 0x0c);
207 return 0;
208 }
209 return -EBUSY;
210}
211
212static int __devinit snd_card_azt2320_enable_wss(unsigned long port)
213{
214 int error;
215
216 if ((error = snd_card_azt2320_command(port, 0x09)))
217 return error;
218 if ((error = snd_card_azt2320_command(port, 0x00)))
219 return error;
220
221 mdelay(5);
222 return 0;
223}
224
225static int __devinit snd_card_azt2320_probe(int dev,
226 struct pnp_card_link *pcard,
227 const struct pnp_card_device_id *pid)
228{
229 int error;
230 snd_card_t *card;
231 struct snd_card_azt2320 *acard;
232 cs4231_t *chip;
233 opl3_t *opl3;
234
235 if ((card = snd_card_new(index[dev], id[dev], THIS_MODULE,
236 sizeof(struct snd_card_azt2320))) == NULL)
237 return -ENOMEM;
238 acard = (struct snd_card_azt2320 *)card->private_data;
239
240 if ((error = snd_card_azt2320_pnp(dev, acard, pcard, pid))) {
241 snd_card_free(card);
242 return error;
243 }
244 snd_card_set_dev(card, &pcard->card->dev);
245
246 if ((error = snd_card_azt2320_enable_wss(port[dev]))) {
247 snd_card_free(card);
248 return error;
249 }
250
251 if ((error = snd_cs4231_create(card, wss_port[dev], -1,
252 irq[dev],
253 dma1[dev],
254 dma2[dev],
255 CS4231_HW_DETECT, 0, &chip)) < 0) {
256 snd_card_free(card);
257 return error;
258 }
259
260 strcpy(card->driver, "AZT2320");
261 strcpy(card->shortname, "Aztech AZT2320");
262 sprintf(card->longname, "%s, WSS at 0x%lx, irq %i, dma %i&%i",
263 card->shortname, chip->port, irq[dev], dma1[dev], dma2[dev]);
264
265 if ((error = snd_cs4231_pcm(chip, 0, NULL)) < 0) {
266 snd_card_free(card);
267 return error;
268 }
269 if ((error = snd_cs4231_mixer(chip)) < 0) {
270 snd_card_free(card);
271 return error;
272 }
273 if ((error = snd_cs4231_timer(chip, 0, NULL)) < 0) {
274 snd_card_free(card);
275 return error;
276 }
277
278 if (mpu_port[dev] > 0 && mpu_port[dev] != SNDRV_AUTO_PORT) {
279 if (snd_mpu401_uart_new(card, 0, MPU401_HW_AZT2320,
280 mpu_port[dev], 0,
281 mpu_irq[dev], SA_INTERRUPT,
282 NULL) < 0)
283 snd_printk(KERN_ERR PFX "no MPU-401 device at 0x%lx\n", mpu_port[dev]);
284 }
285
286 if (fm_port[dev] > 0 && fm_port[dev] != SNDRV_AUTO_PORT) {
287 if (snd_opl3_create(card,
288 fm_port[dev], fm_port[dev] + 2,
289 OPL3_HW_AUTO, 0, &opl3) < 0) {
290 snd_printk(KERN_ERR PFX "no OPL device at 0x%lx-0x%lx\n",
291 fm_port[dev], fm_port[dev] + 2);
292 } else {
293 if ((error = snd_opl3_timer_new(opl3, 1, 2)) < 0) {
294 snd_card_free(card);
295 return error;
296 }
297 if ((error = snd_opl3_hwdep_new(opl3, 0, 1, NULL)) < 0) {
298 snd_card_free(card);
299 return error;
300 }
301 }
302 }
303
304 if ((error = snd_card_register(card)) < 0) {
305 snd_card_free(card);
306 return error;
307 }
308 pnp_set_card_drvdata(pcard, card);
309 return 0;
310}
311
312static int __devinit snd_azt2320_pnp_detect(struct pnp_card_link *card,
313 const struct pnp_card_device_id *id)
314{
315 static int dev;
316 int res;
317
318 for ( ; dev < SNDRV_CARDS; dev++) {
319 if (!enable[dev])
320 continue;
321 res = snd_card_azt2320_probe(dev, card, id);
322 if (res < 0)
323 return res;
324 dev++;
325 return 0;
326 }
327 return -ENODEV;
328}
329
330static void __devexit snd_azt2320_pnp_remove(struct pnp_card_link * pcard)
331{
332 snd_card_t *card = (snd_card_t *) pnp_get_card_drvdata(pcard);
333
334 snd_card_disconnect(card);
335 snd_card_free_in_thread(card);
336}
337
338static struct pnp_card_driver azt2320_pnpc_driver = {
339 .flags = PNP_DRIVER_RES_DISABLE,
340 .name = "azt2320",
341 .id_table = snd_azt2320_pnpids,
342 .probe = snd_azt2320_pnp_detect,
343 .remove = __devexit_p(snd_azt2320_pnp_remove),
344};
345
346static int __init alsa_card_azt2320_init(void)
347{
348 int cards = 0;
349
350 cards += pnp_register_card_driver(&azt2320_pnpc_driver);
351#ifdef MODULE
352 if (!cards) {
353 pnp_unregister_card_driver(&azt2320_pnpc_driver);
354 snd_printk(KERN_ERR "no AZT2320 based soundcards found\n");
355 }
356#endif
357 return cards ? 0 : -ENODEV;
358}
359
360static void __exit alsa_card_azt2320_exit(void)
361{
362 pnp_unregister_card_driver(&azt2320_pnpc_driver);
363}
364
365module_init(alsa_card_azt2320_init)
366module_exit(alsa_card_azt2320_exit)
diff --git a/sound/isa/cmi8330.c b/sound/isa/cmi8330.c
new file mode 100644
index 000000000000..46776cc0c157
--- /dev/null
+++ b/sound/isa/cmi8330.c
@@ -0,0 +1,633 @@
1/*
2 * Driver for C-Media's CMI8330 soundcards.
3 * Copyright (c) by George Talusan <gstalusan@uwaterloo.ca>
4 * http://www.undergrad.math.uwaterloo.ca/~gstalusa
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 *
20 */
21
22/*
23 * NOTES
24 *
25 * The extended registers contain mixer settings which are largely
26 * untapped for the time being.
27 *
28 * MPU401 and SPDIF are not supported yet. I don't have the hardware
29 * to aid in coding and testing, so I won't bother.
30 *
31 * To quickly load the module,
32 *
33 * modprobe -a snd-cmi8330 sbport=0x220 sbirq=5 sbdma8=1
34 * sbdma16=5 wssport=0x530 wssirq=11 wssdma=0
35 *
36 * This card has two mixers and two PCM devices. I've cheesed it such
37 * that recording and playback can be done through the same device.
38 * The driver "magically" routes the capturing to the AD1848 codec,
39 * and playback to the SB16 codec. This allows for full-duplex mode
40 * to some extent.
41 * The utilities in alsa-utils are aware of both devices, so passing
42 * the appropriate parameters to amixer and alsactl will give you
43 * full control over both mixers.
44 */
45
46#include <sound/driver.h>
47#include <linux/init.h>
48#include <linux/slab.h>
49#include <linux/pnp.h>
50#include <linux/moduleparam.h>
51#include <sound/core.h>
52#include <sound/ad1848.h>
53#include <sound/sb.h>
54#include <sound/initval.h>
55
56/*
57 */
58/* #define ENABLE_SB_MIXER */
59#define PLAYBACK_ON_SB
60
61/*
62 */
63MODULE_AUTHOR("George Talusan <gstalusan@uwaterloo.ca>");
64MODULE_DESCRIPTION("C-Media CMI8330");
65MODULE_LICENSE("GPL");
66MODULE_SUPPORTED_DEVICE("{{C-Media,CMI8330,isapnp:{CMI0001,@@@0001,@X@0001}}}");
67
68static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX;
69static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR;
70static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_ISAPNP;
71#ifdef CONFIG_PNP
72static int isapnp[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 1};
73#endif
74static long sbport[SNDRV_CARDS] = SNDRV_DEFAULT_PORT;
75static int sbirq[SNDRV_CARDS] = SNDRV_DEFAULT_IRQ;
76static int sbdma8[SNDRV_CARDS] = SNDRV_DEFAULT_DMA;
77static int sbdma16[SNDRV_CARDS] = SNDRV_DEFAULT_DMA;
78static long wssport[SNDRV_CARDS] = SNDRV_DEFAULT_PORT;
79static int wssirq[SNDRV_CARDS] = SNDRV_DEFAULT_IRQ;
80static int wssdma[SNDRV_CARDS] = SNDRV_DEFAULT_DMA;
81
82module_param_array(index, int, NULL, 0444);
83MODULE_PARM_DESC(index, "Index value for CMI8330 soundcard.");
84module_param_array(id, charp, NULL, 0444);
85MODULE_PARM_DESC(id, "ID string for CMI8330 soundcard.");
86module_param_array(enable, bool, NULL, 0444);
87MODULE_PARM_DESC(enable, "Enable CMI8330 soundcard.");
88#ifdef CONFIG_PNP
89module_param_array(isapnp, bool, NULL, 0444);
90MODULE_PARM_DESC(isapnp, "PnP detection for specified soundcard.");
91#endif
92
93module_param_array(sbport, long, NULL, 0444);
94MODULE_PARM_DESC(sbport, "Port # for CMI8330 SB driver.");
95module_param_array(sbirq, int, NULL, 0444);
96MODULE_PARM_DESC(sbirq, "IRQ # for CMI8330 SB driver.");
97module_param_array(sbdma8, int, NULL, 0444);
98MODULE_PARM_DESC(sbdma8, "DMA8 for CMI8330 SB driver.");
99module_param_array(sbdma16, int, NULL, 0444);
100MODULE_PARM_DESC(sbdma16, "DMA16 for CMI8330 SB driver.");
101
102module_param_array(wssport, long, NULL, 0444);
103MODULE_PARM_DESC(wssport, "Port # for CMI8330 WSS driver.");
104module_param_array(wssirq, int, NULL, 0444);
105MODULE_PARM_DESC(wssirq, "IRQ # for CMI8330 WSS driver.");
106module_param_array(wssdma, int, NULL, 0444);
107MODULE_PARM_DESC(wssdma, "DMA for CMI8330 WSS driver.");
108
109#define CMI8330_RMUX3D 16
110#define CMI8330_MUTEMUX 17
111#define CMI8330_OUTPUTVOL 18
112#define CMI8330_MASTVOL 19
113#define CMI8330_LINVOL 20
114#define CMI8330_CDINVOL 21
115#define CMI8330_WAVVOL 22
116#define CMI8330_RECMUX 23
117#define CMI8330_WAVGAIN 24
118#define CMI8330_LINGAIN 25
119#define CMI8330_CDINGAIN 26
120
121static unsigned char snd_cmi8330_image[((CMI8330_CDINGAIN)-16) + 1] =
122{
123 0x40, /* 16 - recording mux (SB-mixer-enabled) */
124#ifdef ENABLE_SB_MIXER
125 0x40, /* 17 - mute mux (Mode2) */
126#else
127 0x0, /* 17 - mute mux */
128#endif
129 0x0, /* 18 - vol */
130 0x0, /* 19 - master volume */
131 0x0, /* 20 - line-in volume */
132 0x0, /* 21 - cd-in volume */
133 0x0, /* 22 - wave volume */
134 0x0, /* 23 - mute/rec mux */
135 0x0, /* 24 - wave rec gain */
136 0x0, /* 25 - line-in rec gain */
137 0x0 /* 26 - cd-in rec gain */
138};
139
140typedef int (*snd_pcm_open_callback_t)(snd_pcm_substream_t *);
141
142struct snd_cmi8330 {
143#ifdef CONFIG_PNP
144 struct pnp_dev *cap;
145 struct pnp_dev *play;
146#endif
147 snd_card_t *card;
148 ad1848_t *wss;
149 sb_t *sb;
150
151 snd_pcm_t *pcm;
152 struct snd_cmi8330_stream {
153 snd_pcm_ops_t ops;
154 snd_pcm_open_callback_t open;
155 void *private_data; /* sb or wss */
156 } streams[2];
157};
158
159static snd_card_t *snd_cmi8330_legacy[SNDRV_CARDS] = SNDRV_DEFAULT_PTR;
160
161#ifdef CONFIG_PNP
162
163static struct pnp_card_device_id snd_cmi8330_pnpids[] = {
164 { .id = "CMI0001", .devs = { { "@@@0001" }, { "@X@0001" } } },
165 { .id = "" }
166};
167
168MODULE_DEVICE_TABLE(pnp_card, snd_cmi8330_pnpids);
169
170#endif
171
172
173static struct ad1848_mix_elem snd_cmi8330_controls[] __initdata = {
174AD1848_DOUBLE("Master Playback Volume", 0, CMI8330_MASTVOL, CMI8330_MASTVOL, 4, 0, 15, 0),
175AD1848_SINGLE("Loud Playback Switch", 0, CMI8330_MUTEMUX, 6, 1, 1),
176AD1848_DOUBLE("PCM Playback Switch", 0, AD1848_LEFT_OUTPUT, AD1848_RIGHT_OUTPUT, 7, 7, 1, 1),
177AD1848_DOUBLE("PCM Playback Volume", 0, AD1848_LEFT_OUTPUT, AD1848_RIGHT_OUTPUT, 0, 0, 63, 1),
178AD1848_DOUBLE("Line Playback Switch", 0, CMI8330_MUTEMUX, CMI8330_MUTEMUX, 4, 3, 1, 0),
179AD1848_DOUBLE("Line Playback Volume", 0, CMI8330_LINVOL, CMI8330_LINVOL, 4, 0, 15, 0),
180AD1848_DOUBLE("Line Capture Switch", 0, CMI8330_RMUX3D, CMI8330_RMUX3D, 2, 1, 1, 0),
181AD1848_DOUBLE("Line Capture Volume", 0, CMI8330_LINGAIN, CMI8330_LINGAIN, 4, 0, 15, 0),
182AD1848_DOUBLE("CD Playback Switch", 0, CMI8330_MUTEMUX, CMI8330_MUTEMUX, 2, 1, 1, 0),
183AD1848_DOUBLE("CD Capture Switch", 0, CMI8330_RMUX3D, CMI8330_RMUX3D, 4, 3, 1, 0),
184AD1848_DOUBLE("CD Playback Volume", 0, CMI8330_CDINVOL, CMI8330_CDINVOL, 4, 0, 15, 0),
185AD1848_DOUBLE("CD Capture Volume", 0, CMI8330_CDINGAIN, CMI8330_CDINGAIN, 4, 0, 15, 0),
186AD1848_SINGLE("Mic Playback Switch", 0, CMI8330_MUTEMUX, 0, 1, 0),
187AD1848_SINGLE("Mic Playback Volume", 0, CMI8330_OUTPUTVOL, 0, 7, 0),
188AD1848_SINGLE("Mic Capture Switch", 0, CMI8330_RMUX3D, 0, 1, 0),
189AD1848_SINGLE("Mic Capture Volume", 0, CMI8330_OUTPUTVOL, 5, 7, 0),
190AD1848_DOUBLE("Wavetable Playback Switch", 0, CMI8330_RECMUX, CMI8330_RECMUX, 1, 0, 1, 0),
191AD1848_DOUBLE("Wavetable Playback Volume", 0, CMI8330_WAVVOL, CMI8330_WAVVOL, 4, 0, 15, 0),
192AD1848_DOUBLE("Wavetable Capture Switch", 0, CMI8330_RECMUX, CMI8330_RECMUX, 5, 4, 1, 0),
193AD1848_DOUBLE("Wavetable Capture Volume", 0, CMI8330_WAVGAIN, CMI8330_WAVGAIN, 4, 0, 15, 0),
194AD1848_SINGLE("3D Control - Switch", 0, CMI8330_RMUX3D, 5, 1, 1),
195AD1848_SINGLE("PC Speaker Playback Volume", 0, CMI8330_OUTPUTVOL, 3, 3, 0),
196AD1848_SINGLE("FM Playback Switch", 0, CMI8330_RECMUX, 3, 1, 1),
197AD1848_SINGLE("IEC958 Input Capture Switch", 0, CMI8330_RMUX3D, 7, 1, 1),
198AD1848_SINGLE("IEC958 Input Playback Switch", 0, CMI8330_MUTEMUX, 7, 1, 1),
199};
200
201#ifdef ENABLE_SB_MIXER
202static struct sbmix_elem cmi8330_sb_mixers[] __initdata = {
203SB_DOUBLE("SB Master Playback Volume", SB_DSP4_MASTER_DEV, (SB_DSP4_MASTER_DEV + 1), 3, 3, 31),
204SB_DOUBLE("Tone Control - Bass", SB_DSP4_BASS_DEV, (SB_DSP4_BASS_DEV + 1), 4, 4, 15),
205SB_DOUBLE("Tone Control - Treble", SB_DSP4_TREBLE_DEV, (SB_DSP4_TREBLE_DEV + 1), 4, 4, 15),
206SB_DOUBLE("SB PCM Playback Volume", SB_DSP4_PCM_DEV, (SB_DSP4_PCM_DEV + 1), 3, 3, 31),
207SB_DOUBLE("SB Synth Playback Volume", SB_DSP4_SYNTH_DEV, (SB_DSP4_SYNTH_DEV + 1), 3, 3, 31),
208SB_DOUBLE("SB CD Playback Switch", SB_DSP4_OUTPUT_SW, SB_DSP4_OUTPUT_SW, 2, 1, 1),
209SB_DOUBLE("SB CD Playback Volume", SB_DSP4_CD_DEV, (SB_DSP4_CD_DEV + 1), 3, 3, 31),
210SB_DOUBLE("SB Line Playback Switch", SB_DSP4_OUTPUT_SW, SB_DSP4_OUTPUT_SW, 4, 3, 1),
211SB_DOUBLE("SB Line Playback Volume", SB_DSP4_LINE_DEV, (SB_DSP4_LINE_DEV + 1), 3, 3, 31),
212SB_SINGLE("SB Mic Playback Switch", SB_DSP4_OUTPUT_SW, 0, 1),
213SB_SINGLE("SB Mic Playback Volume", SB_DSP4_MIC_DEV, 3, 31),
214SB_SINGLE("SB PC Speaker Volume", SB_DSP4_SPEAKER_DEV, 6, 3),
215SB_DOUBLE("SB Capture Volume", SB_DSP4_IGAIN_DEV, (SB_DSP4_IGAIN_DEV + 1), 6, 6, 3),
216SB_DOUBLE("SB Playback Volume", SB_DSP4_OGAIN_DEV, (SB_DSP4_OGAIN_DEV + 1), 6, 6, 3),
217SB_SINGLE("SB Mic Auto Gain", SB_DSP4_MIC_AGC, 0, 1),
218};
219
220static unsigned char cmi8330_sb_init_values[][2] __initdata = {
221 { SB_DSP4_MASTER_DEV + 0, 0 },
222 { SB_DSP4_MASTER_DEV + 1, 0 },
223 { SB_DSP4_PCM_DEV + 0, 0 },
224 { SB_DSP4_PCM_DEV + 1, 0 },
225 { SB_DSP4_SYNTH_DEV + 0, 0 },
226 { SB_DSP4_SYNTH_DEV + 1, 0 },
227 { SB_DSP4_INPUT_LEFT, 0 },
228 { SB_DSP4_INPUT_RIGHT, 0 },
229 { SB_DSP4_OUTPUT_SW, 0 },
230 { SB_DSP4_SPEAKER_DEV, 0 },
231};
232
233
234static int __devinit cmi8330_add_sb_mixers(sb_t *chip)
235{
236 int idx, err;
237 unsigned long flags;
238
239 spin_lock_irqsave(&chip->mixer_lock, flags);
240 snd_sbmixer_write(chip, 0x00, 0x00); /* mixer reset */
241 spin_unlock_irqrestore(&chip->mixer_lock, flags);
242
243 /* mute and zero volume channels */
244 for (idx = 0; idx < ARRAY_SIZE(cmi8330_sb_init_values); idx++) {
245 spin_lock_irqsave(&chip->mixer_lock, flags);
246 snd_sbmixer_write(chip, cmi8330_sb_init_values[idx][0],
247 cmi8330_sb_init_values[idx][1]);
248 spin_unlock_irqrestore(&chip->mixer_lock, flags);
249 }
250
251 for (idx = 0; idx < ARRAY_SIZE(cmi8330_sb_mixers); idx++) {
252 if ((err = snd_sbmixer_add_ctl_elem(chip, &cmi8330_sb_mixers[idx])) < 0)
253 return err;
254 }
255 return 0;
256}
257#endif
258
259static int __devinit snd_cmi8330_mixer(snd_card_t *card, struct snd_cmi8330 *acard)
260{
261 unsigned int idx;
262 int err;
263
264 strcpy(card->mixername, "CMI8330/C3D");
265
266 for (idx = 0; idx < ARRAY_SIZE(snd_cmi8330_controls); idx++) {
267 if ((err = snd_ad1848_add_ctl_elem(acard->wss, &snd_cmi8330_controls[idx])) < 0)
268 return err;
269 }
270
271#ifdef ENABLE_SB_MIXER
272 if ((err = cmi8330_add_sb_mixers(acard->sb)) < 0)
273 return err;
274#endif
275 return 0;
276}
277
278#ifdef CONFIG_PNP
279static int __devinit snd_cmi8330_pnp(int dev, struct snd_cmi8330 *acard,
280 struct pnp_card_link *card,
281 const struct pnp_card_device_id *id)
282{
283 struct pnp_dev *pdev;
284 struct pnp_resource_table * cfg = kmalloc(sizeof(struct pnp_resource_table), GFP_KERNEL);
285 int err;
286
287 acard->cap = pnp_request_card_device(card, id->devs[0].id, NULL);
288 if (acard->cap == NULL) {
289 kfree(cfg);
290 return -EBUSY;
291 }
292 acard->play = pnp_request_card_device(card, id->devs[1].id, NULL);
293 if (acard->play == NULL) {
294 kfree(cfg);
295 return -EBUSY;
296 }
297
298 pdev = acard->cap;
299 pnp_init_resource_table(cfg);
300 /* allocate AD1848 resources */
301 if (wssport[dev] != SNDRV_AUTO_PORT)
302 pnp_resource_change(&cfg->port_resource[0], wssport[dev], 8);
303 if (wssdma[dev] != SNDRV_AUTO_DMA)
304 pnp_resource_change(&cfg->dma_resource[0], wssdma[dev], 1);
305 if (wssirq[dev] != SNDRV_AUTO_IRQ)
306 pnp_resource_change(&cfg->irq_resource[0], wssirq[dev], 1);
307
308 err = pnp_manual_config_dev(pdev, cfg, 0);
309 if (err < 0)
310 snd_printk(KERN_ERR "CMI8330/C3D (AD1848) PnP manual resources are invalid, using auto config\n");
311 err = pnp_activate_dev(pdev);
312 if (err < 0) {
313 snd_printk(KERN_ERR "CMI8330/C3D (AD1848) PnP configure failure\n");
314 kfree(cfg);
315 return -EBUSY;
316 }
317 wssport[dev] = pnp_port_start(pdev, 0);
318 wssdma[dev] = pnp_dma(pdev, 0);
319 wssirq[dev] = pnp_irq(pdev, 0);
320
321 /* allocate SB16 resources */
322 pdev = acard->play;
323 pnp_init_resource_table(cfg);
324 if (sbport[dev] != SNDRV_AUTO_PORT)
325 pnp_resource_change(&cfg->port_resource[0], sbport[dev], 16);
326 if (sbdma8[dev] != SNDRV_AUTO_DMA)
327 pnp_resource_change(&cfg->dma_resource[0], sbdma8[dev], 1);
328 if (sbdma16[dev] != SNDRV_AUTO_DMA)
329 pnp_resource_change(&cfg->dma_resource[1], sbdma16[dev], 1);
330 if (sbirq[dev] != SNDRV_AUTO_IRQ)
331 pnp_resource_change(&cfg->irq_resource[0], sbirq[dev], 1);
332
333 err = pnp_manual_config_dev(pdev, cfg, 0);
334 if (err < 0)
335 snd_printk(KERN_ERR "CMI8330/C3D (SB16) PnP manual resources are invalid, using auto config\n");
336 err = pnp_activate_dev(pdev);
337 if (err < 0) {
338 snd_printk(KERN_ERR "CMI8330/C3D (SB16) PnP configure failure\n");
339 kfree(cfg);
340 return -EBUSY;
341 }
342 sbport[dev] = pnp_port_start(pdev, 0);
343 sbdma8[dev] = pnp_dma(pdev, 0);
344 sbdma16[dev] = pnp_dma(pdev, 1);
345 sbirq[dev] = pnp_irq(pdev, 0);
346
347 kfree(cfg);
348 return 0;
349}
350#endif
351
352/*
353 * PCM interface
354 *
355 * since we call the different chip interfaces for playback and capture
356 * directions, we need a trick.
357 *
358 * - copy the ops for each direction into a local record.
359 * - replace the open callback with the new one, which replaces the
360 * substream->private_data with the corresponding chip instance
361 * and calls again the original open callback of the chip.
362 *
363 */
364
365#ifdef PLAYBACK_ON_SB
366#define CMI_SB_STREAM SNDRV_PCM_STREAM_PLAYBACK
367#define CMI_AD_STREAM SNDRV_PCM_STREAM_CAPTURE
368#else
369#define CMI_SB_STREAM SNDRV_PCM_STREAM_CAPTURE
370#define CMI_AD_STREAM SNDRV_PCM_STREAM_PLAYBACK
371#endif
372
373static int snd_cmi8330_playback_open(snd_pcm_substream_t * substream)
374{
375 struct snd_cmi8330 *chip = snd_pcm_substream_chip(substream);
376
377 /* replace the private_data and call the original open callback */
378 substream->private_data = chip->streams[SNDRV_PCM_STREAM_PLAYBACK].private_data;
379 return chip->streams[SNDRV_PCM_STREAM_PLAYBACK].open(substream);
380}
381
382static int snd_cmi8330_capture_open(snd_pcm_substream_t * substream)
383{
384 struct snd_cmi8330 *chip = snd_pcm_substream_chip(substream);
385
386 /* replace the private_data and call the original open callback */
387 substream->private_data = chip->streams[SNDRV_PCM_STREAM_CAPTURE].private_data;
388 return chip->streams[SNDRV_PCM_STREAM_CAPTURE].open(substream);
389}
390
391static void snd_cmi8330_pcm_free(snd_pcm_t *pcm)
392{
393 snd_pcm_lib_preallocate_free_for_all(pcm);
394}
395
396static int __devinit snd_cmi8330_pcm(snd_card_t *card, struct snd_cmi8330 *chip)
397{
398 snd_pcm_t *pcm;
399 const snd_pcm_ops_t *ops;
400 int err;
401 static snd_pcm_open_callback_t cmi_open_callbacks[2] = {
402 snd_cmi8330_playback_open,
403 snd_cmi8330_capture_open
404 };
405
406 if ((err = snd_pcm_new(card, "CMI8330", 0, 1, 1, &pcm)) < 0)
407 return err;
408 strcpy(pcm->name, "CMI8330");
409 pcm->private_data = chip;
410 pcm->private_free = snd_cmi8330_pcm_free;
411
412 /* SB16 */
413 ops = snd_sb16dsp_get_pcm_ops(CMI_SB_STREAM);
414 chip->streams[CMI_SB_STREAM].ops = *ops;
415 chip->streams[CMI_SB_STREAM].open = ops->open;
416 chip->streams[CMI_SB_STREAM].ops.open = cmi_open_callbacks[CMI_SB_STREAM];
417 chip->streams[CMI_SB_STREAM].private_data = chip->sb;
418
419 /* AD1848 */
420 ops = snd_ad1848_get_pcm_ops(CMI_AD_STREAM);
421 chip->streams[CMI_AD_STREAM].ops = *ops;
422 chip->streams[CMI_AD_STREAM].open = ops->open;
423 chip->streams[CMI_AD_STREAM].ops.open = cmi_open_callbacks[CMI_AD_STREAM];
424 chip->streams[CMI_AD_STREAM].private_data = chip->wss;
425
426 snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &chip->streams[SNDRV_PCM_STREAM_PLAYBACK].ops);
427 snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &chip->streams[SNDRV_PCM_STREAM_CAPTURE].ops);
428
429 snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV,
430 snd_dma_isa_data(),
431 64*1024, 128*1024);
432 chip->pcm = pcm;
433
434 return 0;
435}
436
437
438/*
439 */
440
441static int __devinit snd_cmi8330_probe(int dev,
442 struct pnp_card_link *pcard,
443 const struct pnp_card_device_id *pid)
444{
445 snd_card_t *card;
446 struct snd_cmi8330 *acard;
447 unsigned long flags;
448 int i, err;
449
450#ifdef CONFIG_PNP
451 if (!isapnp[dev]) {
452#endif
453 if (wssport[dev] == SNDRV_AUTO_PORT) {
454 snd_printk("specify wssport\n");
455 return -EINVAL;
456 }
457 if (sbport[dev] == SNDRV_AUTO_PORT) {
458 snd_printk("specify sbport\n");
459 return -EINVAL;
460 }
461#ifdef CONFIG_PNP
462 }
463#endif
464 card = snd_card_new(index[dev], id[dev], THIS_MODULE,
465 sizeof(struct snd_cmi8330));
466 if (card == NULL) {
467 snd_printk("could not get a new card\n");
468 return -ENOMEM;
469 }
470 acard = (struct snd_cmi8330 *)card->private_data;
471 acard->card = card;
472
473#ifdef CONFIG_PNP
474 if (isapnp[dev]) {
475 if ((err = snd_cmi8330_pnp(dev, acard, pcard, pid)) < 0) {
476 snd_printk("PnP detection failed\n");
477 snd_card_free(card);
478 return err;
479 }
480 snd_card_set_dev(card, &pcard->card->dev);
481 }
482#endif
483
484 if ((err = snd_ad1848_create(card,
485 wssport[dev] + 4,
486 wssirq[dev],
487 wssdma[dev],
488 AD1848_HW_DETECT,
489 &acard->wss)) < 0) {
490 snd_printk("(AD1848) device busy??\n");
491 snd_card_free(card);
492 return err;
493 }
494 if (acard->wss->hardware != AD1848_HW_CMI8330) {
495 snd_printk("(AD1848) not found during probe\n");
496 snd_card_free(card);
497 return -ENODEV;
498 }
499
500 if ((err = snd_sbdsp_create(card, sbport[dev],
501 sbirq[dev],
502 snd_sb16dsp_interrupt,
503 sbdma8[dev],
504 sbdma16[dev],
505 SB_HW_AUTO, &acard->sb)) < 0) {
506 snd_printk("(SB16) device busy??\n");
507 snd_card_free(card);
508 return err;
509 }
510 if (acard->sb->hardware != SB_HW_16) {
511 snd_printk("(SB16) not found during probe\n");
512 snd_card_free(card);
513 return -ENODEV;
514 }
515
516 spin_lock_irqsave(&acard->wss->reg_lock, flags);
517 snd_ad1848_out(acard->wss, AD1848_MISC_INFO, 0x40); /* switch on MODE2 */
518 for (i = CMI8330_RMUX3D; i <= CMI8330_CDINGAIN; i++)
519 snd_ad1848_out(acard->wss, i, snd_cmi8330_image[i - CMI8330_RMUX3D]);
520 spin_unlock_irqrestore(&acard->wss->reg_lock, flags);
521
522 if ((err = snd_cmi8330_mixer(card, acard)) < 0) {
523 snd_printk("failed to create mixers\n");
524 snd_card_free(card);
525 return err;
526 }
527
528 if ((err = snd_cmi8330_pcm(card, acard)) < 0) {
529 snd_printk("failed to create pcms\n");
530 snd_card_free(card);
531 return err;
532 }
533
534 strcpy(card->driver, "CMI8330/C3D");
535 strcpy(card->shortname, "C-Media CMI8330/C3D");
536 sprintf(card->longname, "%s at 0x%lx, irq %d, dma %d",
537 card->shortname,
538 acard->wss->port,
539 wssirq[dev],
540 wssdma[dev]);
541
542 if ((err = snd_card_register(card)) < 0) {
543 snd_card_free(card);
544 return err;
545 }
546
547 if (pcard)
548 pnp_set_card_drvdata(pcard, card);
549 else
550 snd_cmi8330_legacy[dev] = card;
551 return 0;
552}
553
554#ifdef CONFIG_PNP
555static int __devinit snd_cmi8330_pnp_detect(struct pnp_card_link *card,
556 const struct pnp_card_device_id *id)
557{
558 static int dev;
559 int res;
560
561 for ( ; dev < SNDRV_CARDS; dev++) {
562 if (!enable[dev] || !isapnp[dev])
563 continue;
564 res = snd_cmi8330_probe(dev, card, id);
565 if (res < 0)
566 return res;
567 dev++;
568 return 0;
569 }
570 return -ENODEV;
571}
572
573static void __devexit snd_cmi8330_pnp_remove(struct pnp_card_link * pcard)
574{
575 snd_card_t *card = (snd_card_t *) pnp_get_card_drvdata(pcard);
576
577 snd_card_disconnect(card);
578 snd_card_free_in_thread(card);
579}
580
581static struct pnp_card_driver cmi8330_pnpc_driver = {
582 .flags = PNP_DRIVER_RES_DISABLE,
583 .name = "cmi8330",
584 .id_table = snd_cmi8330_pnpids,
585 .probe = snd_cmi8330_pnp_detect,
586 .remove = __devexit_p(snd_cmi8330_pnp_remove),
587};
588#endif /* CONFIG_PNP */
589
590static int __init alsa_card_cmi8330_init(void)
591{
592 int dev, cards = 0;
593
594 for (dev = 0; dev < SNDRV_CARDS; dev++) {
595 if (!enable[dev])
596 continue;
597#ifdef CONFIG_PNP
598 if (isapnp[dev])
599 continue;
600#endif
601 if (snd_cmi8330_probe(dev, NULL, NULL) >= 0)
602 cards++;
603 }
604#ifdef CONFIG_PNP
605 cards += pnp_register_card_driver(&cmi8330_pnpc_driver);
606#endif
607
608 if (!cards) {
609#ifdef CONFIG_PNP
610 pnp_unregister_card_driver(&cmi8330_pnpc_driver);
611#endif
612#ifdef MODULE
613 snd_printk(KERN_ERR "CMI8330 not found or device busy\n");
614#endif
615 return -ENODEV;
616 }
617 return 0;
618}
619
620static void __exit alsa_card_cmi8330_exit(void)
621{
622 int i;
623
624#ifdef CONFIG_PNP
625 /* PnP cards first */
626 pnp_unregister_card_driver(&cmi8330_pnpc_driver);
627#endif
628 for (i = 0; i < SNDRV_CARDS; i++)
629 snd_card_free(snd_cmi8330_legacy[i]);
630}
631
632module_init(alsa_card_cmi8330_init)
633module_exit(alsa_card_cmi8330_exit)
diff --git a/sound/isa/cs423x/Makefile b/sound/isa/cs423x/Makefile
new file mode 100644
index 000000000000..d2afaea30cbc
--- /dev/null
+++ b/sound/isa/cs423x/Makefile
@@ -0,0 +1,25 @@
1#
2# Makefile for ALSA
3# Copyright (c) 2001 by Jaroslav Kysela <perex@suse.cz>
4#
5
6snd-cs4231-lib-objs := cs4231_lib.o
7snd-cs4236-lib-objs := cs4236_lib.o
8snd-cs4231-objs := cs4231.o
9snd-cs4232-objs := cs4232.o
10snd-cs4236-objs := cs4236.o
11
12# Toplevel Module Dependency
13obj-$(CONFIG_SND_AZT2320) += snd-cs4231-lib.o
14obj-$(CONFIG_SND_OPL3SA2) += snd-cs4231-lib.o
15obj-$(CONFIG_SND_CS4231) += snd-cs4231.o snd-cs4231-lib.o
16obj-$(CONFIG_SND_CS4232) += snd-cs4232.o snd-cs4231-lib.o
17obj-$(CONFIG_SND_CS4236) += snd-cs4236.o snd-cs4236-lib.o snd-cs4231-lib.o
18obj-$(CONFIG_SND_GUSMAX) += snd-cs4231-lib.o
19obj-$(CONFIG_SND_INTERWAVE) += snd-cs4231-lib.o
20obj-$(CONFIG_SND_INTERWAVE_STB) += snd-cs4231-lib.o
21obj-$(CONFIG_SND_OPTI92X_CS4231) += snd-cs4231-lib.o
22obj-$(CONFIG_SND_WAVEFRONT) += snd-cs4231-lib.o
23obj-$(CONFIG_SND_SSCAPE) += snd-cs4231-lib.o
24
25obj-m := $(sort $(obj-m))
diff --git a/sound/isa/cs423x/cs4231.c b/sound/isa/cs423x/cs4231.c
new file mode 100644
index 000000000000..7640837659ea
--- /dev/null
+++ b/sound/isa/cs423x/cs4231.c
@@ -0,0 +1,169 @@
1/*
2 * Generic driver for CS4231 chips
3 * Copyright (c) by Jaroslav Kysela <perex@suse.cz>
4 * Originally the CS4232/CS4232A driver, modified for use on CS4231 by
5 * Tugrul Galatali <galatalt@stuy.edu>
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 *
21 */
22
23#include <sound/driver.h>
24#include <linux/init.h>
25#include <linux/time.h>
26#include <linux/wait.h>
27#include <linux/moduleparam.h>
28#include <sound/core.h>
29#include <sound/cs4231.h>
30#include <sound/mpu401.h>
31#include <sound/initval.h>
32
33MODULE_AUTHOR("Jaroslav Kysela <perex@suse.cz>");
34MODULE_DESCRIPTION("Generic CS4231");
35MODULE_LICENSE("GPL");
36MODULE_SUPPORTED_DEVICE("{{Crystal Semiconductors,CS4231}}");
37
38static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-MAX */
39static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* ID for this card */
40static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE; /* Enable this card */
41static long port[SNDRV_CARDS] = SNDRV_DEFAULT_PORT; /* PnP setup */
42static long mpu_port[SNDRV_CARDS] = SNDRV_DEFAULT_PORT; /* PnP setup */
43static int irq[SNDRV_CARDS] = SNDRV_DEFAULT_IRQ; /* 5,7,9,11,12,15 */
44static int mpu_irq[SNDRV_CARDS] = SNDRV_DEFAULT_IRQ; /* 9,11,12,15 */
45static int dma1[SNDRV_CARDS] = SNDRV_DEFAULT_DMA; /* 0,1,3,5,6,7 */
46static int dma2[SNDRV_CARDS] = SNDRV_DEFAULT_DMA; /* 0,1,3,5,6,7 */
47
48module_param_array(index, int, NULL, 0444);
49MODULE_PARM_DESC(index, "Index value for CS4231 soundcard.");
50module_param_array(id, charp, NULL, 0444);
51MODULE_PARM_DESC(id, "ID string for CS4231 soundcard.");
52module_param_array(enable, bool, NULL, 0444);
53MODULE_PARM_DESC(enable, "Enable CS4231 soundcard.");
54module_param_array(port, long, NULL, 0444);
55MODULE_PARM_DESC(port, "Port # for CS4231 driver.");
56module_param_array(mpu_port, long, NULL, 0444);
57MODULE_PARM_DESC(mpu_port, "MPU-401 port # for CS4231 driver.");
58module_param_array(irq, int, NULL, 0444);
59MODULE_PARM_DESC(irq, "IRQ # for CS4231 driver.");
60module_param_array(mpu_irq, int, NULL, 0444);
61MODULE_PARM_DESC(mpu_irq, "MPU-401 IRQ # for CS4231 driver.");
62module_param_array(dma1, int, NULL, 0444);
63MODULE_PARM_DESC(dma1, "DMA1 # for CS4231 driver.");
64module_param_array(dma2, int, NULL, 0444);
65MODULE_PARM_DESC(dma2, "DMA2 # for CS4231 driver.");
66
67static snd_card_t *snd_cs4231_cards[SNDRV_CARDS] = SNDRV_DEFAULT_PTR;
68
69
70static int __init snd_card_cs4231_probe(int dev)
71{
72 snd_card_t *card;
73 struct snd_card_cs4231 *acard;
74 snd_pcm_t *pcm = NULL;
75 cs4231_t *chip;
76 int err;
77
78 if (port[dev] == SNDRV_AUTO_PORT) {
79 snd_printk("specify port\n");
80 return -EINVAL;
81 }
82 if (irq[dev] == SNDRV_AUTO_IRQ) {
83 snd_printk("specify irq\n");
84 return -EINVAL;
85 }
86 if (dma1[dev] == SNDRV_AUTO_DMA) {
87 snd_printk("specify dma1\n");
88 return -EINVAL;
89 }
90 card = snd_card_new(index[dev], id[dev], THIS_MODULE, 0);
91 if (card == NULL)
92 return -ENOMEM;
93 acard = (struct snd_card_cs4231 *)card->private_data;
94 if ((err = snd_cs4231_create(card, port[dev], -1,
95 irq[dev],
96 dma1[dev],
97 dma2[dev],
98 CS4231_HW_DETECT,
99 0, &chip)) < 0) {
100 snd_card_free(card);
101 return err;
102 }
103
104 if ((err = snd_cs4231_pcm(chip, 0, &pcm)) < 0) {
105 snd_card_free(card);
106 return err;
107 }
108
109 strcpy(card->driver, "CS4231");
110 strcpy(card->shortname, pcm->name);
111 sprintf(card->longname, "%s at 0x%lx, irq %d, dma %d",
112 pcm->name, chip->port, irq[dev], dma1[dev]);
113 if (dma2[dev] >= 0)
114 sprintf(card->longname + strlen(card->longname), "&%d", dma2[dev]);
115
116 if ((err = snd_cs4231_mixer(chip)) < 0) {
117 snd_card_free(card);
118 return err;
119 }
120 if ((err = snd_cs4231_timer(chip, 0, NULL)) < 0) {
121 snd_card_free(card);
122 return err;
123 }
124
125 if (mpu_port[dev] > 0 && mpu_port[dev] != SNDRV_AUTO_PORT) {
126 if (mpu_irq[dev] == SNDRV_AUTO_IRQ)
127 mpu_irq[dev] = -1;
128 if (snd_mpu401_uart_new(card, 0, MPU401_HW_CS4232,
129 mpu_port[dev], 0,
130 mpu_irq[dev],
131 mpu_irq[dev] >= 0 ? SA_INTERRUPT : 0,
132 NULL) < 0)
133 printk(KERN_ERR "cs4231: MPU401 not detected\n");
134 }
135 if ((err = snd_card_register(card)) < 0) {
136 snd_card_free(card);
137 return err;
138 }
139 snd_cs4231_cards[dev] = card;
140 return 0;
141}
142
143static int __init alsa_card_cs4231_init(void)
144{
145 int dev, cards;
146
147 for (dev = cards = 0; dev < SNDRV_CARDS && enable[dev]; dev++) {
148 if (snd_card_cs4231_probe(dev) >= 0)
149 cards++;
150 }
151 if (!cards) {
152#ifdef MODULE
153 printk(KERN_ERR "CS4231 soundcard not found or device busy\n");
154#endif
155 return -ENODEV;
156 }
157 return 0;
158}
159
160static void __exit alsa_card_cs4231_exit(void)
161{
162 int idx;
163
164 for (idx = 0; idx < SNDRV_CARDS; idx++)
165 snd_card_free(snd_cs4231_cards[idx]);
166}
167
168module_init(alsa_card_cs4231_init)
169module_exit(alsa_card_cs4231_exit)
diff --git a/sound/isa/cs423x/cs4231_lib.c b/sound/isa/cs423x/cs4231_lib.c
new file mode 100644
index 000000000000..3e7a2a33a5ca
--- /dev/null
+++ b/sound/isa/cs423x/cs4231_lib.c
@@ -0,0 +1,1964 @@
1/*
2 * Copyright (c) by Jaroslav Kysela <perex@suse.cz>
3 * Routines for control of CS4231(A)/CS4232/InterWave & compatible chips
4 *
5 * Bugs:
6 * - sometimes record brokes playback with WSS portion of
7 * Yamaha OPL3-SA3 chip
8 * - CS4231 (GUS MAX) - still trouble with occasional noises
9 * - broken initialization?
10 *
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 2 of the License, or
14 * (at your option) any later version.
15 *
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
20 *
21 * You should have received a copy of the GNU General Public License
22 * along with this program; if not, write to the Free Software
23 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
24 *
25 */
26
27#include <sound/driver.h>
28#include <linux/delay.h>
29#include <linux/pm.h>
30#include <linux/init.h>
31#include <linux/interrupt.h>
32#include <linux/slab.h>
33#include <linux/ioport.h>
34#include <sound/core.h>
35#include <sound/cs4231.h>
36#include <sound/pcm_params.h>
37
38#include <asm/io.h>
39#include <asm/dma.h>
40#include <asm/irq.h>
41
42MODULE_AUTHOR("Jaroslav Kysela <perex@suse.cz>");
43MODULE_DESCRIPTION("Routines for control of CS4231(A)/CS4232/InterWave & compatible chips");
44MODULE_LICENSE("GPL");
45
46#if 0
47#define SNDRV_DEBUG_MCE
48#endif
49
50/*
51 * Some variables
52 */
53
54static unsigned char freq_bits[14] = {
55 /* 5510 */ 0x00 | CS4231_XTAL2,
56 /* 6620 */ 0x0E | CS4231_XTAL2,
57 /* 8000 */ 0x00 | CS4231_XTAL1,
58 /* 9600 */ 0x0E | CS4231_XTAL1,
59 /* 11025 */ 0x02 | CS4231_XTAL2,
60 /* 16000 */ 0x02 | CS4231_XTAL1,
61 /* 18900 */ 0x04 | CS4231_XTAL2,
62 /* 22050 */ 0x06 | CS4231_XTAL2,
63 /* 27042 */ 0x04 | CS4231_XTAL1,
64 /* 32000 */ 0x06 | CS4231_XTAL1,
65 /* 33075 */ 0x0C | CS4231_XTAL2,
66 /* 37800 */ 0x08 | CS4231_XTAL2,
67 /* 44100 */ 0x0A | CS4231_XTAL2,
68 /* 48000 */ 0x0C | CS4231_XTAL1
69};
70
71static unsigned int rates[14] = {
72 5510, 6620, 8000, 9600, 11025, 16000, 18900, 22050,
73 27042, 32000, 33075, 37800, 44100, 48000
74};
75
76static snd_pcm_hw_constraint_list_t hw_constraints_rates = {
77 .count = 14,
78 .list = rates,
79 .mask = 0,
80};
81
82static int snd_cs4231_xrate(snd_pcm_runtime_t *runtime)
83{
84 return snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE, &hw_constraints_rates);
85}
86
87static unsigned char snd_cs4231_original_image[32] =
88{
89 0x00, /* 00/00 - lic */
90 0x00, /* 01/01 - ric */
91 0x9f, /* 02/02 - la1ic */
92 0x9f, /* 03/03 - ra1ic */
93 0x9f, /* 04/04 - la2ic */
94 0x9f, /* 05/05 - ra2ic */
95 0xbf, /* 06/06 - loc */
96 0xbf, /* 07/07 - roc */
97 0x20, /* 08/08 - pdfr */
98 CS4231_AUTOCALIB, /* 09/09 - ic */
99 0x00, /* 0a/10 - pc */
100 0x00, /* 0b/11 - ti */
101 CS4231_MODE2, /* 0c/12 - mi */
102 0xfc, /* 0d/13 - lbc */
103 0x00, /* 0e/14 - pbru */
104 0x00, /* 0f/15 - pbrl */
105 0x80, /* 10/16 - afei */
106 0x01, /* 11/17 - afeii */
107 0x9f, /* 12/18 - llic */
108 0x9f, /* 13/19 - rlic */
109 0x00, /* 14/20 - tlb */
110 0x00, /* 15/21 - thb */
111 0x00, /* 16/22 - la3mic/reserved */
112 0x00, /* 17/23 - ra3mic/reserved */
113 0x00, /* 18/24 - afs */
114 0x00, /* 19/25 - lamoc/version */
115 0xcf, /* 1a/26 - mioc */
116 0x00, /* 1b/27 - ramoc/reserved */
117 0x20, /* 1c/28 - cdfr */
118 0x00, /* 1d/29 - res4 */
119 0x00, /* 1e/30 - cbru */
120 0x00, /* 1f/31 - cbrl */
121};
122
123/*
124 * Basic I/O functions
125 */
126
127#if !defined(EBUS_SUPPORT) && !defined(SBUS_SUPPORT)
128#define __CS4231_INLINE__ inline
129#else
130#define __CS4231_INLINE__ /* nothing */
131#endif
132
133static __CS4231_INLINE__ void cs4231_outb(cs4231_t *chip, u8 offset, u8 val)
134{
135#ifdef EBUS_SUPPORT
136 if (chip->ebus->flag) {
137 writeb(val, chip->port + (offset << 2));
138 } else {
139#endif
140#ifdef SBUS_SUPPORT
141 sbus_writeb(val, chip->port + (offset << 2));
142#endif
143#ifdef EBUS_SUPPORT
144 }
145#endif
146#ifdef LEGACY_SUPPORT
147 outb(val, chip->port + offset);
148#endif
149}
150
151static __CS4231_INLINE__ u8 cs4231_inb(cs4231_t *chip, u8 offset)
152{
153#ifdef EBUS_SUPPORT
154 if (chip->ebus_flag) {
155 return readb(chip->port + (offset << 2));
156 } else {
157#endif
158#ifdef SBUS_SUPPORT
159 return sbus_readb(chip->port + (offset << 2));
160#endif
161#ifdef EBUS_SUPPORT
162 }
163#endif
164#ifdef LEGACY_SUPPORT
165 return inb(chip->port + offset);
166#endif
167}
168
169static void snd_cs4231_outm(cs4231_t *chip, unsigned char reg,
170 unsigned char mask, unsigned char value)
171{
172 int timeout;
173 unsigned char tmp;
174
175 for (timeout = 250;
176 timeout > 0 && (cs4231_inb(chip, CS4231P(REGSEL)) & CS4231_INIT);
177 timeout--)
178 udelay(100);
179#ifdef CONFIG_SND_DEBUG
180 if (cs4231_inb(chip, CS4231P(REGSEL)) & CS4231_INIT)
181 snd_printk("outm: auto calibration time out - reg = 0x%x, value = 0x%x\n", reg, value);
182#endif
183 if (chip->calibrate_mute) {
184 chip->image[reg] &= mask;
185 chip->image[reg] |= value;
186 } else {
187 cs4231_outb(chip, CS4231P(REGSEL), chip->mce_bit | reg);
188 mb();
189 tmp = (chip->image[reg] & mask) | value;
190 cs4231_outb(chip, CS4231P(REG), tmp);
191 chip->image[reg] = tmp;
192 mb();
193 }
194}
195
196static void snd_cs4231_dout(cs4231_t *chip, unsigned char reg, unsigned char value)
197{
198 int timeout;
199
200 for (timeout = 250;
201 timeout > 0 && (cs4231_inb(chip, CS4231P(REGSEL)) & CS4231_INIT);
202 timeout--)
203 udelay(10);
204 cs4231_outb(chip, CS4231P(REGSEL), chip->mce_bit | reg);
205 cs4231_outb(chip, CS4231P(REG), value);
206 mb();
207}
208
209void snd_cs4231_out(cs4231_t *chip, unsigned char reg, unsigned char value)
210{
211 int timeout;
212
213 for (timeout = 250;
214 timeout > 0 && (cs4231_inb(chip, CS4231P(REGSEL)) & CS4231_INIT);
215 timeout--)
216 udelay(100);
217#ifdef CONFIG_SND_DEBUG
218 if (cs4231_inb(chip, CS4231P(REGSEL)) & CS4231_INIT)
219 snd_printk("out: auto calibration time out - reg = 0x%x, value = 0x%x\n", reg, value);
220#endif
221 cs4231_outb(chip, CS4231P(REGSEL), chip->mce_bit | reg);
222 cs4231_outb(chip, CS4231P(REG), value);
223 chip->image[reg] = value;
224 mb();
225#if 0
226 printk("codec out - reg 0x%x = 0x%x\n", chip->mce_bit | reg, value);
227#endif
228}
229
230unsigned char snd_cs4231_in(cs4231_t *chip, unsigned char reg)
231{
232 int timeout;
233
234 for (timeout = 250;
235 timeout > 0 && (cs4231_inb(chip, CS4231P(REGSEL)) & CS4231_INIT);
236 timeout--)
237 udelay(100);
238#ifdef CONFIG_SND_DEBUG
239 if (cs4231_inb(chip, CS4231P(REGSEL)) & CS4231_INIT)
240 snd_printk("in: auto calibration time out - reg = 0x%x\n", reg);
241#endif
242 cs4231_outb(chip, CS4231P(REGSEL), chip->mce_bit | reg);
243 mb();
244 return cs4231_inb(chip, CS4231P(REG));
245}
246
247void snd_cs4236_ext_out(cs4231_t *chip, unsigned char reg, unsigned char val)
248{
249 cs4231_outb(chip, CS4231P(REGSEL), chip->mce_bit | 0x17);
250 cs4231_outb(chip, CS4231P(REG), reg | (chip->image[CS4236_EXT_REG] & 0x01));
251 cs4231_outb(chip, CS4231P(REG), val);
252 chip->eimage[CS4236_REG(reg)] = val;
253#if 0
254 printk("ext out : reg = 0x%x, val = 0x%x\n", reg, val);
255#endif
256}
257
258unsigned char snd_cs4236_ext_in(cs4231_t *chip, unsigned char reg)
259{
260 cs4231_outb(chip, CS4231P(REGSEL), chip->mce_bit | 0x17);
261 cs4231_outb(chip, CS4231P(REG), reg | (chip->image[CS4236_EXT_REG] & 0x01));
262#if 1
263 return cs4231_inb(chip, CS4231P(REG));
264#else
265 {
266 unsigned char res;
267 res = cs4231_inb(chip, CS4231P(REG));
268 printk("ext in : reg = 0x%x, val = 0x%x\n", reg, res);
269 return res;
270 }
271#endif
272}
273
274#if 0
275
276static void snd_cs4231_debug(cs4231_t *chip)
277{
278 printk("CS4231 REGS: INDEX = 0x%02x ", cs4231_inb(chip, CS4231P(REGSEL)));
279 printk(" STATUS = 0x%02x\n", cs4231_inb(chip, CS4231P(STATUS)));
280 printk(" 0x00: left input = 0x%02x ", snd_cs4231_in(chip, 0x00));
281 printk(" 0x10: alt 1 (CFIG 2) = 0x%02x\n", snd_cs4231_in(chip, 0x10));
282 printk(" 0x01: right input = 0x%02x ", snd_cs4231_in(chip, 0x01));
283 printk(" 0x11: alt 2 (CFIG 3) = 0x%02x\n", snd_cs4231_in(chip, 0x11));
284 printk(" 0x02: GF1 left input = 0x%02x ", snd_cs4231_in(chip, 0x02));
285 printk(" 0x12: left line in = 0x%02x\n", snd_cs4231_in(chip, 0x12));
286 printk(" 0x03: GF1 right input = 0x%02x ", snd_cs4231_in(chip, 0x03));
287 printk(" 0x13: right line in = 0x%02x\n", snd_cs4231_in(chip, 0x13));
288 printk(" 0x04: CD left input = 0x%02x ", snd_cs4231_in(chip, 0x04));
289 printk(" 0x14: timer low = 0x%02x\n", snd_cs4231_in(chip, 0x14));
290 printk(" 0x05: CD right input = 0x%02x ", snd_cs4231_in(chip, 0x05));
291 printk(" 0x15: timer high = 0x%02x\n", snd_cs4231_in(chip, 0x15));
292 printk(" 0x06: left output = 0x%02x ", snd_cs4231_in(chip, 0x06));
293 printk(" 0x16: left MIC (PnP) = 0x%02x\n", snd_cs4231_in(chip, 0x16));
294 printk(" 0x07: right output = 0x%02x ", snd_cs4231_in(chip, 0x07));
295 printk(" 0x17: right MIC (PnP) = 0x%02x\n", snd_cs4231_in(chip, 0x17));
296 printk(" 0x08: playback format = 0x%02x ", snd_cs4231_in(chip, 0x08));
297 printk(" 0x18: IRQ status = 0x%02x\n", snd_cs4231_in(chip, 0x18));
298 printk(" 0x09: iface (CFIG 1) = 0x%02x ", snd_cs4231_in(chip, 0x09));
299 printk(" 0x19: left line out = 0x%02x\n", snd_cs4231_in(chip, 0x19));
300 printk(" 0x0a: pin control = 0x%02x ", snd_cs4231_in(chip, 0x0a));
301 printk(" 0x1a: mono control = 0x%02x\n", snd_cs4231_in(chip, 0x1a));
302 printk(" 0x0b: init & status = 0x%02x ", snd_cs4231_in(chip, 0x0b));
303 printk(" 0x1b: right line out = 0x%02x\n", snd_cs4231_in(chip, 0x1b));
304 printk(" 0x0c: revision & mode = 0x%02x ", snd_cs4231_in(chip, 0x0c));
305 printk(" 0x1c: record format = 0x%02x\n", snd_cs4231_in(chip, 0x1c));
306 printk(" 0x0d: loopback = 0x%02x ", snd_cs4231_in(chip, 0x0d));
307 printk(" 0x1d: var freq (PnP) = 0x%02x\n", snd_cs4231_in(chip, 0x1d));
308 printk(" 0x0e: ply upr count = 0x%02x ", snd_cs4231_in(chip, 0x0e));
309 printk(" 0x1e: ply lwr count = 0x%02x\n", snd_cs4231_in(chip, 0x1e));
310 printk(" 0x0f: rec upr count = 0x%02x ", snd_cs4231_in(chip, 0x0f));
311 printk(" 0x1f: rec lwr count = 0x%02x\n", snd_cs4231_in(chip, 0x1f));
312}
313
314#endif
315
316/*
317 * CS4231 detection / MCE routines
318 */
319
320static void snd_cs4231_busy_wait(cs4231_t *chip)
321{
322 int timeout;
323
324 /* huh.. looks like this sequence is proper for CS4231A chip (GUS MAX) */
325 for (timeout = 5; timeout > 0; timeout--)
326 cs4231_inb(chip, CS4231P(REGSEL));
327 /* end of cleanup sequence */
328 for (timeout = 250;
329 timeout > 0 && (cs4231_inb(chip, CS4231P(REGSEL)) & CS4231_INIT);
330 timeout--)
331 udelay(10);
332}
333
334void snd_cs4231_mce_up(cs4231_t *chip)
335{
336 unsigned long flags;
337 int timeout;
338
339 for (timeout = 250; timeout > 0 && (cs4231_inb(chip, CS4231P(REGSEL)) & CS4231_INIT); timeout--)
340 udelay(100);
341#ifdef CONFIG_SND_DEBUG
342 if (cs4231_inb(chip, CS4231P(REGSEL)) & CS4231_INIT)
343 snd_printk("mce_up - auto calibration time out (0)\n");
344#endif
345 spin_lock_irqsave(&chip->reg_lock, flags);
346 chip->mce_bit |= CS4231_MCE;
347 timeout = cs4231_inb(chip, CS4231P(REGSEL));
348 if (timeout == 0x80)
349 snd_printk("mce_up [0x%lx]: serious init problem - codec still busy\n", chip->port);
350 if (!(timeout & CS4231_MCE))
351 cs4231_outb(chip, CS4231P(REGSEL), chip->mce_bit | (timeout & 0x1f));
352 spin_unlock_irqrestore(&chip->reg_lock, flags);
353}
354
355void snd_cs4231_mce_down(cs4231_t *chip)
356{
357 unsigned long flags;
358 int timeout;
359
360 snd_cs4231_busy_wait(chip);
361#if 0
362 printk("(1) timeout = %i\n", timeout);
363#endif
364#ifdef CONFIG_SND_DEBUG
365 if (cs4231_inb(chip, CS4231P(REGSEL)) & CS4231_INIT)
366 snd_printk("mce_down [0x%lx] - auto calibration time out (0)\n", (long)CS4231P(REGSEL));
367#endif
368 spin_lock_irqsave(&chip->reg_lock, flags);
369 chip->mce_bit &= ~CS4231_MCE;
370 timeout = cs4231_inb(chip, CS4231P(REGSEL));
371 cs4231_outb(chip, CS4231P(REGSEL), chip->mce_bit | (timeout & 0x1f));
372 spin_unlock_irqrestore(&chip->reg_lock, flags);
373 if (timeout == 0x80)
374 snd_printk("mce_down [0x%lx]: serious init problem - codec still busy\n", chip->port);
375 if ((timeout & CS4231_MCE) == 0 ||
376 !(chip->hardware & (CS4231_HW_CS4231_MASK | CS4231_HW_CS4232_MASK))) {
377 return;
378 }
379 snd_cs4231_busy_wait(chip);
380
381 /* calibration process */
382
383 for (timeout = 500; timeout > 0 && (snd_cs4231_in(chip, CS4231_TEST_INIT) & CS4231_CALIB_IN_PROGRESS) == 0; timeout--)
384 udelay(10);
385 if ((snd_cs4231_in(chip, CS4231_TEST_INIT) & CS4231_CALIB_IN_PROGRESS) == 0) {
386 snd_printd("cs4231_mce_down - auto calibration time out (1)\n");
387 return;
388 }
389#if 0
390 printk("(2) timeout = %i, jiffies = %li\n", timeout, jiffies);
391#endif
392 /* in 10 ms increments, check condition, up to 250 ms */
393 timeout = 25;
394 while (snd_cs4231_in(chip, CS4231_TEST_INIT) & CS4231_CALIB_IN_PROGRESS) {
395 if (--timeout < 0) {
396 snd_printk("mce_down - auto calibration time out (2)\n");
397 return;
398 }
399 msleep(10);
400 }
401#if 0
402 printk("(3) jiffies = %li\n", jiffies);
403#endif
404 /* in 10 ms increments, check condition, up to 100 ms */
405 timeout = 10;
406 while (cs4231_inb(chip, CS4231P(REGSEL)) & CS4231_INIT) {
407 if (--timeout < 0) {
408 snd_printk(KERN_ERR "mce_down - auto calibration time out (3)\n");
409 return;
410 }
411 msleep(10);
412 }
413#if 0
414 printk("(4) jiffies = %li\n", jiffies);
415 snd_printk("mce_down - exit = 0x%x\n", cs4231_inb(chip, CS4231P(REGSEL)));
416#endif
417}
418
419static unsigned int snd_cs4231_get_count(unsigned char format, unsigned int size)
420{
421 switch (format & 0xe0) {
422 case CS4231_LINEAR_16:
423 case CS4231_LINEAR_16_BIG:
424 size >>= 1;
425 break;
426 case CS4231_ADPCM_16:
427 return size >> 2;
428 }
429 if (format & CS4231_STEREO)
430 size >>= 1;
431 return size;
432}
433
434static int snd_cs4231_trigger(snd_pcm_substream_t *substream,
435 int cmd)
436{
437 cs4231_t *chip = snd_pcm_substream_chip(substream);
438 int result = 0;
439 unsigned int what;
440 struct list_head *pos;
441 snd_pcm_substream_t *s;
442 int do_start;
443
444#if 0
445 printk("codec trigger!!! - what = %i, enable = %i, status = 0x%x\n", what, enable, cs4231_inb(chip, CS4231P(STATUS)));
446#endif
447
448 switch (cmd) {
449 case SNDRV_PCM_TRIGGER_START:
450 case SNDRV_PCM_TRIGGER_RESUME:
451 do_start = 1; break;
452 case SNDRV_PCM_TRIGGER_STOP:
453 case SNDRV_PCM_TRIGGER_SUSPEND:
454 do_start = 0; break;
455 default:
456 return -EINVAL;
457 }
458
459 what = 0;
460 snd_pcm_group_for_each(pos, substream) {
461 s = snd_pcm_group_substream_entry(pos);
462 if (s == chip->playback_substream) {
463 what |= CS4231_PLAYBACK_ENABLE;
464 snd_pcm_trigger_done(s, substream);
465 } else if (s == chip->capture_substream) {
466 what |= CS4231_RECORD_ENABLE;
467 snd_pcm_trigger_done(s, substream);
468 }
469 }
470 spin_lock(&chip->reg_lock);
471 if (do_start) {
472 chip->image[CS4231_IFACE_CTRL] |= what;
473 if (chip->trigger)
474 chip->trigger(chip, what, 1);
475 } else {
476 chip->image[CS4231_IFACE_CTRL] &= ~what;
477 if (chip->trigger)
478 chip->trigger(chip, what, 0);
479 }
480 snd_cs4231_out(chip, CS4231_IFACE_CTRL, chip->image[CS4231_IFACE_CTRL]);
481 spin_unlock(&chip->reg_lock);
482#if 0
483 snd_cs4231_debug(chip);
484#endif
485 return result;
486}
487
488/*
489 * CODEC I/O
490 */
491
492static unsigned char snd_cs4231_get_rate(unsigned int rate)
493{
494 int i;
495
496 for (i = 0; i < 14; i++)
497 if (rate == rates[i])
498 return freq_bits[i];
499 // snd_BUG();
500 return freq_bits[13];
501}
502
503static unsigned char snd_cs4231_get_format(cs4231_t *chip,
504 int format,
505 int channels)
506{
507 unsigned char rformat;
508
509 rformat = CS4231_LINEAR_8;
510 switch (format) {
511 case SNDRV_PCM_FORMAT_MU_LAW: rformat = CS4231_ULAW_8; break;
512 case SNDRV_PCM_FORMAT_A_LAW: rformat = CS4231_ALAW_8; break;
513 case SNDRV_PCM_FORMAT_S16_LE: rformat = CS4231_LINEAR_16; break;
514 case SNDRV_PCM_FORMAT_S16_BE: rformat = CS4231_LINEAR_16_BIG; break;
515 case SNDRV_PCM_FORMAT_IMA_ADPCM: rformat = CS4231_ADPCM_16; break;
516 }
517 if (channels > 1)
518 rformat |= CS4231_STEREO;
519#if 0
520 snd_printk("get_format: 0x%x (mode=0x%x)\n", format, mode);
521#endif
522 return rformat;
523}
524
525static void snd_cs4231_calibrate_mute(cs4231_t *chip, int mute)
526{
527 unsigned long flags;
528
529 mute = mute ? 1 : 0;
530 spin_lock_irqsave(&chip->reg_lock, flags);
531 if (chip->calibrate_mute == mute) {
532 spin_unlock_irqrestore(&chip->reg_lock, flags);
533 return;
534 }
535 if (!mute) {
536 snd_cs4231_dout(chip, CS4231_LEFT_INPUT, chip->image[CS4231_LEFT_INPUT]);
537 snd_cs4231_dout(chip, CS4231_RIGHT_INPUT, chip->image[CS4231_RIGHT_INPUT]);
538 snd_cs4231_dout(chip, CS4231_LOOPBACK, chip->image[CS4231_LOOPBACK]);
539 }
540 snd_cs4231_dout(chip, CS4231_AUX1_LEFT_INPUT, mute ? 0x80 : chip->image[CS4231_AUX1_LEFT_INPUT]);
541 snd_cs4231_dout(chip, CS4231_AUX1_RIGHT_INPUT, mute ? 0x80 : chip->image[CS4231_AUX1_RIGHT_INPUT]);
542 snd_cs4231_dout(chip, CS4231_AUX2_LEFT_INPUT, mute ? 0x80 : chip->image[CS4231_AUX2_LEFT_INPUT]);
543 snd_cs4231_dout(chip, CS4231_AUX2_RIGHT_INPUT, mute ? 0x80 : chip->image[CS4231_AUX2_RIGHT_INPUT]);
544 snd_cs4231_dout(chip, CS4231_LEFT_OUTPUT, mute ? 0x80 : chip->image[CS4231_LEFT_OUTPUT]);
545 snd_cs4231_dout(chip, CS4231_RIGHT_OUTPUT, mute ? 0x80 : chip->image[CS4231_RIGHT_OUTPUT]);
546 snd_cs4231_dout(chip, CS4231_LEFT_LINE_IN, mute ? 0x80 : chip->image[CS4231_LEFT_LINE_IN]);
547 snd_cs4231_dout(chip, CS4231_RIGHT_LINE_IN, mute ? 0x80 : chip->image[CS4231_RIGHT_LINE_IN]);
548 snd_cs4231_dout(chip, CS4231_MONO_CTRL, mute ? 0xc0 : chip->image[CS4231_MONO_CTRL]);
549 if (chip->hardware == CS4231_HW_INTERWAVE) {
550 snd_cs4231_dout(chip, CS4231_LEFT_MIC_INPUT, mute ? 0x80 : chip->image[CS4231_LEFT_MIC_INPUT]);
551 snd_cs4231_dout(chip, CS4231_RIGHT_MIC_INPUT, mute ? 0x80 : chip->image[CS4231_RIGHT_MIC_INPUT]);
552 snd_cs4231_dout(chip, CS4231_LINE_LEFT_OUTPUT, mute ? 0x80 : chip->image[CS4231_LINE_LEFT_OUTPUT]);
553 snd_cs4231_dout(chip, CS4231_LINE_RIGHT_OUTPUT, mute ? 0x80 : chip->image[CS4231_LINE_RIGHT_OUTPUT]);
554 }
555 chip->calibrate_mute = mute;
556 spin_unlock_irqrestore(&chip->reg_lock, flags);
557}
558
559static void snd_cs4231_playback_format(cs4231_t *chip,
560 snd_pcm_hw_params_t *params,
561 unsigned char pdfr)
562{
563 unsigned long flags;
564 int full_calib = 1;
565
566 down(&chip->mce_mutex);
567 snd_cs4231_calibrate_mute(chip, 1);
568 if (chip->hardware == CS4231_HW_CS4231A ||
569 (chip->hardware & CS4231_HW_CS4232_MASK)) {
570 spin_lock_irqsave(&chip->reg_lock, flags);
571 if ((chip->image[CS4231_PLAYBK_FORMAT] & 0x0f) == (pdfr & 0x0f)) { /* rate is same? */
572 snd_cs4231_out(chip, CS4231_ALT_FEATURE_1, chip->image[CS4231_ALT_FEATURE_1] | 0x10);
573 snd_cs4231_out(chip, CS4231_PLAYBK_FORMAT, chip->image[CS4231_PLAYBK_FORMAT] = pdfr);
574 snd_cs4231_out(chip, CS4231_ALT_FEATURE_1, chip->image[CS4231_ALT_FEATURE_1] &= ~0x10);
575 udelay(100); /* Fixes audible clicks at least on GUS MAX */
576 full_calib = 0;
577 }
578 spin_unlock_irqrestore(&chip->reg_lock, flags);
579 }
580 if (full_calib) {
581 snd_cs4231_mce_up(chip);
582 spin_lock_irqsave(&chip->reg_lock, flags);
583 if (chip->hardware != CS4231_HW_INTERWAVE && !chip->single_dma) {
584 snd_cs4231_out(chip, CS4231_PLAYBK_FORMAT,
585 (chip->image[CS4231_IFACE_CTRL] & CS4231_RECORD_ENABLE) ?
586 (pdfr & 0xf0) | (chip->image[CS4231_REC_FORMAT] & 0x0f) :
587 pdfr);
588 } else {
589 snd_cs4231_out(chip, CS4231_PLAYBK_FORMAT, chip->image[CS4231_PLAYBK_FORMAT] = pdfr);
590 }
591 spin_unlock_irqrestore(&chip->reg_lock, flags);
592 snd_cs4231_mce_down(chip);
593 }
594 snd_cs4231_calibrate_mute(chip, 0);
595 up(&chip->mce_mutex);
596}
597
598static void snd_cs4231_capture_format(cs4231_t *chip,
599 snd_pcm_hw_params_t *params,
600 unsigned char cdfr)
601{
602 unsigned long flags;
603 int full_calib = 1;
604
605 down(&chip->mce_mutex);
606 snd_cs4231_calibrate_mute(chip, 1);
607 if (chip->hardware == CS4231_HW_CS4231A ||
608 (chip->hardware & CS4231_HW_CS4232_MASK)) {
609 spin_lock_irqsave(&chip->reg_lock, flags);
610 if ((chip->image[CS4231_PLAYBK_FORMAT] & 0x0f) == (cdfr & 0x0f) || /* rate is same? */
611 (chip->image[CS4231_IFACE_CTRL] & CS4231_PLAYBACK_ENABLE)) {
612 snd_cs4231_out(chip, CS4231_ALT_FEATURE_1, chip->image[CS4231_ALT_FEATURE_1] | 0x20);
613 snd_cs4231_out(chip, CS4231_REC_FORMAT, chip->image[CS4231_REC_FORMAT] = cdfr);
614 snd_cs4231_out(chip, CS4231_ALT_FEATURE_1, chip->image[CS4231_ALT_FEATURE_1] &= ~0x20);
615 full_calib = 0;
616 }
617 spin_unlock_irqrestore(&chip->reg_lock, flags);
618 }
619 if (full_calib) {
620 snd_cs4231_mce_up(chip);
621 spin_lock_irqsave(&chip->reg_lock, flags);
622 if (chip->hardware != CS4231_HW_INTERWAVE) {
623 if (!(chip->image[CS4231_IFACE_CTRL] & CS4231_PLAYBACK_ENABLE)) {
624 snd_cs4231_out(chip, CS4231_PLAYBK_FORMAT,
625 ((chip->single_dma ? cdfr : chip->image[CS4231_PLAYBK_FORMAT]) & 0xf0) |
626 (cdfr & 0x0f));
627 spin_unlock_irqrestore(&chip->reg_lock, flags);
628 snd_cs4231_mce_down(chip);
629 snd_cs4231_mce_up(chip);
630 spin_lock_irqsave(&chip->reg_lock, flags);
631 }
632 }
633 snd_cs4231_out(chip, CS4231_REC_FORMAT, cdfr);
634 spin_unlock_irqrestore(&chip->reg_lock, flags);
635 snd_cs4231_mce_down(chip);
636 }
637 snd_cs4231_calibrate_mute(chip, 0);
638 up(&chip->mce_mutex);
639}
640
641/*
642 * Timer interface
643 */
644
645static unsigned long snd_cs4231_timer_resolution(snd_timer_t * timer)
646{
647 cs4231_t *chip = snd_timer_chip(timer);
648 if (chip->hardware & CS4231_HW_CS4236B_MASK)
649 return 14467;
650 else
651 return chip->image[CS4231_PLAYBK_FORMAT] & 1 ? 9969 : 9920;
652}
653
654static int snd_cs4231_timer_start(snd_timer_t * timer)
655{
656 unsigned long flags;
657 unsigned int ticks;
658 cs4231_t *chip = snd_timer_chip(timer);
659 spin_lock_irqsave(&chip->reg_lock, flags);
660 ticks = timer->sticks;
661 if ((chip->image[CS4231_ALT_FEATURE_1] & CS4231_TIMER_ENABLE) == 0 ||
662 (unsigned char)(ticks >> 8) != chip->image[CS4231_TIMER_HIGH] ||
663 (unsigned char)ticks != chip->image[CS4231_TIMER_LOW]) {
664 snd_cs4231_out(chip, CS4231_TIMER_HIGH, chip->image[CS4231_TIMER_HIGH] = (unsigned char) (ticks >> 8));
665 snd_cs4231_out(chip, CS4231_TIMER_LOW, chip->image[CS4231_TIMER_LOW] = (unsigned char) ticks);
666 snd_cs4231_out(chip, CS4231_ALT_FEATURE_1, chip->image[CS4231_ALT_FEATURE_1] | CS4231_TIMER_ENABLE);
667 }
668 spin_unlock_irqrestore(&chip->reg_lock, flags);
669 return 0;
670}
671
672static int snd_cs4231_timer_stop(snd_timer_t * timer)
673{
674 unsigned long flags;
675 cs4231_t *chip = snd_timer_chip(timer);
676 spin_lock_irqsave(&chip->reg_lock, flags);
677 snd_cs4231_out(chip, CS4231_ALT_FEATURE_1, chip->image[CS4231_ALT_FEATURE_1] &= ~CS4231_TIMER_ENABLE);
678 spin_unlock_irqrestore(&chip->reg_lock, flags);
679 return 0;
680}
681
682static void snd_cs4231_init(cs4231_t *chip)
683{
684 unsigned long flags;
685
686 snd_cs4231_mce_down(chip);
687
688#ifdef SNDRV_DEBUG_MCE
689 snd_printk("init: (1)\n");
690#endif
691 snd_cs4231_mce_up(chip);
692 spin_lock_irqsave(&chip->reg_lock, flags);
693 chip->image[CS4231_IFACE_CTRL] &= ~(CS4231_PLAYBACK_ENABLE | CS4231_PLAYBACK_PIO |
694 CS4231_RECORD_ENABLE | CS4231_RECORD_PIO |
695 CS4231_CALIB_MODE);
696 chip->image[CS4231_IFACE_CTRL] |= CS4231_AUTOCALIB;
697 snd_cs4231_out(chip, CS4231_IFACE_CTRL, chip->image[CS4231_IFACE_CTRL]);
698 spin_unlock_irqrestore(&chip->reg_lock, flags);
699 snd_cs4231_mce_down(chip);
700
701#ifdef SNDRV_DEBUG_MCE
702 snd_printk("init: (2)\n");
703#endif
704
705 snd_cs4231_mce_up(chip);
706 spin_lock_irqsave(&chip->reg_lock, flags);
707 snd_cs4231_out(chip, CS4231_ALT_FEATURE_1, chip->image[CS4231_ALT_FEATURE_1]);
708 spin_unlock_irqrestore(&chip->reg_lock, flags);
709 snd_cs4231_mce_down(chip);
710
711#ifdef SNDRV_DEBUG_MCE
712 snd_printk("init: (3) - afei = 0x%x\n", chip->image[CS4231_ALT_FEATURE_1]);
713#endif
714
715 spin_lock_irqsave(&chip->reg_lock, flags);
716 snd_cs4231_out(chip, CS4231_ALT_FEATURE_2, chip->image[CS4231_ALT_FEATURE_2]);
717 spin_unlock_irqrestore(&chip->reg_lock, flags);
718
719 snd_cs4231_mce_up(chip);
720 spin_lock_irqsave(&chip->reg_lock, flags);
721 snd_cs4231_out(chip, CS4231_PLAYBK_FORMAT, chip->image[CS4231_PLAYBK_FORMAT]);
722 spin_unlock_irqrestore(&chip->reg_lock, flags);
723 snd_cs4231_mce_down(chip);
724
725#ifdef SNDRV_DEBUG_MCE
726 snd_printk("init: (4)\n");
727#endif
728
729 snd_cs4231_mce_up(chip);
730 spin_lock_irqsave(&chip->reg_lock, flags);
731 snd_cs4231_out(chip, CS4231_REC_FORMAT, chip->image[CS4231_REC_FORMAT]);
732 spin_unlock_irqrestore(&chip->reg_lock, flags);
733 snd_cs4231_mce_down(chip);
734
735#ifdef SNDRV_DEBUG_MCE
736 snd_printk("init: (5)\n");
737#endif
738}
739
740static int snd_cs4231_open(cs4231_t *chip, unsigned int mode)
741{
742 unsigned long flags;
743
744 down(&chip->open_mutex);
745 if ((chip->mode & mode) ||
746 ((chip->mode & CS4231_MODE_OPEN) && chip->single_dma)) {
747 up(&chip->open_mutex);
748 return -EAGAIN;
749 }
750 if (chip->mode & CS4231_MODE_OPEN) {
751 chip->mode |= mode;
752 up(&chip->open_mutex);
753 return 0;
754 }
755 /* ok. now enable and ack CODEC IRQ */
756 spin_lock_irqsave(&chip->reg_lock, flags);
757 snd_cs4231_out(chip, CS4231_IRQ_STATUS, CS4231_PLAYBACK_IRQ |
758 CS4231_RECORD_IRQ |
759 CS4231_TIMER_IRQ);
760 snd_cs4231_out(chip, CS4231_IRQ_STATUS, 0);
761 cs4231_outb(chip, CS4231P(STATUS), 0); /* clear IRQ */
762 cs4231_outb(chip, CS4231P(STATUS), 0); /* clear IRQ */
763 chip->image[CS4231_PIN_CTRL] |= CS4231_IRQ_ENABLE;
764 snd_cs4231_out(chip, CS4231_PIN_CTRL, chip->image[CS4231_PIN_CTRL]);
765 snd_cs4231_out(chip, CS4231_IRQ_STATUS, CS4231_PLAYBACK_IRQ |
766 CS4231_RECORD_IRQ |
767 CS4231_TIMER_IRQ);
768 snd_cs4231_out(chip, CS4231_IRQ_STATUS, 0);
769 spin_unlock_irqrestore(&chip->reg_lock, flags);
770
771 chip->mode = mode;
772 up(&chip->open_mutex);
773 return 0;
774}
775
776static void snd_cs4231_close(cs4231_t *chip, unsigned int mode)
777{
778 unsigned long flags;
779
780 down(&chip->open_mutex);
781 chip->mode &= ~mode;
782 if (chip->mode & CS4231_MODE_OPEN) {
783 up(&chip->open_mutex);
784 return;
785 }
786 snd_cs4231_calibrate_mute(chip, 1);
787
788 /* disable IRQ */
789 spin_lock_irqsave(&chip->reg_lock, flags);
790 snd_cs4231_out(chip, CS4231_IRQ_STATUS, 0);
791 cs4231_outb(chip, CS4231P(STATUS), 0); /* clear IRQ */
792 cs4231_outb(chip, CS4231P(STATUS), 0); /* clear IRQ */
793 chip->image[CS4231_PIN_CTRL] &= ~CS4231_IRQ_ENABLE;
794 snd_cs4231_out(chip, CS4231_PIN_CTRL, chip->image[CS4231_PIN_CTRL]);
795
796 /* now disable record & playback */
797
798 if (chip->image[CS4231_IFACE_CTRL] & (CS4231_PLAYBACK_ENABLE | CS4231_PLAYBACK_PIO |
799 CS4231_RECORD_ENABLE | CS4231_RECORD_PIO)) {
800 spin_unlock_irqrestore(&chip->reg_lock, flags);
801 snd_cs4231_mce_up(chip);
802 spin_lock_irqsave(&chip->reg_lock, flags);
803 chip->image[CS4231_IFACE_CTRL] &= ~(CS4231_PLAYBACK_ENABLE | CS4231_PLAYBACK_PIO |
804 CS4231_RECORD_ENABLE | CS4231_RECORD_PIO);
805 snd_cs4231_out(chip, CS4231_IFACE_CTRL, chip->image[CS4231_IFACE_CTRL]);
806 spin_unlock_irqrestore(&chip->reg_lock, flags);
807 snd_cs4231_mce_down(chip);
808 spin_lock_irqsave(&chip->reg_lock, flags);
809 }
810
811 /* clear IRQ again */
812 snd_cs4231_out(chip, CS4231_IRQ_STATUS, 0);
813 cs4231_outb(chip, CS4231P(STATUS), 0); /* clear IRQ */
814 cs4231_outb(chip, CS4231P(STATUS), 0); /* clear IRQ */
815 spin_unlock_irqrestore(&chip->reg_lock, flags);
816
817 snd_cs4231_calibrate_mute(chip, 0);
818
819 chip->mode = 0;
820 up(&chip->open_mutex);
821}
822
823/*
824 * timer open/close
825 */
826
827static int snd_cs4231_timer_open(snd_timer_t * timer)
828{
829 cs4231_t *chip = snd_timer_chip(timer);
830 snd_cs4231_open(chip, CS4231_MODE_TIMER);
831 return 0;
832}
833
834static int snd_cs4231_timer_close(snd_timer_t * timer)
835{
836 cs4231_t *chip = snd_timer_chip(timer);
837 snd_cs4231_close(chip, CS4231_MODE_TIMER);
838 return 0;
839}
840
841static struct _snd_timer_hardware snd_cs4231_timer_table =
842{
843 .flags = SNDRV_TIMER_HW_AUTO,
844 .resolution = 9945,
845 .ticks = 65535,
846 .open = snd_cs4231_timer_open,
847 .close = snd_cs4231_timer_close,
848 .c_resolution = snd_cs4231_timer_resolution,
849 .start = snd_cs4231_timer_start,
850 .stop = snd_cs4231_timer_stop,
851};
852
853/*
854 * ok.. exported functions..
855 */
856
857static int snd_cs4231_playback_hw_params(snd_pcm_substream_t * substream,
858 snd_pcm_hw_params_t * hw_params)
859{
860 cs4231_t *chip = snd_pcm_substream_chip(substream);
861 unsigned char new_pdfr;
862 int err;
863
864 if ((err = snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(hw_params))) < 0)
865 return err;
866 new_pdfr = snd_cs4231_get_format(chip, params_format(hw_params), params_channels(hw_params)) |
867 snd_cs4231_get_rate(params_rate(hw_params));
868 chip->set_playback_format(chip, hw_params, new_pdfr);
869 return 0;
870}
871
872static int snd_cs4231_playback_hw_free(snd_pcm_substream_t * substream)
873{
874 return snd_pcm_lib_free_pages(substream);
875}
876
877#ifdef LEGACY_SUPPORT
878static int snd_cs4231_playback_prepare(snd_pcm_substream_t * substream)
879{
880 cs4231_t *chip = snd_pcm_substream_chip(substream);
881 snd_pcm_runtime_t *runtime = substream->runtime;
882 unsigned long flags;
883 unsigned int size = snd_pcm_lib_buffer_bytes(substream);
884 unsigned int count = snd_pcm_lib_period_bytes(substream);
885
886 spin_lock_irqsave(&chip->reg_lock, flags);
887 chip->p_dma_size = size;
888 chip->image[CS4231_IFACE_CTRL] &= ~(CS4231_PLAYBACK_ENABLE | CS4231_PLAYBACK_PIO);
889 snd_dma_program(chip->dma1, runtime->dma_addr, size, DMA_MODE_WRITE | DMA_AUTOINIT);
890 count = snd_cs4231_get_count(chip->image[CS4231_PLAYBK_FORMAT], count) - 1;
891 snd_cs4231_out(chip, CS4231_PLY_LWR_CNT, (unsigned char) count);
892 snd_cs4231_out(chip, CS4231_PLY_UPR_CNT, (unsigned char) (count >> 8));
893 spin_unlock_irqrestore(&chip->reg_lock, flags);
894#if 0
895 snd_cs4231_debug(chip);
896#endif
897 return 0;
898}
899#endif /* LEGACY_SUPPORT */
900
901static int snd_cs4231_capture_hw_params(snd_pcm_substream_t * substream,
902 snd_pcm_hw_params_t * hw_params)
903{
904 cs4231_t *chip = snd_pcm_substream_chip(substream);
905 unsigned char new_cdfr;
906 int err;
907
908 if ((err = snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(hw_params))) < 0)
909 return err;
910 new_cdfr = snd_cs4231_get_format(chip, params_format(hw_params), params_channels(hw_params)) |
911 snd_cs4231_get_rate(params_rate(hw_params));
912 chip->set_capture_format(chip, hw_params, new_cdfr);
913 return 0;
914}
915
916static int snd_cs4231_capture_hw_free(snd_pcm_substream_t * substream)
917{
918 return snd_pcm_lib_free_pages(substream);
919}
920
921#ifdef LEGACY_SUPPORT
922static int snd_cs4231_capture_prepare(snd_pcm_substream_t * substream)
923{
924 cs4231_t *chip = snd_pcm_substream_chip(substream);
925 snd_pcm_runtime_t *runtime = substream->runtime;
926 unsigned long flags;
927 unsigned int size = snd_pcm_lib_buffer_bytes(substream);
928 unsigned int count = snd_pcm_lib_period_bytes(substream);
929
930 spin_lock_irqsave(&chip->reg_lock, flags);
931 chip->c_dma_size = size;
932 chip->image[CS4231_IFACE_CTRL] &= ~(CS4231_RECORD_ENABLE | CS4231_RECORD_PIO);
933 snd_dma_program(chip->dma2, runtime->dma_addr, size, DMA_MODE_READ | DMA_AUTOINIT);
934 count = snd_cs4231_get_count(chip->image[CS4231_REC_FORMAT], count) - 1;
935 if (chip->single_dma && chip->hardware != CS4231_HW_INTERWAVE) {
936 snd_cs4231_out(chip, CS4231_PLY_LWR_CNT, (unsigned char) count);
937 snd_cs4231_out(chip, CS4231_PLY_UPR_CNT, (unsigned char) (count >> 8));
938 } else {
939 snd_cs4231_out(chip, CS4231_REC_LWR_CNT, (unsigned char) count);
940 snd_cs4231_out(chip, CS4231_REC_UPR_CNT, (unsigned char) (count >> 8));
941 }
942 spin_unlock_irqrestore(&chip->reg_lock, flags);
943 return 0;
944}
945#endif
946
947static void snd_cs4231_overrange(cs4231_t *chip)
948{
949 unsigned long flags;
950 unsigned char res;
951
952 spin_lock_irqsave(&chip->reg_lock, flags);
953 res = snd_cs4231_in(chip, CS4231_TEST_INIT);
954 spin_unlock_irqrestore(&chip->reg_lock, flags);
955 if (res & (0x08 | 0x02)) /* detect overrange only above 0dB; may be user selectable? */
956 chip->capture_substream->runtime->overrange++;
957}
958
959irqreturn_t snd_cs4231_interrupt(int irq, void *dev_id, struct pt_regs *regs)
960{
961 cs4231_t *chip = dev_id;
962 unsigned char status;
963
964 status = snd_cs4231_in(chip, CS4231_IRQ_STATUS);
965 if (status & CS4231_TIMER_IRQ) {
966 if (chip->timer)
967 snd_timer_interrupt(chip->timer, chip->timer->sticks);
968 }
969 if (chip->single_dma && chip->hardware != CS4231_HW_INTERWAVE) {
970 if (status & CS4231_PLAYBACK_IRQ) {
971 if (chip->mode & CS4231_MODE_PLAY) {
972 if (chip->playback_substream)
973 snd_pcm_period_elapsed(chip->playback_substream);
974 }
975 if (chip->mode & CS4231_MODE_RECORD) {
976 if (chip->capture_substream) {
977 snd_cs4231_overrange(chip);
978 snd_pcm_period_elapsed(chip->capture_substream);
979 }
980 }
981 }
982 } else {
983 if (status & CS4231_PLAYBACK_IRQ) {
984 if (chip->playback_substream)
985 snd_pcm_period_elapsed(chip->playback_substream);
986 }
987 if (status & CS4231_RECORD_IRQ) {
988 if (chip->capture_substream) {
989 snd_cs4231_overrange(chip);
990 snd_pcm_period_elapsed(chip->capture_substream);
991 }
992 }
993 }
994
995 spin_lock(&chip->reg_lock);
996 snd_cs4231_outm(chip, CS4231_IRQ_STATUS, ~CS4231_ALL_IRQS | ~status, 0);
997 spin_unlock(&chip->reg_lock);
998 return IRQ_HANDLED;
999}
1000
1001#ifdef LEGACY_SUPPORT
1002static snd_pcm_uframes_t snd_cs4231_playback_pointer(snd_pcm_substream_t * substream)
1003{
1004 cs4231_t *chip = snd_pcm_substream_chip(substream);
1005 size_t ptr;
1006
1007 if (!(chip->image[CS4231_IFACE_CTRL] & CS4231_PLAYBACK_ENABLE))
1008 return 0;
1009 ptr = snd_dma_pointer(chip->dma1, chip->p_dma_size);
1010 return bytes_to_frames(substream->runtime, ptr);
1011}
1012
1013static snd_pcm_uframes_t snd_cs4231_capture_pointer(snd_pcm_substream_t * substream)
1014{
1015 cs4231_t *chip = snd_pcm_substream_chip(substream);
1016 size_t ptr;
1017
1018 if (!(chip->image[CS4231_IFACE_CTRL] & CS4231_RECORD_ENABLE))
1019 return 0;
1020 ptr = snd_dma_pointer(chip->dma2, chip->c_dma_size);
1021 return bytes_to_frames(substream->runtime, ptr);
1022}
1023#endif /* LEGACY_SUPPORT */
1024
1025/*
1026
1027 */
1028
1029static int snd_cs4231_probe(cs4231_t *chip)
1030{
1031 unsigned long flags;
1032 int i, id, rev;
1033 unsigned char *ptr;
1034 unsigned int hw;
1035
1036#if 0
1037 snd_cs4231_debug(chip);
1038#endif
1039 id = 0;
1040 for (i = 0; i < 50; i++) {
1041 mb();
1042 if (cs4231_inb(chip, CS4231P(REGSEL)) & CS4231_INIT)
1043 udelay(2000);
1044 else {
1045 spin_lock_irqsave(&chip->reg_lock, flags);
1046 snd_cs4231_out(chip, CS4231_MISC_INFO, CS4231_MODE2);
1047 id = snd_cs4231_in(chip, CS4231_MISC_INFO) & 0x0f;
1048 spin_unlock_irqrestore(&chip->reg_lock, flags);
1049 if (id == 0x0a)
1050 break; /* this is valid value */
1051 }
1052 }
1053 snd_printdd("cs4231: port = 0x%lx, id = 0x%x\n", chip->port, id);
1054 if (id != 0x0a)
1055 return -ENODEV; /* no valid device found */
1056
1057 if (((hw = chip->hardware) & CS4231_HW_TYPE_MASK) == CS4231_HW_DETECT) {
1058 rev = snd_cs4231_in(chip, CS4231_VERSION) & 0xe7;
1059 snd_printdd("CS4231: VERSION (I25) = 0x%x\n", rev);
1060 if (rev == 0x80) {
1061 unsigned char tmp = snd_cs4231_in(chip, 23);
1062 snd_cs4231_out(chip, 23, ~tmp);
1063 if (snd_cs4231_in(chip, 23) != tmp)
1064 chip->hardware = CS4231_HW_AD1845;
1065 else
1066 chip->hardware = CS4231_HW_CS4231;
1067 } else if (rev == 0xa0) {
1068 chip->hardware = CS4231_HW_CS4231A;
1069 } else if (rev == 0xa2) {
1070 chip->hardware = CS4231_HW_CS4232;
1071 } else if (rev == 0xb2) {
1072 chip->hardware = CS4231_HW_CS4232A;
1073 } else if (rev == 0x83) {
1074 chip->hardware = CS4231_HW_CS4236;
1075 } else if (rev == 0x03) {
1076 chip->hardware = CS4231_HW_CS4236B;
1077 } else {
1078 snd_printk("unknown CS chip with version 0x%x\n", rev);
1079 return -ENODEV; /* unknown CS4231 chip? */
1080 }
1081 }
1082 spin_lock_irqsave(&chip->reg_lock, flags);
1083 cs4231_inb(chip, CS4231P(STATUS)); /* clear any pendings IRQ */
1084 cs4231_outb(chip, CS4231P(STATUS), 0);
1085 mb();
1086 spin_unlock_irqrestore(&chip->reg_lock, flags);
1087
1088 chip->image[CS4231_MISC_INFO] = CS4231_MODE2;
1089 switch (chip->hardware) {
1090 case CS4231_HW_INTERWAVE:
1091 chip->image[CS4231_MISC_INFO] = CS4231_IW_MODE3;
1092 break;
1093 case CS4231_HW_CS4235:
1094 case CS4231_HW_CS4236B:
1095 case CS4231_HW_CS4237B:
1096 case CS4231_HW_CS4238B:
1097 case CS4231_HW_CS4239:
1098 if (hw == CS4231_HW_DETECT3)
1099 chip->image[CS4231_MISC_INFO] = CS4231_4236_MODE3;
1100 else
1101 chip->hardware = CS4231_HW_CS4236;
1102 break;
1103 }
1104
1105 chip->image[CS4231_IFACE_CTRL] =
1106 (chip->image[CS4231_IFACE_CTRL] & ~CS4231_SINGLE_DMA) |
1107 (chip->single_dma ? CS4231_SINGLE_DMA : 0);
1108 chip->image[CS4231_ALT_FEATURE_1] = 0x80;
1109 chip->image[CS4231_ALT_FEATURE_2] = chip->hardware == CS4231_HW_INTERWAVE ? 0xc2 : 0x01;
1110 ptr = (unsigned char *) &chip->image;
1111 snd_cs4231_mce_down(chip);
1112 spin_lock_irqsave(&chip->reg_lock, flags);
1113 for (i = 0; i < 32; i++) /* ok.. fill all CS4231 registers */
1114 snd_cs4231_out(chip, i, *ptr++);
1115 spin_unlock_irqrestore(&chip->reg_lock, flags);
1116 snd_cs4231_mce_up(chip);
1117 snd_cs4231_mce_down(chip);
1118
1119 mdelay(2);
1120
1121 /* ok.. try check hardware version for CS4236+ chips */
1122 if ((hw & CS4231_HW_TYPE_MASK) == CS4231_HW_DETECT) {
1123 if (chip->hardware == CS4231_HW_CS4236B) {
1124 rev = snd_cs4236_ext_in(chip, CS4236_VERSION);
1125 snd_cs4236_ext_out(chip, CS4236_VERSION, 0xff);
1126 id = snd_cs4236_ext_in(chip, CS4236_VERSION);
1127 snd_cs4236_ext_out(chip, CS4236_VERSION, rev);
1128 snd_printdd("CS4231: ext version; rev = 0x%x, id = 0x%x\n", rev, id);
1129 if ((id & 0x1f) == 0x1d) { /* CS4235 */
1130 chip->hardware = CS4231_HW_CS4235;
1131 switch (id >> 5) {
1132 case 4:
1133 case 5:
1134 case 6:
1135 break;
1136 default:
1137 snd_printk("unknown CS4235 chip (enhanced version = 0x%x)\n", id);
1138 }
1139 } else if ((id & 0x1f) == 0x0b) { /* CS4236/B */
1140 switch (id >> 5) {
1141 case 4:
1142 case 5:
1143 case 6:
1144 case 7:
1145 chip->hardware = CS4231_HW_CS4236B;
1146 break;
1147 default:
1148 snd_printk("unknown CS4236 chip (enhanced version = 0x%x)\n", id);
1149 }
1150 } else if ((id & 0x1f) == 0x08) { /* CS4237B */
1151 chip->hardware = CS4231_HW_CS4237B;
1152 switch (id >> 5) {
1153 case 4:
1154 case 5:
1155 case 6:
1156 case 7:
1157 break;
1158 default:
1159 snd_printk("unknown CS4237B chip (enhanced version = 0x%x)\n", id);
1160 }
1161 } else if ((id & 0x1f) == 0x09) { /* CS4238B */
1162 chip->hardware = CS4231_HW_CS4238B;
1163 switch (id >> 5) {
1164 case 5:
1165 case 6:
1166 case 7:
1167 break;
1168 default:
1169 snd_printk("unknown CS4238B chip (enhanced version = 0x%x)\n", id);
1170 }
1171 } else if ((id & 0x1f) == 0x1e) { /* CS4239 */
1172 chip->hardware = CS4231_HW_CS4239;
1173 switch (id >> 5) {
1174 case 4:
1175 case 5:
1176 case 6:
1177 break;
1178 default:
1179 snd_printk("unknown CS4239 chip (enhanced version = 0x%x)\n", id);
1180 }
1181 } else {
1182 snd_printk("unknown CS4236/CS423xB chip (enhanced version = 0x%x)\n", id);
1183 }
1184 }
1185 }
1186 return 0; /* all things are ok.. */
1187}
1188
1189/*
1190
1191 */
1192
1193static snd_pcm_hardware_t snd_cs4231_playback =
1194{
1195 .info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED |
1196 SNDRV_PCM_INFO_MMAP_VALID |
1197 SNDRV_PCM_INFO_RESUME |
1198 SNDRV_PCM_INFO_SYNC_START),
1199 .formats = (SNDRV_PCM_FMTBIT_MU_LAW | SNDRV_PCM_FMTBIT_A_LAW | SNDRV_PCM_FMTBIT_IMA_ADPCM |
1200 SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S16_BE),
1201 .rates = SNDRV_PCM_RATE_KNOT | SNDRV_PCM_RATE_8000_48000,
1202 .rate_min = 5510,
1203 .rate_max = 48000,
1204 .channels_min = 1,
1205 .channels_max = 2,
1206 .buffer_bytes_max = (128*1024),
1207 .period_bytes_min = 64,
1208 .period_bytes_max = (128*1024),
1209 .periods_min = 1,
1210 .periods_max = 1024,
1211 .fifo_size = 0,
1212};
1213
1214static snd_pcm_hardware_t snd_cs4231_capture =
1215{
1216 .info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED |
1217 SNDRV_PCM_INFO_MMAP_VALID |
1218 SNDRV_PCM_INFO_RESUME |
1219 SNDRV_PCM_INFO_SYNC_START),
1220 .formats = (SNDRV_PCM_FMTBIT_MU_LAW | SNDRV_PCM_FMTBIT_A_LAW | SNDRV_PCM_FMTBIT_IMA_ADPCM |
1221 SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S16_BE),
1222 .rates = SNDRV_PCM_RATE_KNOT | SNDRV_PCM_RATE_8000_48000,
1223 .rate_min = 5510,
1224 .rate_max = 48000,
1225 .channels_min = 1,
1226 .channels_max = 2,
1227 .buffer_bytes_max = (128*1024),
1228 .period_bytes_min = 64,
1229 .period_bytes_max = (128*1024),
1230 .periods_min = 1,
1231 .periods_max = 1024,
1232 .fifo_size = 0,
1233};
1234
1235/*
1236
1237 */
1238
1239static int snd_cs4231_playback_open(snd_pcm_substream_t * substream)
1240{
1241 cs4231_t *chip = snd_pcm_substream_chip(substream);
1242 snd_pcm_runtime_t *runtime = substream->runtime;
1243 int err;
1244
1245 runtime->hw = snd_cs4231_playback;
1246
1247 /* hardware bug in InterWave chipset */
1248 if (chip->hardware == CS4231_HW_INTERWAVE && chip->dma1 > 3)
1249 runtime->hw.formats &= ~SNDRV_PCM_FMTBIT_MU_LAW;
1250
1251 /* hardware limitation of cheap chips */
1252 if (chip->hardware == CS4231_HW_CS4235 ||
1253 chip->hardware == CS4231_HW_CS4239)
1254 runtime->hw.formats = SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S16_LE;
1255
1256#ifdef LEGACY_SUPPORT
1257 snd_pcm_limit_isa_dma_size(chip->dma1, &runtime->hw.buffer_bytes_max);
1258 snd_pcm_limit_isa_dma_size(chip->dma1, &runtime->hw.period_bytes_max);
1259
1260 if (chip->claim_dma) {
1261 if ((err = chip->claim_dma(chip, chip->dma_private_data, chip->dma1)) < 0)
1262 return err;
1263 }
1264#endif
1265
1266 if ((err = snd_cs4231_open(chip, CS4231_MODE_PLAY)) < 0) {
1267#ifdef LEGACY_SUPPORT
1268 if (chip->release_dma)
1269 chip->release_dma(chip, chip->dma_private_data, chip->dma1);
1270#endif
1271 snd_free_pages(runtime->dma_area, runtime->dma_bytes);
1272 return err;
1273 }
1274 chip->playback_substream = substream;
1275#if defined(SBUS_SUPPORT) || defined(EBUS_SUPPORT)
1276 chip->p_periods_sent = 0;
1277#endif
1278 snd_pcm_set_sync(substream);
1279 chip->rate_constraint(runtime);
1280 return 0;
1281}
1282
1283static int snd_cs4231_capture_open(snd_pcm_substream_t * substream)
1284{
1285 cs4231_t *chip = snd_pcm_substream_chip(substream);
1286 snd_pcm_runtime_t *runtime = substream->runtime;
1287 int err;
1288
1289 runtime->hw = snd_cs4231_capture;
1290
1291 /* hardware limitation of cheap chips */
1292 if (chip->hardware == CS4231_HW_CS4235 ||
1293 chip->hardware == CS4231_HW_CS4239)
1294 runtime->hw.formats = SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S16_LE;
1295
1296#ifdef LEGACY_SUPPORT
1297 snd_pcm_limit_isa_dma_size(chip->dma2, &runtime->hw.buffer_bytes_max);
1298 snd_pcm_limit_isa_dma_size(chip->dma2, &runtime->hw.period_bytes_max);
1299
1300 if (chip->claim_dma) {
1301 if ((err = chip->claim_dma(chip, chip->dma_private_data, chip->dma2)) < 0)
1302 return err;
1303 }
1304#endif
1305
1306 if ((err = snd_cs4231_open(chip, CS4231_MODE_RECORD)) < 0) {
1307#ifdef LEGACY_SUPPORT
1308 if (chip->release_dma)
1309 chip->release_dma(chip, chip->dma_private_data, chip->dma2);
1310#endif
1311 snd_free_pages(runtime->dma_area, runtime->dma_bytes);
1312 return err;
1313 }
1314 chip->capture_substream = substream;
1315#if defined(SBUS_SUPPORT) || defined(EBUS_SUPPORT)
1316 chip->c_periods_sent = 0;
1317#endif
1318 snd_pcm_set_sync(substream);
1319 chip->rate_constraint(runtime);
1320 return 0;
1321}
1322
1323static int snd_cs4231_playback_close(snd_pcm_substream_t * substream)
1324{
1325 cs4231_t *chip = snd_pcm_substream_chip(substream);
1326
1327 chip->playback_substream = NULL;
1328 snd_cs4231_close(chip, CS4231_MODE_PLAY);
1329 return 0;
1330}
1331
1332static int snd_cs4231_capture_close(snd_pcm_substream_t * substream)
1333{
1334 cs4231_t *chip = snd_pcm_substream_chip(substream);
1335
1336 chip->capture_substream = NULL;
1337 snd_cs4231_close(chip, CS4231_MODE_RECORD);
1338 return 0;
1339}
1340
1341#ifdef CONFIG_PM
1342
1343/* lowlevel suspend callback for CS4231 */
1344static void snd_cs4231_suspend(cs4231_t *chip)
1345{
1346 int reg;
1347 unsigned long flags;
1348
1349 spin_lock_irqsave(&chip->reg_lock, flags);
1350 for (reg = 0; reg < 32; reg++)
1351 chip->image[reg] = snd_cs4231_in(chip, reg);
1352 spin_unlock_irqrestore(&chip->reg_lock, flags);
1353}
1354
1355/* lowlevel resume callback for CS4231 */
1356static void snd_cs4231_resume(cs4231_t *chip)
1357{
1358 int reg;
1359 unsigned long flags;
1360 int timeout;
1361
1362 snd_cs4231_mce_up(chip);
1363 spin_lock_irqsave(&chip->reg_lock, flags);
1364 for (reg = 0; reg < 32; reg++) {
1365 switch (reg) {
1366 case CS4231_VERSION:
1367 break;
1368 default:
1369 snd_cs4231_out(chip, reg, chip->image[reg]);
1370 break;
1371 }
1372 }
1373 spin_unlock_irqrestore(&chip->reg_lock, flags);
1374#if 0
1375 snd_cs4231_mce_down(chip);
1376#else
1377 /* The following is a workaround to avoid freeze after resume on TP600E.
1378 This is the first half of copy of snd_cs4231_mce_down(), but doesn't
1379 include rescheduling. -- iwai
1380 */
1381 snd_cs4231_busy_wait(chip);
1382 spin_lock_irqsave(&chip->reg_lock, flags);
1383 chip->mce_bit &= ~CS4231_MCE;
1384 timeout = cs4231_inb(chip, CS4231P(REGSEL));
1385 cs4231_outb(chip, CS4231P(REGSEL), chip->mce_bit | (timeout & 0x1f));
1386 spin_unlock_irqrestore(&chip->reg_lock, flags);
1387 if (timeout == 0x80)
1388 snd_printk("down [0x%lx]: serious init problem - codec still busy\n", chip->port);
1389 if ((timeout & CS4231_MCE) == 0 ||
1390 !(chip->hardware & (CS4231_HW_CS4231_MASK | CS4231_HW_CS4232_MASK))) {
1391 return;
1392 }
1393 snd_cs4231_busy_wait(chip);
1394#endif
1395}
1396
1397static int snd_cs4231_pm_suspend(snd_card_t *card, pm_message_t state)
1398{
1399 cs4231_t *chip = card->pm_private_data;
1400 if (chip->suspend)
1401 chip->suspend(chip);
1402 return 0;
1403}
1404
1405static int snd_cs4231_pm_resume(snd_card_t *card)
1406{
1407 cs4231_t *chip = card->pm_private_data;
1408 if (chip->resume)
1409 chip->resume(chip);
1410 return 0;
1411}
1412#endif /* CONFIG_PM */
1413
1414#ifdef LEGACY_SUPPORT
1415
1416static int snd_cs4231_free(cs4231_t *chip)
1417{
1418 if (chip->res_port) {
1419 release_resource(chip->res_port);
1420 kfree_nocheck(chip->res_port);
1421 }
1422 if (chip->res_cport) {
1423 release_resource(chip->res_cport);
1424 kfree_nocheck(chip->res_cport);
1425 }
1426 if (chip->irq >= 0) {
1427 disable_irq(chip->irq);
1428 if (!(chip->hwshare & CS4231_HWSHARE_IRQ))
1429 free_irq(chip->irq, (void *) chip);
1430 }
1431 if (!(chip->hwshare & CS4231_HWSHARE_DMA1) && chip->dma1 >= 0) {
1432 snd_dma_disable(chip->dma1);
1433 free_dma(chip->dma1);
1434 }
1435 if (!(chip->hwshare & CS4231_HWSHARE_DMA2) && chip->dma2 >= 0 && chip->dma2 != chip->dma1) {
1436 snd_dma_disable(chip->dma2);
1437 free_dma(chip->dma2);
1438 }
1439 if (chip->timer)
1440 snd_device_free(chip->card, chip->timer);
1441 kfree(chip);
1442 return 0;
1443}
1444
1445static int snd_cs4231_dev_free(snd_device_t *device)
1446{
1447 cs4231_t *chip = device->device_data;
1448 return snd_cs4231_free(chip);
1449}
1450
1451#endif /* LEGACY_SUPPORT */
1452
1453const char *snd_cs4231_chip_id(cs4231_t *chip)
1454{
1455 switch (chip->hardware) {
1456 case CS4231_HW_CS4231: return "CS4231";
1457 case CS4231_HW_CS4231A: return "CS4231A";
1458 case CS4231_HW_CS4232: return "CS4232";
1459 case CS4231_HW_CS4232A: return "CS4232A";
1460 case CS4231_HW_CS4235: return "CS4235";
1461 case CS4231_HW_CS4236: return "CS4236";
1462 case CS4231_HW_CS4236B: return "CS4236B";
1463 case CS4231_HW_CS4237B: return "CS4237B";
1464 case CS4231_HW_CS4238B: return "CS4238B";
1465 case CS4231_HW_CS4239: return "CS4239";
1466 case CS4231_HW_INTERWAVE: return "AMD InterWave";
1467 case CS4231_HW_OPL3SA2: return chip->card->shortname;
1468 case CS4231_HW_AD1845: return "AD1845";
1469 default: return "???";
1470 }
1471}
1472
1473static int snd_cs4231_new(snd_card_t * card,
1474 unsigned short hardware,
1475 unsigned short hwshare,
1476 cs4231_t ** rchip)
1477{
1478 cs4231_t *chip;
1479
1480 *rchip = NULL;
1481 chip = kcalloc(1, sizeof(*chip), GFP_KERNEL);
1482 if (chip == NULL)
1483 return -ENOMEM;
1484 chip->hardware = hardware;
1485 chip->hwshare = hwshare;
1486
1487 spin_lock_init(&chip->reg_lock);
1488 init_MUTEX(&chip->mce_mutex);
1489 init_MUTEX(&chip->open_mutex);
1490 chip->card = card;
1491 chip->rate_constraint = snd_cs4231_xrate;
1492 chip->set_playback_format = snd_cs4231_playback_format;
1493 chip->set_capture_format = snd_cs4231_capture_format;
1494 memcpy(&chip->image, &snd_cs4231_original_image, sizeof(snd_cs4231_original_image));
1495
1496 *rchip = chip;
1497 return 0;
1498}
1499
1500#ifdef LEGACY_SUPPORT
1501
1502int snd_cs4231_create(snd_card_t * card,
1503 unsigned long port,
1504 unsigned long cport,
1505 int irq, int dma1, int dma2,
1506 unsigned short hardware,
1507 unsigned short hwshare,
1508 cs4231_t ** rchip)
1509{
1510 static snd_device_ops_t ops = {
1511 .dev_free = snd_cs4231_dev_free,
1512 };
1513 cs4231_t *chip;
1514 int err;
1515
1516 err = snd_cs4231_new(card, hardware, hwshare, &chip);
1517 if (err < 0)
1518 return err;
1519
1520 chip->irq = -1;
1521 chip->dma1 = -1;
1522 chip->dma2 = -1;
1523
1524 if ((chip->res_port = request_region(port, 4, "CS4231")) == NULL) {
1525 snd_printk(KERN_ERR "cs4231: can't grab port 0x%lx\n", port);
1526 snd_cs4231_free(chip);
1527 return -EBUSY;
1528 }
1529 chip->port = port;
1530 if ((long)cport >= 0 && (chip->res_cport = request_region(cport, 8, "CS4232 Control")) == NULL) {
1531 snd_printk(KERN_ERR "cs4231: can't grab control port 0x%lx\n", cport);
1532 snd_cs4231_free(chip);
1533 return -ENODEV;
1534 }
1535 chip->cport = cport;
1536 if (!(hwshare & CS4231_HWSHARE_IRQ) && request_irq(irq, snd_cs4231_interrupt, SA_INTERRUPT, "CS4231", (void *) chip)) {
1537 snd_printk(KERN_ERR "cs4231: can't grab IRQ %d\n", irq);
1538 snd_cs4231_free(chip);
1539 return -EBUSY;
1540 }
1541 chip->irq = irq;
1542 if (!(hwshare & CS4231_HWSHARE_DMA1) && request_dma(dma1, "CS4231 - 1")) {
1543 snd_printk(KERN_ERR "cs4231: can't grab DMA1 %d\n", dma1);
1544 snd_cs4231_free(chip);
1545 return -EBUSY;
1546 }
1547 chip->dma1 = dma1;
1548 if (!(hwshare & CS4231_HWSHARE_DMA2) && dma1 != dma2 && dma2 >= 0 && request_dma(dma2, "CS4231 - 2")) {
1549 snd_printk(KERN_ERR "cs4231: can't grab DMA2 %d\n", dma2);
1550 snd_cs4231_free(chip);
1551 return -EBUSY;
1552 }
1553 if (dma1 == dma2 || dma2 < 0) {
1554 chip->single_dma = 1;
1555 chip->dma2 = chip->dma1;
1556 } else
1557 chip->dma2 = dma2;
1558
1559 /* global setup */
1560 if (snd_cs4231_probe(chip) < 0) {
1561 snd_cs4231_free(chip);
1562 return -ENODEV;
1563 }
1564 snd_cs4231_init(chip);
1565
1566 if (chip->hardware & CS4231_HW_CS4232_MASK) {
1567 if (chip->res_cport == NULL)
1568 snd_printk("CS4232 control port features are not accessible\n");
1569 }
1570
1571 /* Register device */
1572 if ((err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops)) < 0) {
1573 snd_cs4231_free(chip);
1574 return err;
1575 }
1576
1577#ifdef CONFIG_PM
1578 /* Power Management */
1579 chip->suspend = snd_cs4231_suspend;
1580 chip->resume = snd_cs4231_resume;
1581 snd_card_set_isa_pm_callback(card, snd_cs4231_pm_suspend, snd_cs4231_pm_resume, chip);
1582#endif
1583
1584 *rchip = chip;
1585 return 0;
1586}
1587
1588#endif /* LEGACY_SUPPORT */
1589
1590static snd_pcm_ops_t snd_cs4231_playback_ops = {
1591 .open = snd_cs4231_playback_open,
1592 .close = snd_cs4231_playback_close,
1593 .ioctl = snd_pcm_lib_ioctl,
1594 .hw_params = snd_cs4231_playback_hw_params,
1595 .hw_free = snd_cs4231_playback_hw_free,
1596 .prepare = snd_cs4231_playback_prepare,
1597 .trigger = snd_cs4231_trigger,
1598 .pointer = snd_cs4231_playback_pointer,
1599};
1600
1601static snd_pcm_ops_t snd_cs4231_capture_ops = {
1602 .open = snd_cs4231_capture_open,
1603 .close = snd_cs4231_capture_close,
1604 .ioctl = snd_pcm_lib_ioctl,
1605 .hw_params = snd_cs4231_capture_hw_params,
1606 .hw_free = snd_cs4231_capture_hw_free,
1607 .prepare = snd_cs4231_capture_prepare,
1608 .trigger = snd_cs4231_trigger,
1609 .pointer = snd_cs4231_capture_pointer,
1610};
1611
1612static void snd_cs4231_pcm_free(snd_pcm_t *pcm)
1613{
1614 cs4231_t *chip = pcm->private_data;
1615 chip->pcm = NULL;
1616 snd_pcm_lib_preallocate_free_for_all(pcm);
1617}
1618
1619int snd_cs4231_pcm(cs4231_t *chip, int device, snd_pcm_t **rpcm)
1620{
1621 snd_pcm_t *pcm;
1622 int err;
1623
1624 if ((err = snd_pcm_new(chip->card, "CS4231", device, 1, 1, &pcm)) < 0)
1625 return err;
1626
1627 spin_lock_init(&chip->reg_lock);
1628 init_MUTEX(&chip->mce_mutex);
1629 init_MUTEX(&chip->open_mutex);
1630
1631 snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_cs4231_playback_ops);
1632 snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_cs4231_capture_ops);
1633
1634 /* global setup */
1635 pcm->private_data = chip;
1636 pcm->private_free = snd_cs4231_pcm_free;
1637 pcm->info_flags = 0;
1638 if (chip->single_dma)
1639 pcm->info_flags |= SNDRV_PCM_INFO_HALF_DUPLEX;
1640 if (chip->hardware != CS4231_HW_INTERWAVE)
1641 pcm->info_flags |= SNDRV_PCM_INFO_JOINT_DUPLEX;
1642 strcpy(pcm->name, snd_cs4231_chip_id(chip));
1643
1644#ifdef LEGACY_SUPPORT
1645 snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV,
1646 snd_dma_isa_data(),
1647 64*1024, chip->dma1 > 3 || chip->dma2 > 3 ? 128*1024 : 64*1024);
1648#else
1649# ifdef EBUS_SUPPORT
1650 if (chip->ebus_flag) {
1651 snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV,
1652 chip->dev_u.pdev,
1653 64*1024, 128*1024);
1654 } else {
1655# endif
1656# ifdef SBUS_SUPPORT
1657 snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_SBUS,
1658 chip->dev_u.sdev,
1659 64*1024, 128*1024);
1660# endif
1661# ifdef EBUS_SUPPORT
1662 }
1663# endif
1664#endif
1665
1666 chip->pcm = pcm;
1667 if (rpcm)
1668 *rpcm = pcm;
1669 return 0;
1670}
1671
1672static void snd_cs4231_timer_free(snd_timer_t *timer)
1673{
1674 cs4231_t *chip = timer->private_data;
1675 chip->timer = NULL;
1676}
1677
1678int snd_cs4231_timer(cs4231_t *chip, int device, snd_timer_t **rtimer)
1679{
1680 snd_timer_t *timer;
1681 snd_timer_id_t tid;
1682 int err;
1683
1684 /* Timer initialization */
1685 tid.dev_class = SNDRV_TIMER_CLASS_CARD;
1686 tid.dev_sclass = SNDRV_TIMER_SCLASS_NONE;
1687 tid.card = chip->card->number;
1688 tid.device = device;
1689 tid.subdevice = 0;
1690 if ((err = snd_timer_new(chip->card, "CS4231", &tid, &timer)) < 0)
1691 return err;
1692 strcpy(timer->name, snd_cs4231_chip_id(chip));
1693 timer->private_data = chip;
1694 timer->private_free = snd_cs4231_timer_free;
1695 timer->hw = snd_cs4231_timer_table;
1696 chip->timer = timer;
1697 if (rtimer)
1698 *rtimer = timer;
1699 return 0;
1700}
1701
1702/*
1703 * MIXER part
1704 */
1705
1706static int snd_cs4231_info_mux(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
1707{
1708 static char *texts[4] = {
1709 "Line", "Aux", "Mic", "Mix"
1710 };
1711 static char *opl3sa_texts[4] = {
1712 "Line", "CD", "Mic", "Mix"
1713 };
1714 static char *gusmax_texts[4] = {
1715 "Line", "Synth", "Mic", "Mix"
1716 };
1717 char **ptexts = texts;
1718 cs4231_t *chip = snd_kcontrol_chip(kcontrol);
1719
1720 snd_assert(chip->card != NULL, return -EINVAL);
1721 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
1722 uinfo->count = 2;
1723 uinfo->value.enumerated.items = 4;
1724 if (uinfo->value.enumerated.item > 3)
1725 uinfo->value.enumerated.item = 3;
1726 if (!strcmp(chip->card->driver, "GUS MAX"))
1727 ptexts = gusmax_texts;
1728 switch (chip->hardware) {
1729 case CS4231_HW_INTERWAVE: ptexts = gusmax_texts; break;
1730 case CS4231_HW_OPL3SA2: ptexts = opl3sa_texts; break;
1731 }
1732 strcpy(uinfo->value.enumerated.name, ptexts[uinfo->value.enumerated.item]);
1733 return 0;
1734}
1735
1736static int snd_cs4231_get_mux(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
1737{
1738 cs4231_t *chip = snd_kcontrol_chip(kcontrol);
1739 unsigned long flags;
1740
1741 spin_lock_irqsave(&chip->reg_lock, flags);
1742 ucontrol->value.enumerated.item[0] = (chip->image[CS4231_LEFT_INPUT] & CS4231_MIXS_ALL) >> 6;
1743 ucontrol->value.enumerated.item[1] = (chip->image[CS4231_RIGHT_INPUT] & CS4231_MIXS_ALL) >> 6;
1744 spin_unlock_irqrestore(&chip->reg_lock, flags);
1745 return 0;
1746}
1747
1748static int snd_cs4231_put_mux(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
1749{
1750 cs4231_t *chip = snd_kcontrol_chip(kcontrol);
1751 unsigned long flags;
1752 unsigned short left, right;
1753 int change;
1754
1755 if (ucontrol->value.enumerated.item[0] > 3 ||
1756 ucontrol->value.enumerated.item[1] > 3)
1757 return -EINVAL;
1758 left = ucontrol->value.enumerated.item[0] << 6;
1759 right = ucontrol->value.enumerated.item[1] << 6;
1760 spin_lock_irqsave(&chip->reg_lock, flags);
1761 left = (chip->image[CS4231_LEFT_INPUT] & ~CS4231_MIXS_ALL) | left;
1762 right = (chip->image[CS4231_RIGHT_INPUT] & ~CS4231_MIXS_ALL) | right;
1763 change = left != chip->image[CS4231_LEFT_INPUT] ||
1764 right != chip->image[CS4231_RIGHT_INPUT];
1765 snd_cs4231_out(chip, CS4231_LEFT_INPUT, left);
1766 snd_cs4231_out(chip, CS4231_RIGHT_INPUT, right);
1767 spin_unlock_irqrestore(&chip->reg_lock, flags);
1768 return change;
1769}
1770
1771int snd_cs4231_info_single(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
1772{
1773 int mask = (kcontrol->private_value >> 16) & 0xff;
1774
1775 uinfo->type = mask == 1 ? SNDRV_CTL_ELEM_TYPE_BOOLEAN : SNDRV_CTL_ELEM_TYPE_INTEGER;
1776 uinfo->count = 1;
1777 uinfo->value.integer.min = 0;
1778 uinfo->value.integer.max = mask;
1779 return 0;
1780}
1781
1782int snd_cs4231_get_single(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
1783{
1784 cs4231_t *chip = snd_kcontrol_chip(kcontrol);
1785 unsigned long flags;
1786 int reg = kcontrol->private_value & 0xff;
1787 int shift = (kcontrol->private_value >> 8) & 0xff;
1788 int mask = (kcontrol->private_value >> 16) & 0xff;
1789 int invert = (kcontrol->private_value >> 24) & 0xff;
1790
1791 spin_lock_irqsave(&chip->reg_lock, flags);
1792 ucontrol->value.integer.value[0] = (chip->image[reg] >> shift) & mask;
1793 spin_unlock_irqrestore(&chip->reg_lock, flags);
1794 if (invert)
1795 ucontrol->value.integer.value[0] = mask - ucontrol->value.integer.value[0];
1796 return 0;
1797}
1798
1799int snd_cs4231_put_single(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
1800{
1801 cs4231_t *chip = snd_kcontrol_chip(kcontrol);
1802 unsigned long flags;
1803 int reg = kcontrol->private_value & 0xff;
1804 int shift = (kcontrol->private_value >> 8) & 0xff;
1805 int mask = (kcontrol->private_value >> 16) & 0xff;
1806 int invert = (kcontrol->private_value >> 24) & 0xff;
1807 int change;
1808 unsigned short val;
1809
1810 val = (ucontrol->value.integer.value[0] & mask);
1811 if (invert)
1812 val = mask - val;
1813 val <<= shift;
1814 spin_lock_irqsave(&chip->reg_lock, flags);
1815 val = (chip->image[reg] & ~(mask << shift)) | val;
1816 change = val != chip->image[reg];
1817 snd_cs4231_out(chip, reg, val);
1818 spin_unlock_irqrestore(&chip->reg_lock, flags);
1819 return change;
1820}
1821
1822int snd_cs4231_info_double(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
1823{
1824 int mask = (kcontrol->private_value >> 24) & 0xff;
1825
1826 uinfo->type = mask == 1 ? SNDRV_CTL_ELEM_TYPE_BOOLEAN : SNDRV_CTL_ELEM_TYPE_INTEGER;
1827 uinfo->count = 2;
1828 uinfo->value.integer.min = 0;
1829 uinfo->value.integer.max = mask;
1830 return 0;
1831}
1832
1833int snd_cs4231_get_double(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
1834{
1835 cs4231_t *chip = snd_kcontrol_chip(kcontrol);
1836 unsigned long flags;
1837 int left_reg = kcontrol->private_value & 0xff;
1838 int right_reg = (kcontrol->private_value >> 8) & 0xff;
1839 int shift_left = (kcontrol->private_value >> 16) & 0x07;
1840 int shift_right = (kcontrol->private_value >> 19) & 0x07;
1841 int mask = (kcontrol->private_value >> 24) & 0xff;
1842 int invert = (kcontrol->private_value >> 22) & 1;
1843
1844 spin_lock_irqsave(&chip->reg_lock, flags);
1845 ucontrol->value.integer.value[0] = (chip->image[left_reg] >> shift_left) & mask;
1846 ucontrol->value.integer.value[1] = (chip->image[right_reg] >> shift_right) & mask;
1847 spin_unlock_irqrestore(&chip->reg_lock, flags);
1848 if (invert) {
1849 ucontrol->value.integer.value[0] = mask - ucontrol->value.integer.value[0];
1850 ucontrol->value.integer.value[1] = mask - ucontrol->value.integer.value[1];
1851 }
1852 return 0;
1853}
1854
1855int snd_cs4231_put_double(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
1856{
1857 cs4231_t *chip = snd_kcontrol_chip(kcontrol);
1858 unsigned long flags;
1859 int left_reg = kcontrol->private_value & 0xff;
1860 int right_reg = (kcontrol->private_value >> 8) & 0xff;
1861 int shift_left = (kcontrol->private_value >> 16) & 0x07;
1862 int shift_right = (kcontrol->private_value >> 19) & 0x07;
1863 int mask = (kcontrol->private_value >> 24) & 0xff;
1864 int invert = (kcontrol->private_value >> 22) & 1;
1865 int change;
1866 unsigned short val1, val2;
1867
1868 val1 = ucontrol->value.integer.value[0] & mask;
1869 val2 = ucontrol->value.integer.value[1] & mask;
1870 if (invert) {
1871 val1 = mask - val1;
1872 val2 = mask - val2;
1873 }
1874 val1 <<= shift_left;
1875 val2 <<= shift_right;
1876 spin_lock_irqsave(&chip->reg_lock, flags);
1877 val1 = (chip->image[left_reg] & ~(mask << shift_left)) | val1;
1878 val2 = (chip->image[right_reg] & ~(mask << shift_right)) | val2;
1879 change = val1 != chip->image[left_reg] || val2 != chip->image[right_reg];
1880 snd_cs4231_out(chip, left_reg, val1);
1881 snd_cs4231_out(chip, right_reg, val2);
1882 spin_unlock_irqrestore(&chip->reg_lock, flags);
1883 return change;
1884}
1885
1886static snd_kcontrol_new_t snd_cs4231_controls[] = {
1887CS4231_DOUBLE("PCM Playback Switch", 0, CS4231_LEFT_OUTPUT, CS4231_RIGHT_OUTPUT, 7, 7, 1, 1),
1888CS4231_DOUBLE("PCM Playback Volume", 0, CS4231_LEFT_OUTPUT, CS4231_RIGHT_OUTPUT, 0, 0, 63, 1),
1889CS4231_DOUBLE("Line Playback Switch", 0, CS4231_LEFT_LINE_IN, CS4231_RIGHT_LINE_IN, 7, 7, 1, 1),
1890CS4231_DOUBLE("Line Playback Volume", 0, CS4231_LEFT_LINE_IN, CS4231_RIGHT_LINE_IN, 0, 0, 31, 1),
1891CS4231_DOUBLE("Aux Playback Switch", 0, CS4231_AUX1_LEFT_INPUT, CS4231_AUX1_RIGHT_INPUT, 7, 7, 1, 1),
1892CS4231_DOUBLE("Aux Playback Volume", 0, CS4231_AUX1_LEFT_INPUT, CS4231_AUX1_RIGHT_INPUT, 0, 0, 31, 1),
1893CS4231_DOUBLE("Aux Playback Switch", 1, CS4231_AUX2_LEFT_INPUT, CS4231_AUX2_RIGHT_INPUT, 7, 7, 1, 1),
1894CS4231_DOUBLE("Aux Playback Volume", 1, CS4231_AUX2_LEFT_INPUT, CS4231_AUX2_RIGHT_INPUT, 0, 0, 31, 1),
1895CS4231_SINGLE("Mono Playback Switch", 0, CS4231_MONO_CTRL, 7, 1, 1),
1896CS4231_SINGLE("Mono Playback Volume", 0, CS4231_MONO_CTRL, 0, 15, 1),
1897CS4231_SINGLE("Mono Output Playback Switch", 0, CS4231_MONO_CTRL, 6, 1, 1),
1898CS4231_SINGLE("Mono Output Playback Bypass", 0, CS4231_MONO_CTRL, 5, 1, 0),
1899CS4231_DOUBLE("Capture Volume", 0, CS4231_LEFT_INPUT, CS4231_RIGHT_INPUT, 0, 0, 15, 0),
1900{
1901 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1902 .name = "Capture Source",
1903 .info = snd_cs4231_info_mux,
1904 .get = snd_cs4231_get_mux,
1905 .put = snd_cs4231_put_mux,
1906},
1907CS4231_DOUBLE("Mic Boost", 0, CS4231_LEFT_INPUT, CS4231_RIGHT_INPUT, 5, 5, 1, 0),
1908CS4231_SINGLE("Loopback Capture Switch", 0, CS4231_LOOPBACK, 0, 1, 0),
1909CS4231_SINGLE("Loopback Capture Volume", 0, CS4231_LOOPBACK, 2, 63, 1)
1910};
1911
1912int snd_cs4231_mixer(cs4231_t *chip)
1913{
1914 snd_card_t *card;
1915 unsigned int idx;
1916 int err;
1917
1918 snd_assert(chip != NULL && chip->pcm != NULL, return -EINVAL);
1919
1920 card = chip->card;
1921
1922 strcpy(card->mixername, chip->pcm->name);
1923
1924 for (idx = 0; idx < ARRAY_SIZE(snd_cs4231_controls); idx++) {
1925 if ((err = snd_ctl_add(card, snd_ctl_new1(&snd_cs4231_controls[idx], chip))) < 0)
1926 return err;
1927 }
1928 return 0;
1929}
1930
1931EXPORT_SYMBOL(snd_cs4231_out);
1932EXPORT_SYMBOL(snd_cs4231_in);
1933EXPORT_SYMBOL(snd_cs4236_ext_out);
1934EXPORT_SYMBOL(snd_cs4236_ext_in);
1935EXPORT_SYMBOL(snd_cs4231_mce_up);
1936EXPORT_SYMBOL(snd_cs4231_mce_down);
1937EXPORT_SYMBOL(snd_cs4231_interrupt);
1938EXPORT_SYMBOL(snd_cs4231_chip_id);
1939EXPORT_SYMBOL(snd_cs4231_create);
1940EXPORT_SYMBOL(snd_cs4231_pcm);
1941EXPORT_SYMBOL(snd_cs4231_mixer);
1942EXPORT_SYMBOL(snd_cs4231_timer);
1943EXPORT_SYMBOL(snd_cs4231_info_single);
1944EXPORT_SYMBOL(snd_cs4231_get_single);
1945EXPORT_SYMBOL(snd_cs4231_put_single);
1946EXPORT_SYMBOL(snd_cs4231_info_double);
1947EXPORT_SYMBOL(snd_cs4231_get_double);
1948EXPORT_SYMBOL(snd_cs4231_put_double);
1949
1950/*
1951 * INIT part
1952 */
1953
1954static int __init alsa_cs4231_init(void)
1955{
1956 return 0;
1957}
1958
1959static void __exit alsa_cs4231_exit(void)
1960{
1961}
1962
1963module_init(alsa_cs4231_init)
1964module_exit(alsa_cs4231_exit)
diff --git a/sound/isa/cs423x/cs4232.c b/sound/isa/cs423x/cs4232.c
new file mode 100644
index 000000000000..9fad2e6c0c2c
--- /dev/null
+++ b/sound/isa/cs423x/cs4232.c
@@ -0,0 +1,2 @@
1#define CS4232
2#include "cs4236.c"
diff --git a/sound/isa/cs423x/cs4236.c b/sound/isa/cs423x/cs4236.c
new file mode 100644
index 000000000000..e745a54e00a1
--- /dev/null
+++ b/sound/isa/cs423x/cs4236.c
@@ -0,0 +1,608 @@
1/*
2 * Driver for generic CS4232/CS4235/CS4236/CS4236B/CS4237B/CS4238B/CS4239 chips
3 * Copyright (c) by Jaroslav Kysela <perex@suse.cz>
4 *
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 *
20 */
21
22#include <sound/driver.h>
23#include <linux/init.h>
24#include <linux/slab.h>
25#include <linux/pnp.h>
26#include <linux/moduleparam.h>
27#include <sound/core.h>
28#include <sound/cs4231.h>
29#include <sound/mpu401.h>
30#include <sound/opl3.h>
31#include <sound/initval.h>
32
33MODULE_AUTHOR("Jaroslav Kysela <perex@suse.cz>");
34MODULE_LICENSE("GPL");
35#ifdef CS4232
36MODULE_DESCRIPTION("Cirrus Logic CS4232");
37MODULE_SUPPORTED_DEVICE("{{Turtle Beach,TBS-2000},"
38 "{Turtle Beach,Tropez Plus},"
39 "{SIC CrystalWave 32},"
40 "{Hewlett Packard,Omnibook 5500},"
41 "{TerraTec,Maestro 32/96},"
42 "{Philips,PCA70PS}}");
43#else
44MODULE_DESCRIPTION("Cirrus Logic CS4235-9");
45MODULE_SUPPORTED_DEVICE("{{Crystal Semiconductors,CS4235},"
46 "{Crystal Semiconductors,CS4236},"
47 "{Crystal Semiconductors,CS4237},"
48 "{Crystal Semiconductors,CS4238},"
49 "{Crystal Semiconductors,CS4239},"
50 "{Acer,AW37},"
51 "{Acer,AW35/Pro},"
52 "{Crystal,3D},"
53 "{Crystal Computer,TidalWave128},"
54 "{Dell,Optiplex GX1},"
55 "{Dell,Workstation 400 sound},"
56 "{EliteGroup,P5TX-LA sound},"
57 "{Gallant,SC-70P},"
58 "{Gateway,E1000 Onboard CS4236B},"
59 "{Genius,Sound Maker 3DJ},"
60 "{Hewlett Packard,HP6330 sound},"
61 "{IBM,PC 300PL sound},"
62 "{IBM,Aptiva 2137 E24},"
63 "{IBM,IntelliStation M Pro},"
64 "{Intel,Marlin Spike Mobo CS4235},"
65 "{Intel PR440FX Onboard},"
66 "{Guillemot,MaxiSound 16 PnP},"
67 "{NewClear,3D},"
68 "{TerraTec,AudioSystem EWS64L/XL},"
69 "{Typhoon Soundsystem,CS4236B},"
70 "{Turtle Beach,Malibu},"
71 "{Unknown,Digital PC 5000 Onboard}}");
72#endif
73
74#ifdef CS4232
75#define IDENT "CS4232"
76#else
77#define IDENT "CS4236+"
78#endif
79
80static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-MAX */
81static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* ID for this card */
82static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_ISAPNP; /* Enable this card */
83#ifdef CONFIG_PNP
84static int isapnp[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 1};
85#endif
86static long port[SNDRV_CARDS] = SNDRV_DEFAULT_PORT; /* PnP setup */
87static long cport[SNDRV_CARDS] = SNDRV_DEFAULT_PORT; /* PnP setup */
88static long mpu_port[SNDRV_CARDS] = SNDRV_DEFAULT_PORT;/* PnP setup */
89static long fm_port[SNDRV_CARDS] = SNDRV_DEFAULT_PORT; /* PnP setup */
90static long sb_port[SNDRV_CARDS] = SNDRV_DEFAULT_PORT; /* PnP setup */
91static int irq[SNDRV_CARDS] = SNDRV_DEFAULT_IRQ; /* 5,7,9,11,12,15 */
92static int mpu_irq[SNDRV_CARDS] = SNDRV_DEFAULT_IRQ; /* 9,11,12,15 */
93static int dma1[SNDRV_CARDS] = SNDRV_DEFAULT_DMA; /* 0,1,3,5,6,7 */
94static int dma2[SNDRV_CARDS] = SNDRV_DEFAULT_DMA; /* 0,1,3,5,6,7 */
95
96module_param_array(index, int, NULL, 0444);
97MODULE_PARM_DESC(index, "Index value for " IDENT " soundcard.");
98module_param_array(id, charp, NULL, 0444);
99MODULE_PARM_DESC(id, "ID string for " IDENT " soundcard.");
100module_param_array(enable, bool, NULL, 0444);
101MODULE_PARM_DESC(enable, "Enable " IDENT " soundcard.");
102#ifdef CONFIG_PNP
103module_param_array(isapnp, bool, NULL, 0444);
104MODULE_PARM_DESC(isapnp, "ISA PnP detection for specified soundcard.");
105#endif
106module_param_array(port, long, NULL, 0444);
107MODULE_PARM_DESC(port, "Port # for " IDENT " driver.");
108module_param_array(cport, long, NULL, 0444);
109MODULE_PARM_DESC(cport, "Control port # for " IDENT " driver.");
110module_param_array(mpu_port, long, NULL, 0444);
111MODULE_PARM_DESC(mpu_port, "MPU-401 port # for " IDENT " driver.");
112module_param_array(fm_port, long, NULL, 0444);
113MODULE_PARM_DESC(fm_port, "FM port # for " IDENT " driver.");
114module_param_array(sb_port, long, NULL, 0444);
115MODULE_PARM_DESC(sb_port, "SB port # for " IDENT " driver (optional).");
116module_param_array(irq, int, NULL, 0444);
117MODULE_PARM_DESC(irq, "IRQ # for " IDENT " driver.");
118module_param_array(mpu_irq, int, NULL, 0444);
119MODULE_PARM_DESC(mpu_irq, "MPU-401 IRQ # for " IDENT " driver.");
120module_param_array(dma1, int, NULL, 0444);
121MODULE_PARM_DESC(dma1, "DMA1 # for " IDENT " driver.");
122module_param_array(dma2, int, NULL, 0444);
123MODULE_PARM_DESC(dma2, "DMA2 # for " IDENT " driver.");
124
125struct snd_card_cs4236 {
126 struct resource *res_sb_port;
127#ifdef CONFIG_PNP
128 struct pnp_dev *wss;
129 struct pnp_dev *ctrl;
130 struct pnp_dev *mpu;
131#endif
132};
133
134static snd_card_t *snd_cs4236_legacy[SNDRV_CARDS] = SNDRV_DEFAULT_PTR;
135
136#ifdef CONFIG_PNP
137
138#define ISAPNP_CS4232(_va, _vb, _vc, _device, _wss, _ctrl, _mpu401) \
139 { \
140 ISAPNP_CARD_ID(_va, _vb, _vc, _device), \
141 .devs = { ISAPNP_DEVICE_ID(_va, _vb, _vc, _wss), \
142 ISAPNP_DEVICE_ID(_va, _vb, _vc, _ctrl), \
143 ISAPNP_DEVICE_ID(_va, _vb, _vc, _mpu401) } \
144 }
145#define ISAPNP_CS4232_1(_va, _vb, _vc, _device, _wss, _ctrl, _mpu401) \
146 { \
147 ISAPNP_CARD_ID(_va, _vb, _vc, _device), \
148 .devs = { ISAPNP_DEVICE_ID(_va, _vb, _vc, _wss), \
149 ISAPNP_DEVICE_ID(_va, _vb, _vc, _ctrl), \
150 ISAPNP_DEVICE_ID('P', 'N', 'P', _mpu401) } \
151 }
152#define ISAPNP_CS4232_WOMPU(_va, _vb, _vc, _device, _wss, _ctrl) \
153 { \
154 ISAPNP_CARD_ID(_va, _vb, _vc, _device), \
155 .devs = { ISAPNP_DEVICE_ID(_va, _vb, _vc, _wss), \
156 ISAPNP_DEVICE_ID(_va, _vb, _vc, _ctrl) } \
157 }
158
159
160#ifdef CS4232
161static struct pnp_card_device_id snd_cs423x_pnpids[] = {
162 /* Philips PCA70PS */
163 { .id = "CSC0d32", .devs = { { "CSC0000" }, { "CSC0010" }, { "PNPb006" } } },
164 /* TerraTec Maestro 32/96 (CS4232) */
165 { .id = "CSC1a32", .devs = { { "CSC0000" }, { "CSC0010" }, { "CSC0003" } } },
166 /* HP Omnibook 5500 onboard */
167 { .id = "CSC4232", .devs = { { "CSC0000" }, { "CSC0002" }, { "CSC0003" } } },
168 /* Unnamed CS4236 card (Made in Taiwan) */
169 { .id = "CSC4236", .devs = { { "CSC0000" }, { "CSC0010" }, { "CSC0003" } } },
170 /* Turtle Beach TBS-2000 (CS4232) */
171 { .id = "CSC7532", .devs = { { "CSC0000" }, { "CSC0010" }, { "CSCb006" } } },
172 /* Turtle Beach Tropez Plus (CS4232) */
173 { .id = "CSC7632", .devs = { { "CSC0000" }, { "CSC0010" }, { "PNPb006" } } },
174 /* SIC CrystalWave 32 (CS4232) */
175 { .id = "CSCf032", .devs = { { "CSC0000" }, { "CSC0010" }, { "CSC0003" } } },
176 /* --- */
177 { .id = "" } /* end */
178};
179#else /* CS4236 */
180static struct pnp_card_device_id snd_cs423x_pnpids[] = {
181 /* Intel Marlin Spike Motherboard - CS4235 */
182 { .id = "CSC0225", .devs = { { "CSC0000" }, { "CSC0010" }, { "CSC0003" } } },
183 /* Intel Marlin Spike Motherboard (#2) - CS4235 */
184 { .id = "CSC0225", .devs = { { "CSC0100" }, { "CSC0110" }, { "CSC0103" } } },
185 /* Unknown Intel mainboard - CS4235 */
186 { .id = "CSC0225", .devs = { { "CSC0100" }, { "CSC0110" } } },
187 /* Genius Sound Maker 3DJ - CS4237B */
188 { .id = "CSC0437", .devs = { { "CSC0000" }, { "CSC0010" }, { "CSC0003" } } },
189 /* Digital PC 5000 Onboard - CS4236B */
190 { .id = "CSC0735", .devs = { { "CSC0000" }, { "CSC0010" } } },
191 /* some uknown CS4236B */
192 { .id = "CSC0b35", .devs = { { "CSC0000" }, { "CSC0010" }, { "CSC0003" } } },
193 /* Intel PR440FX Onboard sound */
194 { .id = "CSC0b36", .devs = { { "CSC0000" }, { "CSC0010" }, { "CSC0003" } } },
195 /* CS4235 on mainboard without MPU */
196 { .id = "CSC1425", .devs = { { "CSC0100" }, { "CSC0110" } } },
197 /* Gateway E1000 Onboard CS4236B */
198 { .id = "CSC1335", .devs = { { "CSC0000" }, { "CSC0010" }, { "CSC0003" } } },
199 /* HP 6330 Onboard sound */
200 { .id = "CSC1525", .devs = { { "CSC0100" }, { "CSC0110" }, { "CSC0103" } } },
201 /* Crystal Computer TidalWave128 */
202 { .id = "CSC1e37", .devs = { { "CSC0000" }, { "CSC0010" }, { "CSC0003" } } },
203 /* ACER AW37 - CS4235 */
204 { .id = "CSC4236", .devs = { { "CSC0000" }, { "CSC0010" }, { "CSC0003" } } },
205 /* build-in soundcard in EliteGroup P5TX-LA motherboard - CS4237B */
206 { .id = "CSC4237", .devs = { { "CSC0000" }, { "CSC0010" }, { "CSC0003" } } },
207 /* Crystal 3D - CS4237B */
208 { .id = "CSC4336", .devs = { { "CSC0000" }, { "CSC0010" }, { "CSC0003" } } },
209 /* Typhoon Soundsystem PnP - CS4236B */
210 { .id = "CSC4536", .devs = { { "CSC0000" }, { "CSC0010" }, { "CSC0003" } } },
211 /* Crystal CX4235-XQ3 EP - CS4235 */
212 { .id = "CSC4625", .devs = { { "CSC0100" }, { "CSC0110" }, { "CSC0103" } } },
213 /* Crystal Semiconductors CS4237B */
214 { .id = "CSC4637", .devs = { { "CSC0000" }, { "CSC0010" }, { "CSC0003" } } },
215 /* NewClear 3D - CX4237B-XQ3 */
216 { .id = "CSC4837", .devs = { { "CSC0000" }, { "CSC0010" }, { "CSC0003" } } },
217 /* Dell Optiplex GX1 - CS4236B */
218 { .id = "CSC6835", .devs = { { "CSC0000" }, { "CSC0010" }, { "CSC0003" } } },
219 /* Dell P410 motherboard - CS4236B */
220 { .id = "CSC6835", .devs = { { "CSC0000" }, { "CSC0010" } } },
221 /* Dell Workstation 400 Onboard - CS4236B */
222 { .id = "CSC6836", .devs = { { "CSC0000" }, { "CSC0010" }, { "CSC0003" } } },
223 /* Turtle Beach Malibu - CS4237B */
224 { .id = "CSC7537", .devs = { { "CSC0000" }, { "CSC0010" }, { "CSC0003" } } },
225 /* CS4235 - onboard */
226 { .id = "CSC8025", .devs = { { "CSC0100" }, { "CSC0110" }, { "CSC0103" } } },
227 /* IBM Aptiva 2137 E24 Onboard - CS4237B */
228 { .id = "CSC8037", .devs = { { "CSC0000" }, { "CSC0010" }, { "CSC0003" } } },
229 /* IBM IntelliStation M Pro motherboard */
230 { .id = "CSCc835", .devs = { { "CSC0000" }, { "CSC0010" } } },
231 /* Guillemot MaxiSound 16 PnP - CS4236B */
232 { .id = "CSC9836", .devs = { { "CSC0000" }, { "CSC0010" }, { "CSC0003" } } },
233 /* Gallant SC-70P */
234 { .id = "CSC9837", .devs = { { "CSC0000" }, { "CSC0010" }, { "CSC0003" } } },
235 /* TerraTec AudioSystem EWS64XL - CS4236B */
236 { .id = "CSCa836", .devs = { { "CSCa800" }, { "CSCa810" }, { "CSCa803" } } },
237 /* TerraTec AudioSystem EWS64XL - CS4236B */
238 { .id = "CSCa836", .devs = { { "CSCa800" }, { "CSCa810" } } },
239 /* ACER AW37/Pro - CS4235 */
240 { .id = "CSCd925", .devs = { { "CSC0000" }, { "CSC0010" }, { "CSC0003" } } },
241 /* ACER AW35/Pro - CS4237B */
242 { .id = "CSCd937", .devs = { { "CSC0000" }, { "CSC0010" }, { "CSC0003" } } },
243 /* CS4235 without MPU401 */
244 { .id = "CSCe825", .devs = { { "CSC0100" }, { "CSC0110" } } },
245 /* Unknown SiS530 - CS4235 */
246 { .id = "CSC4825", .devs = { { "CSC0100" }, { "CSC0110" } } },
247 /* IBM IntelliStation M Pro 6898 11U - CS4236B */
248 { .id = "CSCe835", .devs = { { "CSC0000" }, { "CSC0010" } } },
249 /* IBM PC 300PL Onboard - CS4236B */
250 { .id = "CSCe836", .devs = { { "CSC0000" }, { "CSC0010" } } },
251 /* Some noname CS4236 based card */
252 { .id = "CSCe936", .devs = { { "CSC0000" }, { "CSC0010" }, { "CSC0003" } } },
253 /* CS4236B */
254 { .id = "CSCf235", .devs = { { "CSC0000" }, { "CSC0010" }, { "CSC0003" } } },
255 /* CS4236B */
256 { .id = "CSCf238", .devs = { { "CSC0000" }, { "CSC0010" }, { "CSC0003" } } },
257 /* --- */
258 { .id = "" } /* end */
259};
260#endif
261
262MODULE_DEVICE_TABLE(pnp_card, snd_cs423x_pnpids);
263
264static int __devinit snd_card_cs4236_pnp(int dev, struct snd_card_cs4236 *acard,
265 struct pnp_card_link *card,
266 const struct pnp_card_device_id *id)
267{
268 struct pnp_dev *pdev;
269 struct pnp_resource_table * cfg = kmalloc(sizeof(struct pnp_resource_table), GFP_KERNEL);
270 int err;
271
272 if (!cfg)
273 return -ENOMEM;
274
275 acard->wss = pnp_request_card_device(card, id->devs[0].id, NULL);
276 if (acard->wss == NULL) {
277 kfree(cfg);
278 return -EBUSY;
279 }
280 acard->ctrl = pnp_request_card_device(card, id->devs[1].id, NULL);
281 if (acard->ctrl == NULL) {
282 kfree(cfg);
283 return -EBUSY;
284 }
285 if (id->devs[2].id[0]) {
286 acard->mpu = pnp_request_card_device(card, id->devs[2].id, NULL);
287 if (acard->mpu == NULL) {
288 kfree(cfg);
289 return -EBUSY;
290 }
291 }
292
293 /* WSS initialization */
294 pdev = acard->wss;
295 pnp_init_resource_table(cfg);
296 if (port[dev] != SNDRV_AUTO_PORT)
297 pnp_resource_change(&cfg->port_resource[0], port[dev], 4);
298 if (fm_port[dev] != SNDRV_AUTO_PORT && fm_port[dev] > 0)
299 pnp_resource_change(&cfg->port_resource[1], fm_port[dev], 4);
300 if (sb_port[dev] != SNDRV_AUTO_PORT)
301 pnp_resource_change(&cfg->port_resource[2], sb_port[dev], 16);
302 if (irq[dev] != SNDRV_AUTO_IRQ)
303 pnp_resource_change(&cfg->irq_resource[0], irq[dev], 1);
304 if (dma1[dev] != SNDRV_AUTO_DMA)
305 pnp_resource_change(&cfg->dma_resource[0], dma1[dev], 1);
306 if (dma2[dev] != SNDRV_AUTO_DMA)
307 pnp_resource_change(&cfg->dma_resource[1], dma2[dev] < 0 ? 4 : dma2[dev], 1);
308 err = pnp_manual_config_dev(pdev, cfg, 0);
309 if (err < 0)
310 snd_printk(KERN_ERR IDENT " WSS PnP manual resources are invalid, using auto config\n");
311 err = pnp_activate_dev(pdev);
312 if (err < 0) {
313 kfree(cfg);
314 printk(KERN_ERR IDENT " WSS PnP configure failed for WSS (out of resources?)\n");
315 return -EBUSY;
316 }
317 port[dev] = pnp_port_start(pdev, 0);
318 if (fm_port[dev] > 0)
319 fm_port[dev] = pnp_port_start(pdev, 1);
320 sb_port[dev] = pnp_port_start(pdev, 2);
321 irq[dev] = pnp_irq(pdev, 0);
322 dma1[dev] = pnp_dma(pdev, 0);
323 dma2[dev] = pnp_dma(pdev, 1) == 4 ? -1 : (int)pnp_dma(pdev, 1);
324 snd_printdd("isapnp WSS: wss port=0x%lx, fm port=0x%lx, sb port=0x%lx\n",
325 port[dev], fm_port[dev], sb_port[dev]);
326 snd_printdd("isapnp WSS: irq=%i, dma1=%i, dma2=%i\n",
327 irq[dev], dma1[dev], dma2[dev]);
328 /* CTRL initialization */
329 if (acard->ctrl && cport[dev] > 0) {
330 pdev = acard->ctrl;
331 pnp_init_resource_table(cfg);
332 if (cport[dev] != SNDRV_AUTO_PORT)
333 pnp_resource_change(&cfg->port_resource[0], cport[dev], 8);
334 err = pnp_manual_config_dev(pdev, cfg, 0);
335 if (err < 0)
336 snd_printk(KERN_ERR IDENT " CTRL PnP manual resources are invalid, using auto config\n");
337 err = pnp_activate_dev(pdev);
338 if (err < 0) {
339 kfree(cfg);
340 printk(KERN_ERR IDENT " CTRL PnP configure failed for WSS (out of resources?)\n");
341 return -EBUSY;
342 }
343 cport[dev] = pnp_port_start(pdev, 0);
344 snd_printdd("isapnp CTRL: control port=0x%lx\n", cport[dev]);
345 }
346 /* MPU initialization */
347 if (acard->mpu && mpu_port[dev] > 0) {
348 pdev = acard->mpu;
349 pnp_init_resource_table(cfg);
350 if (mpu_port[dev] != SNDRV_AUTO_PORT)
351 pnp_resource_change(&cfg->port_resource[0], mpu_port[dev], 2);
352 if (mpu_irq[dev] != SNDRV_AUTO_IRQ && mpu_irq[dev] >= 0 &&
353 pnp_irq_valid(pdev, 0))
354 pnp_resource_change(&cfg->irq_resource[0], mpu_irq[dev], 1);
355 err = pnp_manual_config_dev(pdev, cfg, 0);
356 if (err < 0)
357 snd_printk(KERN_ERR IDENT " MPU401 PnP manual resources are invalid, using auto config\n");
358 err = pnp_activate_dev(pdev);
359 if (err < 0) {
360 printk(KERN_ERR IDENT " MPU401 PnP configure failed for WSS (out of resources?)\n");
361 mpu_port[dev] = SNDRV_AUTO_PORT;
362 mpu_irq[dev] = SNDRV_AUTO_IRQ;
363 } else {
364 mpu_port[dev] = pnp_port_start(pdev, 0);
365 if (mpu_irq[dev] >= 0 &&
366 pnp_irq_valid(pdev, 0) && pnp_irq(pdev, 0) >= 0) {
367 mpu_irq[dev] = pnp_irq(pdev, 0);
368 } else {
369 mpu_irq[dev] = -1; /* disable interrupt */
370 }
371 }
372 snd_printdd("isapnp MPU: port=0x%lx, irq=%i\n", mpu_port[dev], mpu_irq[dev]);
373 }
374 kfree(cfg);
375 return 0;
376}
377#endif /* CONFIG_PNP */
378
379static void snd_card_cs4236_free(snd_card_t *card)
380{
381 struct snd_card_cs4236 *acard = (struct snd_card_cs4236 *)card->private_data;
382
383 if (acard) {
384 if (acard->res_sb_port) {
385 release_resource(acard->res_sb_port);
386 kfree_nocheck(acard->res_sb_port);
387 }
388 }
389}
390
391static int __devinit snd_card_cs423x_probe(int dev, struct pnp_card_link *pcard,
392 const struct pnp_card_device_id *pid)
393{
394 snd_card_t *card;
395 struct snd_card_cs4236 *acard;
396 snd_pcm_t *pcm = NULL;
397 cs4231_t *chip;
398 opl3_t *opl3;
399 int err;
400
401#ifdef CONFIG_PNP
402 if (!isapnp[dev]) {
403#endif
404 if (port[dev] == SNDRV_AUTO_PORT) {
405 snd_printk("specify port\n");
406 return -EINVAL;
407 }
408 if (cport[dev] == SNDRV_AUTO_PORT) {
409 snd_printk("specify cport\n");
410 return -EINVAL;
411 }
412#ifdef CONFIG_PNP
413 }
414#endif
415 card = snd_card_new(index[dev], id[dev], THIS_MODULE,
416 sizeof(struct snd_card_cs4236));
417 if (card == NULL)
418 return -ENOMEM;
419 acard = (struct snd_card_cs4236 *)card->private_data;
420 card->private_free = snd_card_cs4236_free;
421#ifdef CONFIG_PNP
422 if (isapnp[dev]) {
423 if ((err = snd_card_cs4236_pnp(dev, acard, pcard, pid))<0) {
424 printk(KERN_ERR "isapnp detection failed and probing for " IDENT " is not supported\n");
425 snd_card_free(card);
426 return -ENXIO;
427 }
428 snd_card_set_dev(card, &pcard->card->dev);
429 }
430#endif
431 if (sb_port[dev] > 0 && sb_port[dev] != SNDRV_AUTO_PORT)
432 if ((acard->res_sb_port = request_region(sb_port[dev], 16, IDENT " SB")) == NULL) {
433 printk(KERN_ERR IDENT ": unable to register SB port at 0x%lx\n", sb_port[dev]);
434 snd_card_free(card);
435 return -ENOMEM;
436 }
437
438#ifdef CS4232
439 if ((err = snd_cs4231_create(card,
440 port[dev],
441 cport[dev],
442 irq[dev],
443 dma1[dev],
444 dma2[dev],
445 CS4231_HW_DETECT,
446 0,
447 &chip)) < 0) {
448 snd_card_free(card);
449 return err;
450 }
451 if ((err = snd_cs4231_pcm(chip, 0, &pcm)) < 0) {
452 snd_card_free(card);
453 return err;
454 }
455 if ((err = snd_cs4231_mixer(chip)) < 0) {
456 snd_card_free(card);
457 return err;
458 }
459
460#else /* CS4236 */
461 if ((err = snd_cs4236_create(card,
462 port[dev],
463 cport[dev],
464 irq[dev],
465 dma1[dev],
466 dma2[dev],
467 CS4231_HW_DETECT,
468 0,
469 &chip)) < 0) {
470 snd_card_free(card);
471 return err;
472 }
473 if ((err = snd_cs4236_pcm(chip, 0, &pcm)) < 0) {
474 snd_card_free(card);
475 return err;
476 }
477 if ((err = snd_cs4236_mixer(chip)) < 0) {
478 snd_card_free(card);
479 return err;
480 }
481#endif
482 strcpy(card->driver, pcm->name);
483 strcpy(card->shortname, pcm->name);
484 sprintf(card->longname, "%s at 0x%lx, irq %i, dma %i",
485 pcm->name,
486 chip->port,
487 irq[dev],
488 dma1[dev]);
489 if (dma2[dev] >= 0)
490 sprintf(card->longname + strlen(card->longname), "&%d", dma2[dev]);
491
492 if ((err = snd_cs4231_timer(chip, 0, NULL)) < 0) {
493 snd_card_free(card);
494 return err;
495 }
496
497 if (fm_port[dev] > 0 && fm_port[dev] != SNDRV_AUTO_PORT) {
498 if (snd_opl3_create(card,
499 fm_port[dev], fm_port[dev] + 2,
500 OPL3_HW_OPL3_CS, 0, &opl3) < 0) {
501 printk(KERN_ERR IDENT ": OPL3 not detected\n");
502 } else {
503 if ((err = snd_opl3_hwdep_new(opl3, 0, 1, NULL)) < 0) {
504 snd_card_free(card);
505 return err;
506 }
507 }
508 }
509
510 if (mpu_port[dev] > 0 && mpu_port[dev] != SNDRV_AUTO_PORT) {
511 if (mpu_irq[dev] == SNDRV_AUTO_IRQ)
512 mpu_irq[dev] = -1;
513 if (snd_mpu401_uart_new(card, 0, MPU401_HW_CS4232,
514 mpu_port[dev], 0,
515 mpu_irq[dev],
516 mpu_irq[dev] >= 0 ? SA_INTERRUPT : 0, NULL) < 0)
517 printk(KERN_ERR IDENT ": MPU401 not detected\n");
518 }
519 if ((err = snd_card_register(card)) < 0) {
520 snd_card_free(card);
521 return err;
522 }
523 if (pcard)
524 pnp_set_card_drvdata(pcard, card);
525 else
526 snd_cs4236_legacy[dev] = card;
527 return 0;
528}
529
530#ifdef CONFIG_PNP
531static int __devinit snd_cs423x_pnp_detect(struct pnp_card_link *card,
532 const struct pnp_card_device_id *id)
533{
534 static int dev;
535 int res;
536
537 for ( ; dev < SNDRV_CARDS; dev++) {
538 if (!enable[dev] || !isapnp[dev])
539 continue;
540 res = snd_card_cs423x_probe(dev, card, id);
541 if (res < 0)
542 return res;
543 dev++;
544 return 0;
545 }
546 return -ENODEV;
547}
548
549static void __devexit snd_cs423x_pnp_remove(struct pnp_card_link * pcard)
550{
551 snd_card_t *card = (snd_card_t *) pnp_get_card_drvdata(pcard);
552
553 snd_card_disconnect(card);
554 snd_card_free_in_thread(card);
555}
556
557static struct pnp_card_driver cs423x_pnpc_driver = {
558 .flags = PNP_DRIVER_RES_DISABLE,
559 .name = "cs423x",
560 .id_table = snd_cs423x_pnpids,
561 .probe = snd_cs423x_pnp_detect,
562 .remove = __devexit_p(snd_cs423x_pnp_remove),
563};
564#endif /* CONFIG_PNP */
565
566static int __init alsa_card_cs423x_init(void)
567{
568 int dev, cards = 0;
569
570 for (dev = 0; dev < SNDRV_CARDS; dev++) {
571 if (!enable[dev])
572 continue;
573#ifdef CONFIG_PNP
574 if (isapnp[dev])
575 continue;
576#endif
577 if (snd_card_cs423x_probe(dev, NULL, NULL) >= 0)
578 cards++;
579 }
580#ifdef CONFIG_PNP
581 cards += pnp_register_card_driver(&cs423x_pnpc_driver);
582#endif
583 if (!cards) {
584#ifdef CONFIG_PNP
585 pnp_unregister_card_driver(&cs423x_pnpc_driver);
586#endif
587#ifdef MODULE
588 printk(KERN_ERR IDENT " soundcard not found or device busy\n");
589#endif
590 return -ENODEV;
591 }
592 return 0;
593}
594
595static void __exit alsa_card_cs423x_exit(void)
596{
597 int idx;
598
599#ifdef CONFIG_PNP
600 /* PnP cards first */
601 pnp_unregister_card_driver(&cs423x_pnpc_driver);
602#endif
603 for (idx = 0; idx < SNDRV_CARDS; idx++)
604 snd_card_free(snd_cs4236_legacy[idx]);
605}
606
607module_init(alsa_card_cs423x_init)
608module_exit(alsa_card_cs423x_exit)
diff --git a/sound/isa/cs423x/cs4236_lib.c b/sound/isa/cs423x/cs4236_lib.c
new file mode 100644
index 000000000000..2128d4bdef41
--- /dev/null
+++ b/sound/isa/cs423x/cs4236_lib.c
@@ -0,0 +1,970 @@
1/*
2 * Copyright (c) by Jaroslav Kysela <perex@suse.cz>
3 * Routines for control of CS4235/4236B/4237B/4238B/4239 chips
4 *
5 * Note:
6 * -----
7 *
8 * Bugs:
9 * -----
10 *
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 2 of the License, or
14 * (at your option) any later version.
15 *
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
20 *
21 * You should have received a copy of the GNU General Public License
22 * along with this program; if not, write to the Free Software
23 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
24 *
25 */
26
27/*
28 * Indirect control registers (CS4236B+)
29 *
30 * C0
31 * D8: WSS reset (all chips)
32 *
33 * C1 (all chips except CS4236)
34 * D7-D5: version
35 * D4-D0: chip id
36 * 11101 - CS4235
37 * 01011 - CS4236B
38 * 01000 - CS4237B
39 * 01001 - CS4238B
40 * 11110 - CS4239
41 *
42 * C2
43 * D7-D4: 3D Space (CS4235,CS4237B,CS4238B,CS4239)
44 * D3-D0: 3D Center (CS4237B); 3D Volume (CS4238B)
45 *
46 * C3
47 * D7: 3D Enable (CS4237B)
48 * D6: 3D Mono Enable (CS4237B)
49 * D5: 3D Serial Output (CS4237B,CS4238B)
50 * D4: 3D Enable (CS4235,CS4238B,CS4239)
51 *
52 * C4
53 * D7: consumer serial port enable (CS4237B,CS4238B)
54 * D6: channels status block reset (CS4237B,CS4238B)
55 * D5: user bit in sub-frame of digital audio data (CS4237B,CS4238B)
56 * D4: validity bit bit in sub-frame of digital audio data (CS4237B,CS4238B)
57 *
58 * C5 lower channel status (digital serial data description) (CS4237B,CS4238B)
59 * D7-D6: first two bits of category code
60 * D5: lock
61 * D4-D3: pre-emphasis (0 = none, 1 = 50/15us)
62 * D2: copy/copyright (0 = copy inhibited)
63 * D1: 0 = digital audio / 1 = non-digital audio
64 *
65 * C6 upper channel status (digital serial data description) (CS4237B,CS4238B)
66 * D7-D6: sample frequency (0 = 44.1kHz)
67 * D5: generation status (0 = no indication, 1 = original/commercially precaptureed data)
68 * D4-D0: category code (upper bits)
69 *
70 * C7 reserved (must write 0)
71 *
72 * C8 wavetable control
73 * D7: volume control interrupt enable (CS4235,CS4239)
74 * D6: hardware volume control format (CS4235,CS4239)
75 * D3: wavetable serial port enable (all chips)
76 * D2: DSP serial port switch (all chips)
77 * D1: disable MCLK (all chips)
78 * D0: force BRESET low (all chips)
79 *
80 */
81
82#include <sound/driver.h>
83#include <asm/io.h>
84#include <linux/delay.h>
85#include <linux/init.h>
86#include <linux/time.h>
87#include <linux/wait.h>
88#include <sound/core.h>
89#include <sound/cs4231.h>
90#include <sound/asoundef.h>
91
92MODULE_AUTHOR("Jaroslav Kysela <perex@suse.cz>");
93MODULE_DESCRIPTION("Routines for control of CS4235/4236B/4237B/4238B/4239 chips");
94MODULE_LICENSE("GPL");
95
96/*
97 *
98 */
99
100static unsigned char snd_cs4236_ext_map[18] = {
101 /* CS4236_LEFT_LINE */ 0xff,
102 /* CS4236_RIGHT_LINE */ 0xff,
103 /* CS4236_LEFT_MIC */ 0xdf,
104 /* CS4236_RIGHT_MIC */ 0xdf,
105 /* CS4236_LEFT_MIX_CTRL */ 0xe0 | 0x18,
106 /* CS4236_RIGHT_MIX_CTRL */ 0xe0,
107 /* CS4236_LEFT_FM */ 0xbf,
108 /* CS4236_RIGHT_FM */ 0xbf,
109 /* CS4236_LEFT_DSP */ 0xbf,
110 /* CS4236_RIGHT_DSP */ 0xbf,
111 /* CS4236_RIGHT_LOOPBACK */ 0xbf,
112 /* CS4236_DAC_MUTE */ 0xe0,
113 /* CS4236_ADC_RATE */ 0x01, /* 48kHz */
114 /* CS4236_DAC_RATE */ 0x01, /* 48kHz */
115 /* CS4236_LEFT_MASTER */ 0xbf,
116 /* CS4236_RIGHT_MASTER */ 0xbf,
117 /* CS4236_LEFT_WAVE */ 0xbf,
118 /* CS4236_RIGHT_WAVE */ 0xbf
119};
120
121/*
122 *
123 */
124
125static void snd_cs4236_ctrl_out(cs4231_t *chip, unsigned char reg, unsigned char val)
126{
127 outb(reg, chip->cport + 3);
128 outb(chip->cimage[reg] = val, chip->cport + 4);
129}
130
131static unsigned char snd_cs4236_ctrl_in(cs4231_t *chip, unsigned char reg)
132{
133 outb(reg, chip->cport + 3);
134 return inb(chip->cport + 4);
135}
136
137/*
138 * PCM
139 */
140
141#define CLOCKS 8
142
143static ratnum_t clocks[CLOCKS] = {
144 { .num = 16934400, .den_min = 353, .den_max = 353, .den_step = 1 },
145 { .num = 16934400, .den_min = 529, .den_max = 529, .den_step = 1 },
146 { .num = 16934400, .den_min = 617, .den_max = 617, .den_step = 1 },
147 { .num = 16934400, .den_min = 1058, .den_max = 1058, .den_step = 1 },
148 { .num = 16934400, .den_min = 1764, .den_max = 1764, .den_step = 1 },
149 { .num = 16934400, .den_min = 2117, .den_max = 2117, .den_step = 1 },
150 { .num = 16934400, .den_min = 2558, .den_max = 2558, .den_step = 1 },
151 { .num = 16934400/16, .den_min = 21, .den_max = 192, .den_step = 1 }
152};
153
154static snd_pcm_hw_constraint_ratnums_t hw_constraints_clocks = {
155 .nrats = CLOCKS,
156 .rats = clocks,
157};
158
159static int snd_cs4236_xrate(snd_pcm_runtime_t *runtime)
160{
161 return snd_pcm_hw_constraint_ratnums(runtime, 0, SNDRV_PCM_HW_PARAM_RATE,
162 &hw_constraints_clocks);
163}
164
165static unsigned char divisor_to_rate_register(unsigned int divisor)
166{
167 switch (divisor) {
168 case 353: return 1;
169 case 529: return 2;
170 case 617: return 3;
171 case 1058: return 4;
172 case 1764: return 5;
173 case 2117: return 6;
174 case 2558: return 7;
175 default:
176 snd_runtime_check(divisor >= 21 && divisor <= 192, return 192);
177 return divisor;
178 }
179}
180
181static void snd_cs4236_playback_format(cs4231_t *chip, snd_pcm_hw_params_t *params, unsigned char pdfr)
182{
183 unsigned long flags;
184 unsigned char rate = divisor_to_rate_register(params->rate_den);
185
186 spin_lock_irqsave(&chip->reg_lock, flags);
187 /* set fast playback format change and clean playback FIFO */
188 snd_cs4231_out(chip, CS4231_ALT_FEATURE_1, chip->image[CS4231_ALT_FEATURE_1] | 0x10);
189 snd_cs4231_out(chip, CS4231_PLAYBK_FORMAT, pdfr & 0xf0);
190 snd_cs4231_out(chip, CS4231_ALT_FEATURE_1, chip->image[CS4231_ALT_FEATURE_1] & ~0x10);
191 snd_cs4236_ext_out(chip, CS4236_DAC_RATE, rate);
192 spin_unlock_irqrestore(&chip->reg_lock, flags);
193}
194
195static void snd_cs4236_capture_format(cs4231_t *chip, snd_pcm_hw_params_t *params, unsigned char cdfr)
196{
197 unsigned long flags;
198 unsigned char rate = divisor_to_rate_register(params->rate_den);
199
200 spin_lock_irqsave(&chip->reg_lock, flags);
201 /* set fast capture format change and clean capture FIFO */
202 snd_cs4231_out(chip, CS4231_ALT_FEATURE_1, chip->image[CS4231_ALT_FEATURE_1] | 0x20);
203 snd_cs4231_out(chip, CS4231_REC_FORMAT, cdfr & 0xf0);
204 snd_cs4231_out(chip, CS4231_ALT_FEATURE_1, chip->image[CS4231_ALT_FEATURE_1] & ~0x20);
205 snd_cs4236_ext_out(chip, CS4236_ADC_RATE, rate);
206 spin_unlock_irqrestore(&chip->reg_lock, flags);
207}
208
209#ifdef CONFIG_PM
210
211static void snd_cs4236_suspend(cs4231_t *chip)
212{
213 int reg;
214 unsigned long flags;
215
216 spin_lock_irqsave(&chip->reg_lock, flags);
217 for (reg = 0; reg < 32; reg++)
218 chip->image[reg] = snd_cs4231_in(chip, reg);
219 for (reg = 0; reg < 18; reg++)
220 chip->eimage[reg] = snd_cs4236_ext_in(chip, CS4236_I23VAL(reg));
221 for (reg = 2; reg < 9; reg++)
222 chip->cimage[reg] = snd_cs4236_ctrl_in(chip, reg);
223 spin_unlock_irqrestore(&chip->reg_lock, flags);
224}
225
226static void snd_cs4236_resume(cs4231_t *chip)
227{
228 int reg;
229 unsigned long flags;
230
231 snd_cs4231_mce_up(chip);
232 spin_lock_irqsave(&chip->reg_lock, flags);
233 for (reg = 0; reg < 32; reg++) {
234 switch (reg) {
235 case CS4236_EXT_REG:
236 case CS4231_VERSION:
237 case 27: /* why? CS4235 - master left */
238 case 29: /* why? CS4235 - master right */
239 break;
240 default:
241 snd_cs4231_out(chip, reg, chip->image[reg]);
242 break;
243 }
244 }
245 for (reg = 0; reg < 18; reg++)
246 snd_cs4236_ext_out(chip, CS4236_I23VAL(reg), chip->eimage[reg]);
247 for (reg = 2; reg < 9; reg++) {
248 switch (reg) {
249 case 7:
250 break;
251 default:
252 snd_cs4236_ctrl_out(chip, reg, chip->cimage[reg]);
253 }
254 }
255 spin_unlock_irqrestore(&chip->reg_lock, flags);
256 snd_cs4231_mce_down(chip);
257}
258
259#endif /* CONFIG_PM */
260
261int snd_cs4236_create(snd_card_t * card,
262 unsigned long port,
263 unsigned long cport,
264 int irq, int dma1, int dma2,
265 unsigned short hardware,
266 unsigned short hwshare,
267 cs4231_t ** rchip)
268{
269 cs4231_t *chip;
270 unsigned char ver1, ver2;
271 unsigned int reg;
272 int err;
273
274 *rchip = NULL;
275 if (hardware == CS4231_HW_DETECT)
276 hardware = CS4231_HW_DETECT3;
277 if (cport < 0x100) {
278 snd_printk("please, specify control port for CS4236+ chips\n");
279 return -ENODEV;
280 }
281 if ((err = snd_cs4231_create(card, port, cport, irq, dma1, dma2, hardware, hwshare, &chip)) < 0)
282 return err;
283
284 if (!(chip->hardware & CS4231_HW_CS4236B_MASK)) {
285 snd_printk("CS4236+: MODE3 and extended registers not available, hardware=0x%x\n",chip->hardware);
286 snd_device_free(card, chip);
287 return -ENODEV;
288 }
289#if 0
290 {
291 int idx;
292 for (idx = 0; idx < 8; idx++)
293 snd_printk("CD%i = 0x%x\n", idx, inb(chip->cport + idx));
294 for (idx = 0; idx < 9; idx++)
295 snd_printk("C%i = 0x%x\n", idx, snd_cs4236_ctrl_in(chip, idx));
296 }
297#endif
298 ver1 = snd_cs4236_ctrl_in(chip, 1);
299 ver2 = snd_cs4236_ext_in(chip, CS4236_VERSION);
300 snd_printdd("CS4236: [0x%lx] C1 (version) = 0x%x, ext = 0x%x\n", cport, ver1, ver2);
301 if (ver1 != ver2) {
302 snd_printk("CS4236+ chip detected, but control port 0x%lx is not valid\n", cport);
303 snd_device_free(card, chip);
304 return -ENODEV;
305 }
306 snd_cs4236_ctrl_out(chip, 0, 0x00);
307 snd_cs4236_ctrl_out(chip, 2, 0xff);
308 snd_cs4236_ctrl_out(chip, 3, 0x00);
309 snd_cs4236_ctrl_out(chip, 4, 0x80);
310 snd_cs4236_ctrl_out(chip, 5, ((IEC958_AES1_CON_PCM_CODER & 3) << 6) | IEC958_AES0_CON_EMPHASIS_NONE);
311 snd_cs4236_ctrl_out(chip, 6, IEC958_AES1_CON_PCM_CODER >> 2);
312 snd_cs4236_ctrl_out(chip, 7, 0x00);
313 /* 0x8c for C8 is valid for Turtle Beach Malibu - the IEC-958 output */
314 /* is working with this setup, other hardware should have */
315 /* different signal paths and this value should be selectable */
316 /* in the future */
317 snd_cs4236_ctrl_out(chip, 8, 0x8c);
318 chip->rate_constraint = snd_cs4236_xrate;
319 chip->set_playback_format = snd_cs4236_playback_format;
320 chip->set_capture_format = snd_cs4236_capture_format;
321#ifdef CONFIG_PM
322 chip->suspend = snd_cs4236_suspend;
323 chip->resume = snd_cs4236_resume;
324#endif
325
326 /* initialize extended registers */
327 for (reg = 0; reg < sizeof(snd_cs4236_ext_map); reg++)
328 snd_cs4236_ext_out(chip, CS4236_I23VAL(reg), snd_cs4236_ext_map[reg]);
329
330 /* initialize compatible but more featured registers */
331 snd_cs4231_out(chip, CS4231_LEFT_INPUT, 0x40);
332 snd_cs4231_out(chip, CS4231_RIGHT_INPUT, 0x40);
333 snd_cs4231_out(chip, CS4231_AUX1_LEFT_INPUT, 0xff);
334 snd_cs4231_out(chip, CS4231_AUX1_RIGHT_INPUT, 0xff);
335 snd_cs4231_out(chip, CS4231_AUX2_LEFT_INPUT, 0xdf);
336 snd_cs4231_out(chip, CS4231_AUX2_RIGHT_INPUT, 0xdf);
337 snd_cs4231_out(chip, CS4231_RIGHT_LINE_IN, 0xff);
338 snd_cs4231_out(chip, CS4231_LEFT_LINE_IN, 0xff);
339 snd_cs4231_out(chip, CS4231_RIGHT_LINE_IN, 0xff);
340 switch (chip->hardware) {
341 case CS4231_HW_CS4235:
342 case CS4231_HW_CS4239:
343 snd_cs4231_out(chip, CS4235_LEFT_MASTER, 0xff);
344 snd_cs4231_out(chip, CS4235_RIGHT_MASTER, 0xff);
345 break;
346 }
347
348 *rchip = chip;
349 return 0;
350}
351
352int snd_cs4236_pcm(cs4231_t *chip, int device, snd_pcm_t **rpcm)
353{
354 snd_pcm_t *pcm;
355 int err;
356
357 if ((err = snd_cs4231_pcm(chip, device, &pcm)) < 0)
358 return err;
359 pcm->info_flags &= ~SNDRV_PCM_INFO_JOINT_DUPLEX;
360 if (rpcm)
361 *rpcm = pcm;
362 return 0;
363}
364
365/*
366 * MIXER
367 */
368
369#define CS4236_SINGLE(xname, xindex, reg, shift, mask, invert) \
370{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xindex, \
371 .info = snd_cs4236_info_single, \
372 .get = snd_cs4236_get_single, .put = snd_cs4236_put_single, \
373 .private_value = reg | (shift << 8) | (mask << 16) | (invert << 24) }
374
375static int snd_cs4236_info_single(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
376{
377 int mask = (kcontrol->private_value >> 16) & 0xff;
378
379 uinfo->type = mask == 1 ? SNDRV_CTL_ELEM_TYPE_BOOLEAN : SNDRV_CTL_ELEM_TYPE_INTEGER;
380 uinfo->count = 1;
381 uinfo->value.integer.min = 0;
382 uinfo->value.integer.max = mask;
383 return 0;
384}
385
386static int snd_cs4236_get_single(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
387{
388 cs4231_t *chip = snd_kcontrol_chip(kcontrol);
389 unsigned long flags;
390 int reg = kcontrol->private_value & 0xff;
391 int shift = (kcontrol->private_value >> 8) & 0xff;
392 int mask = (kcontrol->private_value >> 16) & 0xff;
393 int invert = (kcontrol->private_value >> 24) & 0xff;
394
395 spin_lock_irqsave(&chip->reg_lock, flags);
396 ucontrol->value.integer.value[0] = (chip->eimage[CS4236_REG(reg)] >> shift) & mask;
397 spin_unlock_irqrestore(&chip->reg_lock, flags);
398 if (invert)
399 ucontrol->value.integer.value[0] = mask - ucontrol->value.integer.value[0];
400 return 0;
401}
402
403static int snd_cs4236_put_single(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
404{
405 cs4231_t *chip = snd_kcontrol_chip(kcontrol);
406 unsigned long flags;
407 int reg = kcontrol->private_value & 0xff;
408 int shift = (kcontrol->private_value >> 8) & 0xff;
409 int mask = (kcontrol->private_value >> 16) & 0xff;
410 int invert = (kcontrol->private_value >> 24) & 0xff;
411 int change;
412 unsigned short val;
413
414 val = (ucontrol->value.integer.value[0] & mask);
415 if (invert)
416 val = mask - val;
417 val <<= shift;
418 spin_lock_irqsave(&chip->reg_lock, flags);
419 val = (chip->eimage[CS4236_REG(reg)] & ~(mask << shift)) | val;
420 change = val != chip->eimage[CS4236_REG(reg)];
421 snd_cs4236_ext_out(chip, reg, val);
422 spin_unlock_irqrestore(&chip->reg_lock, flags);
423 return change;
424}
425
426#define CS4236_SINGLEC(xname, xindex, reg, shift, mask, invert) \
427{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xindex, \
428 .info = snd_cs4236_info_single, \
429 .get = snd_cs4236_get_singlec, .put = snd_cs4236_put_singlec, \
430 .private_value = reg | (shift << 8) | (mask << 16) | (invert << 24) }
431
432static int snd_cs4236_get_singlec(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
433{
434 cs4231_t *chip = snd_kcontrol_chip(kcontrol);
435 unsigned long flags;
436 int reg = kcontrol->private_value & 0xff;
437 int shift = (kcontrol->private_value >> 8) & 0xff;
438 int mask = (kcontrol->private_value >> 16) & 0xff;
439 int invert = (kcontrol->private_value >> 24) & 0xff;
440
441 spin_lock_irqsave(&chip->reg_lock, flags);
442 ucontrol->value.integer.value[0] = (chip->cimage[reg] >> shift) & mask;
443 spin_unlock_irqrestore(&chip->reg_lock, flags);
444 if (invert)
445 ucontrol->value.integer.value[0] = mask - ucontrol->value.integer.value[0];
446 return 0;
447}
448
449static int snd_cs4236_put_singlec(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
450{
451 cs4231_t *chip = snd_kcontrol_chip(kcontrol);
452 unsigned long flags;
453 int reg = kcontrol->private_value & 0xff;
454 int shift = (kcontrol->private_value >> 8) & 0xff;
455 int mask = (kcontrol->private_value >> 16) & 0xff;
456 int invert = (kcontrol->private_value >> 24) & 0xff;
457 int change;
458 unsigned short val;
459
460 val = (ucontrol->value.integer.value[0] & mask);
461 if (invert)
462 val = mask - val;
463 val <<= shift;
464 spin_lock_irqsave(&chip->reg_lock, flags);
465 val = (chip->cimage[reg] & ~(mask << shift)) | val;
466 change = val != chip->cimage[reg];
467 snd_cs4236_ctrl_out(chip, reg, val);
468 spin_unlock_irqrestore(&chip->reg_lock, flags);
469 return change;
470}
471
472#define CS4236_DOUBLE(xname, xindex, left_reg, right_reg, shift_left, shift_right, mask, invert) \
473{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xindex, \
474 .info = snd_cs4236_info_double, \
475 .get = snd_cs4236_get_double, .put = snd_cs4236_put_double, \
476 .private_value = left_reg | (right_reg << 8) | (shift_left << 16) | (shift_right << 19) | (mask << 24) | (invert << 22) }
477
478static int snd_cs4236_info_double(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
479{
480 int mask = (kcontrol->private_value >> 24) & 0xff;
481
482 uinfo->type = mask == 1 ? SNDRV_CTL_ELEM_TYPE_BOOLEAN : SNDRV_CTL_ELEM_TYPE_INTEGER;
483 uinfo->count = 2;
484 uinfo->value.integer.min = 0;
485 uinfo->value.integer.max = mask;
486 return 0;
487}
488
489static int snd_cs4236_get_double(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
490{
491 cs4231_t *chip = snd_kcontrol_chip(kcontrol);
492 unsigned long flags;
493 int left_reg = kcontrol->private_value & 0xff;
494 int right_reg = (kcontrol->private_value >> 8) & 0xff;
495 int shift_left = (kcontrol->private_value >> 16) & 0x07;
496 int shift_right = (kcontrol->private_value >> 19) & 0x07;
497 int mask = (kcontrol->private_value >> 24) & 0xff;
498 int invert = (kcontrol->private_value >> 22) & 1;
499
500 spin_lock_irqsave(&chip->reg_lock, flags);
501 ucontrol->value.integer.value[0] = (chip->eimage[CS4236_REG(left_reg)] >> shift_left) & mask;
502 ucontrol->value.integer.value[1] = (chip->eimage[CS4236_REG(right_reg)] >> shift_right) & mask;
503 spin_unlock_irqrestore(&chip->reg_lock, flags);
504 if (invert) {
505 ucontrol->value.integer.value[0] = mask - ucontrol->value.integer.value[0];
506 ucontrol->value.integer.value[1] = mask - ucontrol->value.integer.value[1];
507 }
508 return 0;
509}
510
511static int snd_cs4236_put_double(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
512{
513 cs4231_t *chip = snd_kcontrol_chip(kcontrol);
514 unsigned long flags;
515 int left_reg = kcontrol->private_value & 0xff;
516 int right_reg = (kcontrol->private_value >> 8) & 0xff;
517 int shift_left = (kcontrol->private_value >> 16) & 0x07;
518 int shift_right = (kcontrol->private_value >> 19) & 0x07;
519 int mask = (kcontrol->private_value >> 24) & 0xff;
520 int invert = (kcontrol->private_value >> 22) & 1;
521 int change;
522 unsigned short val1, val2;
523
524 val1 = ucontrol->value.integer.value[0] & mask;
525 val2 = ucontrol->value.integer.value[1] & mask;
526 if (invert) {
527 val1 = mask - val1;
528 val2 = mask - val2;
529 }
530 val1 <<= shift_left;
531 val2 <<= shift_right;
532 spin_lock_irqsave(&chip->reg_lock, flags);
533 if (left_reg != right_reg) {
534 val1 = (chip->eimage[CS4236_REG(left_reg)] & ~(mask << shift_left)) | val1;
535 val2 = (chip->eimage[CS4236_REG(right_reg)] & ~(mask << shift_right)) | val2;
536 change = val1 != chip->eimage[CS4236_REG(left_reg)] || val2 != chip->eimage[CS4236_REG(right_reg)];
537 snd_cs4236_ext_out(chip, left_reg, val1);
538 snd_cs4236_ext_out(chip, right_reg, val2);
539 } else {
540 val1 = (chip->eimage[CS4236_REG(left_reg)] & ~((mask << shift_left) | (mask << shift_right))) | val1 | val2;
541 change = val1 != chip->eimage[CS4236_REG(left_reg)];
542 snd_cs4236_ext_out(chip, left_reg, val1);
543 }
544 spin_unlock_irqrestore(&chip->reg_lock, flags);
545 return change;
546}
547
548#define CS4236_DOUBLE1(xname, xindex, left_reg, right_reg, shift_left, shift_right, mask, invert) \
549{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xindex, \
550 .info = snd_cs4236_info_double, \
551 .get = snd_cs4236_get_double1, .put = snd_cs4236_put_double1, \
552 .private_value = left_reg | (right_reg << 8) | (shift_left << 16) | (shift_right << 19) | (mask << 24) | (invert << 22) }
553
554static int snd_cs4236_get_double1(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
555{
556 cs4231_t *chip = snd_kcontrol_chip(kcontrol);
557 unsigned long flags;
558 int left_reg = kcontrol->private_value & 0xff;
559 int right_reg = (kcontrol->private_value >> 8) & 0xff;
560 int shift_left = (kcontrol->private_value >> 16) & 0x07;
561 int shift_right = (kcontrol->private_value >> 19) & 0x07;
562 int mask = (kcontrol->private_value >> 24) & 0xff;
563 int invert = (kcontrol->private_value >> 22) & 1;
564
565 spin_lock_irqsave(&chip->reg_lock, flags);
566 ucontrol->value.integer.value[0] = (chip->image[left_reg] >> shift_left) & mask;
567 ucontrol->value.integer.value[1] = (chip->eimage[CS4236_REG(right_reg)] >> shift_right) & mask;
568 spin_unlock_irqrestore(&chip->reg_lock, flags);
569 if (invert) {
570 ucontrol->value.integer.value[0] = mask - ucontrol->value.integer.value[0];
571 ucontrol->value.integer.value[1] = mask - ucontrol->value.integer.value[1];
572 }
573 return 0;
574}
575
576static int snd_cs4236_put_double1(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
577{
578 cs4231_t *chip = snd_kcontrol_chip(kcontrol);
579 unsigned long flags;
580 int left_reg = kcontrol->private_value & 0xff;
581 int right_reg = (kcontrol->private_value >> 8) & 0xff;
582 int shift_left = (kcontrol->private_value >> 16) & 0x07;
583 int shift_right = (kcontrol->private_value >> 19) & 0x07;
584 int mask = (kcontrol->private_value >> 24) & 0xff;
585 int invert = (kcontrol->private_value >> 22) & 1;
586 int change;
587 unsigned short val1, val2;
588
589 val1 = ucontrol->value.integer.value[0] & mask;
590 val2 = ucontrol->value.integer.value[1] & mask;
591 if (invert) {
592 val1 = mask - val1;
593 val2 = mask - val2;
594 }
595 val1 <<= shift_left;
596 val2 <<= shift_right;
597 spin_lock_irqsave(&chip->reg_lock, flags);
598 val1 = (chip->image[left_reg] & ~(mask << shift_left)) | val1;
599 val2 = (chip->eimage[CS4236_REG(right_reg)] & ~(mask << shift_right)) | val2;
600 change = val1 != chip->image[left_reg] || val2 != chip->eimage[CS4236_REG(right_reg)];
601 snd_cs4231_out(chip, left_reg, val1);
602 snd_cs4236_ext_out(chip, right_reg, val2);
603 spin_unlock_irqrestore(&chip->reg_lock, flags);
604 return change;
605}
606
607#define CS4236_MASTER_DIGITAL(xname, xindex) \
608{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xindex, \
609 .info = snd_cs4236_info_double, \
610 .get = snd_cs4236_get_master_digital, .put = snd_cs4236_put_master_digital, \
611 .private_value = 71 << 24 }
612
613static inline int snd_cs4236_mixer_master_digital_invert_volume(int vol)
614{
615 return (vol < 64) ? 63 - vol : 64 + (71 - vol);
616}
617
618static int snd_cs4236_get_master_digital(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
619{
620 cs4231_t *chip = snd_kcontrol_chip(kcontrol);
621 unsigned long flags;
622
623 spin_lock_irqsave(&chip->reg_lock, flags);
624 ucontrol->value.integer.value[0] = snd_cs4236_mixer_master_digital_invert_volume(chip->eimage[CS4236_REG(CS4236_LEFT_MASTER)] & 0x7f);
625 ucontrol->value.integer.value[1] = snd_cs4236_mixer_master_digital_invert_volume(chip->eimage[CS4236_REG(CS4236_RIGHT_MASTER)] & 0x7f);
626 spin_unlock_irqrestore(&chip->reg_lock, flags);
627 return 0;
628}
629
630static int snd_cs4236_put_master_digital(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
631{
632 cs4231_t *chip = snd_kcontrol_chip(kcontrol);
633 unsigned long flags;
634 int change;
635 unsigned short val1, val2;
636
637 val1 = snd_cs4236_mixer_master_digital_invert_volume(ucontrol->value.integer.value[0] & 0x7f);
638 val2 = snd_cs4236_mixer_master_digital_invert_volume(ucontrol->value.integer.value[1] & 0x7f);
639 spin_lock_irqsave(&chip->reg_lock, flags);
640 val1 = (chip->eimage[CS4236_REG(CS4236_LEFT_MASTER)] & ~0x7f) | val1;
641 val2 = (chip->eimage[CS4236_REG(CS4236_RIGHT_MASTER)] & ~0x7f) | val2;
642 change = val1 != chip->eimage[CS4236_REG(CS4236_LEFT_MASTER)] || val2 != chip->eimage[CS4236_REG(CS4236_RIGHT_MASTER)];
643 snd_cs4236_ext_out(chip, CS4236_LEFT_MASTER, val1);
644 snd_cs4236_ext_out(chip, CS4236_RIGHT_MASTER, val1);
645 spin_unlock_irqrestore(&chip->reg_lock, flags);
646 return change;
647}
648
649#define CS4235_OUTPUT_ACCU(xname, xindex) \
650{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xindex, \
651 .info = snd_cs4236_info_double, \
652 .get = snd_cs4235_get_output_accu, .put = snd_cs4235_put_output_accu, \
653 .private_value = 3 << 24 }
654
655static inline int snd_cs4235_mixer_output_accu_get_volume(int vol)
656{
657 switch ((vol >> 5) & 3) {
658 case 0: return 1;
659 case 1: return 3;
660 case 2: return 2;
661 case 3: return 0;
662 }
663 return 3;
664}
665
666static inline int snd_cs4235_mixer_output_accu_set_volume(int vol)
667{
668 switch (vol & 3) {
669 case 0: return 3 << 5;
670 case 1: return 0 << 5;
671 case 2: return 2 << 5;
672 case 3: return 1 << 5;
673 }
674 return 1 << 5;
675}
676
677static int snd_cs4235_get_output_accu(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
678{
679 cs4231_t *chip = snd_kcontrol_chip(kcontrol);
680 unsigned long flags;
681
682 spin_lock_irqsave(&chip->reg_lock, flags);
683 ucontrol->value.integer.value[0] = snd_cs4235_mixer_output_accu_get_volume(chip->image[CS4235_LEFT_MASTER]);
684 ucontrol->value.integer.value[1] = snd_cs4235_mixer_output_accu_get_volume(chip->image[CS4235_RIGHT_MASTER]);
685 spin_unlock_irqrestore(&chip->reg_lock, flags);
686 return 0;
687}
688
689static int snd_cs4235_put_output_accu(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
690{
691 cs4231_t *chip = snd_kcontrol_chip(kcontrol);
692 unsigned long flags;
693 int change;
694 unsigned short val1, val2;
695
696 val1 = snd_cs4235_mixer_output_accu_set_volume(ucontrol->value.integer.value[0]);
697 val2 = snd_cs4235_mixer_output_accu_set_volume(ucontrol->value.integer.value[1]);
698 spin_lock_irqsave(&chip->reg_lock, flags);
699 val1 = (chip->image[CS4235_LEFT_MASTER] & ~(3 << 5)) | val1;
700 val2 = (chip->image[CS4235_RIGHT_MASTER] & ~(3 << 5)) | val2;
701 change = val1 != chip->image[CS4235_LEFT_MASTER] || val2 != chip->image[CS4235_RIGHT_MASTER];
702 snd_cs4231_out(chip, CS4235_LEFT_MASTER, val1);
703 snd_cs4231_out(chip, CS4235_RIGHT_MASTER, val2);
704 spin_unlock_irqrestore(&chip->reg_lock, flags);
705 return change;
706}
707
708static snd_kcontrol_new_t snd_cs4236_controls[] = {
709
710CS4236_DOUBLE("Master Digital Playback Switch", 0, CS4236_LEFT_MASTER, CS4236_RIGHT_MASTER, 7, 7, 1, 1),
711CS4236_DOUBLE("Master Digital Capture Switch", 0, CS4236_DAC_MUTE, CS4236_DAC_MUTE, 7, 6, 1, 1),
712CS4236_MASTER_DIGITAL("Master Digital Volume", 0),
713
714CS4236_DOUBLE("Capture Boost Volume", 0, CS4236_LEFT_MIX_CTRL, CS4236_RIGHT_MIX_CTRL, 5, 5, 3, 1),
715
716CS4231_DOUBLE("PCM Playback Switch", 0, CS4231_LEFT_OUTPUT, CS4231_RIGHT_OUTPUT, 7, 7, 1, 1),
717CS4231_DOUBLE("PCM Playback Volume", 0, CS4231_LEFT_OUTPUT, CS4231_RIGHT_OUTPUT, 0, 0, 63, 1),
718
719CS4236_DOUBLE("DSP Playback Switch", 0, CS4236_LEFT_DSP, CS4236_RIGHT_DSP, 7, 7, 1, 1),
720CS4236_DOUBLE("DSP Playback Volume", 0, CS4236_LEFT_DSP, CS4236_RIGHT_DSP, 0, 0, 63, 1),
721
722CS4236_DOUBLE("FM Playback Switch", 0, CS4236_LEFT_FM, CS4236_RIGHT_FM, 7, 7, 1, 1),
723CS4236_DOUBLE("FM Playback Volume", 0, CS4236_LEFT_FM, CS4236_RIGHT_FM, 0, 0, 63, 1),
724
725CS4236_DOUBLE("Wavetable Playback Switch", 0, CS4236_LEFT_WAVE, CS4236_RIGHT_WAVE, 7, 7, 1, 1),
726CS4236_DOUBLE("Wavetable Playback Volume", 0, CS4236_LEFT_WAVE, CS4236_RIGHT_WAVE, 0, 0, 63, 1),
727
728CS4231_DOUBLE("Synth Playback Switch", 0, CS4231_LEFT_LINE_IN, CS4231_RIGHT_LINE_IN, 7, 7, 1, 1),
729CS4231_DOUBLE("Synth Volume", 0, CS4231_LEFT_LINE_IN, CS4231_RIGHT_LINE_IN, 0, 0, 31, 1),
730CS4231_DOUBLE("Synth Capture Switch", 0, CS4231_LEFT_LINE_IN, CS4231_RIGHT_LINE_IN, 6, 6, 1, 1),
731CS4231_DOUBLE("Synth Capture Bypass", 0, CS4231_LEFT_LINE_IN, CS4231_RIGHT_LINE_IN, 5, 5, 1, 1),
732
733CS4236_DOUBLE("Mic Playback Switch", 0, CS4236_LEFT_MIC, CS4236_RIGHT_MIC, 6, 6, 1, 1),
734CS4236_DOUBLE("Mic Capture Switch", 0, CS4236_LEFT_MIC, CS4236_RIGHT_MIC, 7, 7, 1, 1),
735CS4236_DOUBLE("Mic Volume", 0, CS4236_LEFT_MIC, CS4236_RIGHT_MIC, 0, 0, 31, 1),
736CS4236_DOUBLE("Mic Playback Boost", 0, CS4236_LEFT_MIC, CS4236_RIGHT_MIC, 5, 5, 1, 0),
737
738CS4231_DOUBLE("Line Playback Switch", 0, CS4231_AUX1_LEFT_INPUT, CS4231_AUX1_RIGHT_INPUT, 7, 7, 1, 1),
739CS4231_DOUBLE("Line Volume", 0, CS4231_AUX1_LEFT_INPUT, CS4231_AUX1_RIGHT_INPUT, 0, 0, 31, 1),
740CS4231_DOUBLE("Line Capture Switch", 0, CS4231_AUX1_LEFT_INPUT, CS4231_AUX1_RIGHT_INPUT, 6, 6, 1, 1),
741CS4231_DOUBLE("Line Capture Bypass", 0, CS4231_AUX1_LEFT_INPUT, CS4231_AUX1_RIGHT_INPUT, 5, 5, 1, 1),
742
743CS4231_DOUBLE("CD Playback Switch", 0, CS4231_AUX2_LEFT_INPUT, CS4231_AUX2_RIGHT_INPUT, 7, 7, 1, 1),
744CS4231_DOUBLE("CD Volume", 0, CS4231_AUX2_LEFT_INPUT, CS4231_AUX2_RIGHT_INPUT, 0, 0, 31, 1),
745CS4231_DOUBLE("CD Capture Switch", 0, CS4231_AUX2_LEFT_INPUT, CS4231_AUX2_RIGHT_INPUT, 6, 6, 1, 1),
746
747CS4236_DOUBLE1("Mono Output Playback Switch", 0, CS4231_MONO_CTRL, CS4236_RIGHT_MIX_CTRL, 6, 7, 1, 1),
748CS4236_DOUBLE1("Mono Playback Switch", 0, CS4231_MONO_CTRL, CS4236_LEFT_MIX_CTRL, 7, 7, 1, 1),
749CS4231_SINGLE("Mono Playback Volume", 0, CS4231_MONO_CTRL, 0, 15, 1),
750CS4231_SINGLE("Mono Playback Bypass", 0, CS4231_MONO_CTRL, 5, 1, 0),
751
752CS4231_DOUBLE("Capture Volume", 0, CS4231_LEFT_INPUT, CS4231_RIGHT_INPUT, 0, 0, 15, 0),
753CS4231_DOUBLE("Analog Loopback Capture Switch", 0, CS4231_LEFT_INPUT, CS4231_RIGHT_INPUT, 7, 7, 1, 0),
754
755CS4231_SINGLE("Digital Loopback Playback Switch", 0, CS4231_LOOPBACK, 0, 1, 0),
756CS4236_DOUBLE1("Digital Loopback Playback Volume", 0, CS4231_LOOPBACK, CS4236_RIGHT_LOOPBACK, 2, 0, 63, 1)
757};
758
759static snd_kcontrol_new_t snd_cs4235_controls[] = {
760
761CS4231_DOUBLE("Master Switch", 0, CS4235_LEFT_MASTER, CS4235_RIGHT_MASTER, 7, 7, 1, 1),
762CS4231_DOUBLE("Master Volume", 0, CS4235_LEFT_MASTER, CS4235_RIGHT_MASTER, 0, 0, 31, 1),
763
764CS4235_OUTPUT_ACCU("Playback Volume", 0),
765
766CS4236_DOUBLE("Master Digital Playback Switch", 0, CS4236_LEFT_MASTER, CS4236_RIGHT_MASTER, 7, 7, 1, 1),
767CS4236_DOUBLE("Master Digital Capture Switch", 0, CS4236_DAC_MUTE, CS4236_DAC_MUTE, 7, 6, 1, 1),
768CS4236_MASTER_DIGITAL("Master Digital Volume", 0),
769
770CS4231_DOUBLE("Master Digital Playback Switch", 1, CS4231_LEFT_LINE_IN, CS4231_RIGHT_LINE_IN, 7, 7, 1, 1),
771CS4231_DOUBLE("Master Digital Capture Switch", 1, CS4231_LEFT_LINE_IN, CS4231_RIGHT_LINE_IN, 6, 6, 1, 1),
772CS4231_DOUBLE("Master Digital Volume", 1, CS4231_LEFT_LINE_IN, CS4231_RIGHT_LINE_IN, 0, 0, 31, 1),
773
774CS4236_DOUBLE("Capture Volume", 0, CS4236_LEFT_MIX_CTRL, CS4236_RIGHT_MIX_CTRL, 5, 5, 3, 1),
775
776CS4231_DOUBLE("PCM Switch", 0, CS4231_LEFT_OUTPUT, CS4231_RIGHT_OUTPUT, 7, 7, 1, 1),
777CS4231_DOUBLE("PCM Volume", 0, CS4231_LEFT_OUTPUT, CS4231_RIGHT_OUTPUT, 0, 0, 63, 1),
778
779CS4236_DOUBLE("DSP Switch", 0, CS4236_LEFT_DSP, CS4236_RIGHT_DSP, 7, 7, 1, 1),
780
781CS4236_DOUBLE("FM Switch", 0, CS4236_LEFT_FM, CS4236_RIGHT_FM, 7, 7, 1, 1),
782
783CS4236_DOUBLE("Wavetable Switch", 0, CS4236_LEFT_WAVE, CS4236_RIGHT_WAVE, 7, 7, 1, 1),
784
785CS4236_DOUBLE("Mic Capture Switch", 0, CS4236_LEFT_MIC, CS4236_RIGHT_MIC, 7, 7, 1, 1),
786CS4236_DOUBLE("Mic Playback Switch", 0, CS4236_LEFT_MIC, CS4236_RIGHT_MIC, 6, 6, 1, 1),
787CS4236_SINGLE("Mic Volume", 0, CS4236_LEFT_MIC, 0, 31, 1),
788CS4236_SINGLE("Mic Playback Boost", 0, CS4236_LEFT_MIC, 5, 1, 0),
789
790CS4231_DOUBLE("Aux Playback Switch", 0, CS4231_AUX1_LEFT_INPUT, CS4231_AUX1_RIGHT_INPUT, 7, 7, 1, 1),
791CS4231_DOUBLE("Aux Capture Switch", 0, CS4231_AUX1_LEFT_INPUT, CS4231_AUX1_RIGHT_INPUT, 6, 6, 1, 1),
792CS4231_DOUBLE("Aux Volume", 0, CS4231_AUX1_LEFT_INPUT, CS4231_AUX1_RIGHT_INPUT, 0, 0, 31, 1),
793
794CS4231_DOUBLE("Aux Playback Switch", 1, CS4231_AUX2_LEFT_INPUT, CS4231_AUX2_RIGHT_INPUT, 7, 7, 1, 1),
795CS4231_DOUBLE("Aux Capture Switch", 1, CS4231_AUX2_LEFT_INPUT, CS4231_AUX2_RIGHT_INPUT, 6, 6, 1, 1),
796CS4231_DOUBLE("Aux Volume", 1, CS4231_AUX2_LEFT_INPUT, CS4231_AUX2_RIGHT_INPUT, 0, 0, 31, 1),
797
798CS4236_DOUBLE1("Master Mono Switch", 0, CS4231_MONO_CTRL, CS4236_RIGHT_MIX_CTRL, 6, 7, 1, 1),
799
800CS4236_DOUBLE1("Mono Switch", 0, CS4231_MONO_CTRL, CS4236_LEFT_MIX_CTRL, 7, 7, 1, 1),
801CS4231_SINGLE("Mono Volume", 0, CS4231_MONO_CTRL, 0, 15, 1),
802
803CS4231_DOUBLE("Analog Loopback Switch", 0, CS4231_LEFT_INPUT, CS4231_RIGHT_INPUT, 7, 7, 1, 0),
804};
805
806#define CS4236_IEC958_ENABLE(xname, xindex) \
807{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xindex, \
808 .info = snd_cs4236_info_single, \
809 .get = snd_cs4236_get_iec958_switch, .put = snd_cs4236_put_iec958_switch, \
810 .private_value = 1 << 16 }
811
812static int snd_cs4236_get_iec958_switch(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
813{
814 cs4231_t *chip = snd_kcontrol_chip(kcontrol);
815 unsigned long flags;
816
817 spin_lock_irqsave(&chip->reg_lock, flags);
818 ucontrol->value.integer.value[0] = chip->image[CS4231_ALT_FEATURE_1] & 0x02 ? 1 : 0;
819#if 0
820 printk("get valid: ALT = 0x%x, C3 = 0x%x, C4 = 0x%x, C5 = 0x%x, C6 = 0x%x, C8 = 0x%x\n",
821 snd_cs4231_in(chip, CS4231_ALT_FEATURE_1),
822 snd_cs4236_ctrl_in(chip, 3),
823 snd_cs4236_ctrl_in(chip, 4),
824 snd_cs4236_ctrl_in(chip, 5),
825 snd_cs4236_ctrl_in(chip, 6),
826 snd_cs4236_ctrl_in(chip, 8));
827#endif
828 spin_unlock_irqrestore(&chip->reg_lock, flags);
829 return 0;
830}
831
832static int snd_cs4236_put_iec958_switch(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
833{
834 cs4231_t *chip = snd_kcontrol_chip(kcontrol);
835 unsigned long flags;
836 int change;
837 unsigned short enable, val;
838
839 enable = ucontrol->value.integer.value[0] & 1;
840
841 down(&chip->mce_mutex);
842 snd_cs4231_mce_up(chip);
843 spin_lock_irqsave(&chip->reg_lock, flags);
844 val = (chip->image[CS4231_ALT_FEATURE_1] & ~0x0e) | (0<<2) | (enable << 1);
845 change = val != chip->image[CS4231_ALT_FEATURE_1];
846 snd_cs4231_out(chip, CS4231_ALT_FEATURE_1, val);
847 val = snd_cs4236_ctrl_in(chip, 4) | 0xc0;
848 snd_cs4236_ctrl_out(chip, 4, val);
849 udelay(100);
850 val &= ~0x40;
851 snd_cs4236_ctrl_out(chip, 4, val);
852 spin_unlock_irqrestore(&chip->reg_lock, flags);
853 snd_cs4231_mce_down(chip);
854 up(&chip->mce_mutex);
855
856#if 0
857 printk("set valid: ALT = 0x%x, C3 = 0x%x, C4 = 0x%x, C5 = 0x%x, C6 = 0x%x, C8 = 0x%x\n",
858 snd_cs4231_in(chip, CS4231_ALT_FEATURE_1),
859 snd_cs4236_ctrl_in(chip, 3),
860 snd_cs4236_ctrl_in(chip, 4),
861 snd_cs4236_ctrl_in(chip, 5),
862 snd_cs4236_ctrl_in(chip, 6),
863 snd_cs4236_ctrl_in(chip, 8));
864#endif
865 return change;
866}
867
868static snd_kcontrol_new_t snd_cs4236_iec958_controls[] = {
869CS4236_IEC958_ENABLE("IEC958 Output Enable", 0),
870CS4236_SINGLEC("IEC958 Output Validity", 0, 4, 4, 1, 0),
871CS4236_SINGLEC("IEC958 Output User", 0, 4, 5, 1, 0),
872CS4236_SINGLEC("IEC958 Output CSBR", 0, 4, 6, 1, 0),
873CS4236_SINGLEC("IEC958 Output Channel Status Low", 0, 5, 1, 127, 0),
874CS4236_SINGLEC("IEC958 Output Channel Status High", 0, 6, 0, 255, 0)
875};
876
877static snd_kcontrol_new_t snd_cs4236_3d_controls_cs4235[] = {
878CS4236_SINGLEC("3D Control - Switch", 0, 3, 4, 1, 0),
879CS4236_SINGLEC("3D Control - Space", 0, 2, 4, 15, 1)
880};
881
882static snd_kcontrol_new_t snd_cs4236_3d_controls_cs4237[] = {
883CS4236_SINGLEC("3D Control - Switch", 0, 3, 7, 1, 0),
884CS4236_SINGLEC("3D Control - Space", 0, 2, 4, 15, 1),
885CS4236_SINGLEC("3D Control - Center", 0, 2, 0, 15, 1),
886CS4236_SINGLEC("3D Control - Mono", 0, 3, 6, 1, 0),
887CS4236_SINGLEC("3D Control - IEC958", 0, 3, 5, 1, 0)
888};
889
890static snd_kcontrol_new_t snd_cs4236_3d_controls_cs4238[] = {
891CS4236_SINGLEC("3D Control - Switch", 0, 3, 4, 1, 0),
892CS4236_SINGLEC("3D Control - Space", 0, 2, 4, 15, 1),
893CS4236_SINGLEC("3D Control - Volume", 0, 2, 0, 15, 1),
894CS4236_SINGLEC("3D Control - IEC958", 0, 3, 5, 1, 0)
895};
896
897int snd_cs4236_mixer(cs4231_t *chip)
898{
899 snd_card_t *card;
900 unsigned int idx, count;
901 int err;
902 snd_kcontrol_new_t *kcontrol;
903
904 snd_assert(chip != NULL && chip->card != NULL, return -EINVAL);
905 card = chip->card;
906 strcpy(card->mixername, snd_cs4231_chip_id(chip));
907
908 if (chip->hardware == CS4231_HW_CS4235 ||
909 chip->hardware == CS4231_HW_CS4239) {
910 for (idx = 0; idx < ARRAY_SIZE(snd_cs4235_controls); idx++) {
911 if ((err = snd_ctl_add(card, snd_ctl_new1(&snd_cs4235_controls[idx], chip))) < 0)
912 return err;
913 }
914 } else {
915 for (idx = 0; idx < ARRAY_SIZE(snd_cs4236_controls); idx++) {
916 if ((err = snd_ctl_add(card, snd_ctl_new1(&snd_cs4236_controls[idx], chip))) < 0)
917 return err;
918 }
919 }
920 switch (chip->hardware) {
921 case CS4231_HW_CS4235:
922 case CS4231_HW_CS4239:
923 count = ARRAY_SIZE(snd_cs4236_3d_controls_cs4235);
924 kcontrol = snd_cs4236_3d_controls_cs4235;
925 break;
926 case CS4231_HW_CS4237B:
927 count = ARRAY_SIZE(snd_cs4236_3d_controls_cs4237);
928 kcontrol = snd_cs4236_3d_controls_cs4237;
929 break;
930 case CS4231_HW_CS4238B:
931 count = ARRAY_SIZE(snd_cs4236_3d_controls_cs4238);
932 kcontrol = snd_cs4236_3d_controls_cs4238;
933 break;
934 default:
935 count = 0;
936 kcontrol = NULL;
937 }
938 for (idx = 0; idx < count; idx++, kcontrol++) {
939 if ((err = snd_ctl_add(card, snd_ctl_new1(kcontrol, chip))) < 0)
940 return err;
941 }
942 if (chip->hardware == CS4231_HW_CS4237B ||
943 chip->hardware == CS4231_HW_CS4238B) {
944 for (idx = 0; idx < ARRAY_SIZE(snd_cs4236_iec958_controls); idx++) {
945 if ((err = snd_ctl_add(card, snd_ctl_new1(&snd_cs4236_iec958_controls[idx], chip))) < 0)
946 return err;
947 }
948 }
949 return 0;
950}
951
952EXPORT_SYMBOL(snd_cs4236_create);
953EXPORT_SYMBOL(snd_cs4236_pcm);
954EXPORT_SYMBOL(snd_cs4236_mixer);
955
956/*
957 * INIT part
958 */
959
960static int __init alsa_cs4236_init(void)
961{
962 return 0;
963}
964
965static void __exit alsa_cs4236_exit(void)
966{
967}
968
969module_init(alsa_cs4236_init)
970module_exit(alsa_cs4236_exit)
diff --git a/sound/isa/dt019x.c b/sound/isa/dt019x.c
new file mode 100644
index 000000000000..db7c3397b323
--- /dev/null
+++ b/sound/isa/dt019x.c
@@ -0,0 +1,327 @@
1
2/*
3 dt019x.c - driver for Diamond Technologies DT-0197H based soundcards.
4 Copyright (C) 1999, 2002 by Massimo Piccioni <dafastidio@libero.it>
5
6 Generalised for soundcards based on DT-0196 and ALS-007 chips
7 by Jonathan Woithe <jwoithe@physics.adelaide.edu.au>: June 2002.
8
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 2 of the License, or
12 (at your option) any later version.
13
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
18
19 You should have received a copy of the GNU General Public License
20 along with this program; if not, write to the Free Software
21 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22*/
23
24#include <sound/driver.h>
25#include <linux/init.h>
26#include <linux/sched.h>
27#include <linux/wait.h>
28#include <linux/pnp.h>
29#include <linux/moduleparam.h>
30#include <sound/core.h>
31#include <sound/initval.h>
32#include <sound/mpu401.h>
33#include <sound/opl3.h>
34#include <sound/sb.h>
35
36#define PFX "dt019x: "
37
38MODULE_AUTHOR("Massimo Piccioni <dafastidio@libero.it>");
39MODULE_DESCRIPTION("Diamond Technologies DT-019X / Avance Logic ALS-007");
40MODULE_LICENSE("GPL");
41MODULE_SUPPORTED_DEVICE("{{Diamond Technologies DT-019X},"
42 "{Avance Logic ALS-007}}");
43
44static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-MAX */
45static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* ID for this card */
46static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE; /* Enable this card */
47static long port[SNDRV_CARDS] = SNDRV_DEFAULT_PORT; /* PnP setup */
48static long mpu_port[SNDRV_CARDS] = SNDRV_DEFAULT_PORT; /* PnP setup */
49static long fm_port[SNDRV_CARDS] = SNDRV_DEFAULT_PORT; /* PnP setup */
50static int irq[SNDRV_CARDS] = SNDRV_DEFAULT_IRQ; /* PnP setup */
51static int mpu_irq[SNDRV_CARDS] = SNDRV_DEFAULT_IRQ; /* PnP setup */
52static int dma8[SNDRV_CARDS] = SNDRV_DEFAULT_DMA; /* PnP setup */
53
54module_param_array(index, int, NULL, 0444);
55MODULE_PARM_DESC(index, "Index value for DT-019X based soundcard.");
56module_param_array(id, charp, NULL, 0444);
57MODULE_PARM_DESC(id, "ID string for DT-019X based soundcard.");
58module_param_array(enable, bool, NULL, 0444);
59MODULE_PARM_DESC(enable, "Enable DT-019X based soundcard.");
60module_param_array(port, long, NULL, 0444);
61MODULE_PARM_DESC(port, "Port # for dt019x driver.");
62module_param_array(mpu_port, long, NULL, 0444);
63MODULE_PARM_DESC(mpu_port, "MPU-401 port # for dt019x driver.");
64module_param_array(fm_port, long, NULL, 0444);
65MODULE_PARM_DESC(fm_port, "FM port # for dt019x driver.");
66module_param_array(irq, int, NULL, 0444);
67MODULE_PARM_DESC(irq, "IRQ # for dt019x driver.");
68module_param_array(mpu_irq, int, NULL, 0444);
69MODULE_PARM_DESC(mpu_irq, "MPU-401 IRQ # for dt019x driver.");
70module_param_array(dma8, int, NULL, 0444);
71MODULE_PARM_DESC(dma8, "8-bit DMA # for dt019x driver.");
72
73struct snd_card_dt019x {
74 struct pnp_dev *dev;
75 struct pnp_dev *devmpu;
76 struct pnp_dev *devopl;
77};
78
79static struct pnp_card_device_id snd_dt019x_pnpids[] = {
80 /* DT197A30 */
81 { .id = "RWB1688", .devs = { { "@@@0001" }, { "@X@0001" }, { "@H@0001" }, } },
82 /* DT0196 / ALS-007 */
83 { .id = "ALS0007", .devs = { { "@@@0001" }, { "@X@0001" }, { "@H@0001" }, } },
84 { .id = "", }
85};
86
87MODULE_DEVICE_TABLE(pnp_card, snd_dt019x_pnpids);
88
89
90#define DRIVER_NAME "snd-card-dt019x"
91
92
93static int __devinit snd_card_dt019x_pnp(int dev, struct snd_card_dt019x *acard,
94 struct pnp_card_link *card,
95 const struct pnp_card_device_id *pid)
96{
97 struct pnp_dev *pdev;
98 struct pnp_resource_table * cfg = kmalloc(sizeof(struct pnp_resource_table), GFP_KERNEL);
99 int err;
100
101 if (!cfg)
102 return -ENOMEM;
103
104 acard->dev = pnp_request_card_device(card, pid->devs[0].id, NULL);
105 if (acard->dev == NULL) {
106 kfree (cfg);
107 return -ENODEV;
108 }
109 acard->devmpu = pnp_request_card_device(card, pid->devs[1].id, NULL);
110 acard->devopl = pnp_request_card_device(card, pid->devs[2].id, NULL);
111
112 pdev = acard->dev;
113 pnp_init_resource_table(cfg);
114
115 if (port[dev] != SNDRV_AUTO_PORT)
116 pnp_resource_change(&cfg->port_resource[0], port[dev], 16);
117 if (dma8[dev] != SNDRV_AUTO_DMA)
118 pnp_resource_change(&cfg->dma_resource[0], dma8[dev], 1);
119 if (irq[dev] != SNDRV_AUTO_IRQ)
120 pnp_resource_change(&cfg->irq_resource[0], irq[dev], 1);
121
122 if ((pnp_manual_config_dev(pdev, cfg, 0)) < 0)
123 snd_printk(KERN_ERR PFX "DT-019X AUDIO the requested resources are invalid, using auto config\n");
124 err = pnp_activate_dev(pdev);
125 if (err < 0) {
126 snd_printk(KERN_ERR PFX "DT-019X AUDIO pnp configure failure\n");
127 kfree(cfg);
128 return err;
129 }
130
131 port[dev] = pnp_port_start(pdev, 0);
132 dma8[dev] = pnp_dma(pdev, 0);
133 irq[dev] = pnp_irq(pdev, 0);
134 snd_printdd("dt019x: found audio interface: port=0x%lx, irq=0x%x, dma=0x%x\n",
135 port[dev],irq[dev],dma8[dev]);
136
137 pdev = acard->devmpu;
138
139 if (pdev != NULL) {
140 pnp_init_resource_table(cfg);
141 if (mpu_port[dev] != SNDRV_AUTO_PORT)
142 pnp_resource_change(&cfg->port_resource[0], mpu_port[dev], 2);
143 if (mpu_irq[dev] != SNDRV_AUTO_IRQ)
144 pnp_resource_change(&cfg->irq_resource[0], mpu_irq[dev], 1);
145 if ((pnp_manual_config_dev(pdev, cfg, 0)) < 0)
146 snd_printk(KERN_ERR PFX "DT-019X MPU401 the requested resources are invalid, using auto config\n");
147 err = pnp_activate_dev(pdev);
148 if (err < 0) {
149 pnp_release_card_device(pdev);
150 snd_printk(KERN_ERR PFX "DT-019X MPU401 pnp configure failure, skipping\n");
151 goto __mpu_error;
152 }
153 mpu_port[dev] = pnp_port_start(pdev, 0);
154 mpu_irq[dev] = pnp_irq(pdev, 0);
155 snd_printdd("dt019x: found MPU-401: port=0x%lx, irq=0x%x\n",
156 mpu_port[dev],mpu_irq[dev]);
157 } else {
158 __mpu_error:
159 acard->devmpu = NULL;
160 mpu_port[dev] = -1;
161 }
162
163 pdev = acard->devopl;
164 if (pdev != NULL) {
165 pnp_init_resource_table(cfg);
166 if (fm_port[dev] != SNDRV_AUTO_PORT)
167 pnp_resource_change(&cfg->port_resource[0], fm_port[dev], 4);
168 if ((pnp_manual_config_dev(pdev, cfg, 0)) < 0)
169 snd_printk(KERN_ERR PFX "DT-019X OPL3 the requested resources are invalid, using auto config\n");
170 err = pnp_activate_dev(pdev);
171 if (err < 0) {
172 pnp_release_card_device(pdev);
173 snd_printk(KERN_ERR PFX "DT-019X OPL3 pnp configure failure, skipping\n");
174 goto __fm_error;
175 }
176 fm_port[dev] = pnp_port_start(pdev, 0);
177 snd_printdd("dt019x: found OPL3 synth: port=0x%lx\n",fm_port[dev]);
178 } else {
179 __fm_error:
180 acard->devopl = NULL;
181 fm_port[dev] = -1;
182 }
183
184 kfree(cfg);
185 return 0;
186}
187
188static int __devinit snd_card_dt019x_probe(int dev, struct pnp_card_link *pcard, const struct pnp_card_device_id *pid)
189{
190 int error;
191 sb_t *chip;
192 snd_card_t *card;
193 struct snd_card_dt019x *acard;
194 opl3_t *opl3;
195
196 if ((card = snd_card_new(index[dev], id[dev], THIS_MODULE,
197 sizeof(struct snd_card_dt019x))) == NULL)
198 return -ENOMEM;
199 acard = (struct snd_card_dt019x *)card->private_data;
200
201 snd_card_set_dev(card, &pcard->card->dev);
202 if ((error = snd_card_dt019x_pnp(dev, acard, pcard, pid))) {
203 snd_card_free(card);
204 return error;
205 }
206
207 if ((error = snd_sbdsp_create(card, port[dev],
208 irq[dev],
209 snd_sb16dsp_interrupt,
210 dma8[dev],
211 -1,
212 SB_HW_DT019X,
213 &chip)) < 0) {
214 snd_card_free(card);
215 return error;
216 }
217
218 strcpy(card->driver, "DT-019X");
219 strcpy(card->shortname, "Diamond Tech. DT-019X");
220 sprintf(card->longname, "%s, %s at 0x%lx, irq %d, dma %d",
221 card->shortname, chip->name, chip->port,
222 irq[dev], dma8[dev]);
223
224 if ((error = snd_sb16dsp_pcm(chip, 0, NULL)) < 0) {
225 snd_card_free(card);
226 return error;
227 }
228 if ((error = snd_sbmixer_new(chip)) < 0) {
229 snd_card_free(card);
230 return error;
231 }
232
233 if (mpu_port[dev] > 0 && mpu_port[dev] != SNDRV_AUTO_PORT) {
234 if (mpu_irq[dev] == SNDRV_AUTO_IRQ)
235 mpu_irq[dev] = -1;
236 if (snd_mpu401_uart_new(card, 0,
237/* MPU401_HW_SB,*/
238 MPU401_HW_MPU401,
239 mpu_port[dev], 0,
240 mpu_irq[dev],
241 mpu_irq[dev] >= 0 ? SA_INTERRUPT : 0,
242 NULL) < 0)
243 snd_printk(KERN_ERR PFX "no MPU-401 device at 0x%lx ?\n", mpu_port[dev]);
244 }
245
246 if (fm_port[dev] > 0 && fm_port[dev] != SNDRV_AUTO_PORT) {
247 if (snd_opl3_create(card,
248 fm_port[dev],
249 fm_port[dev] + 2,
250 OPL3_HW_AUTO, 0, &opl3) < 0) {
251 snd_printk(KERN_ERR PFX "no OPL device at 0x%lx-0x%lx ?\n",
252 fm_port[dev], fm_port[dev] + 2);
253 } else {
254 if ((error = snd_opl3_timer_new(opl3, 0, 1)) < 0) {
255 snd_card_free(card);
256 return error;
257 }
258 if ((error = snd_opl3_hwdep_new(opl3, 0, 1, NULL)) < 0) {
259 snd_card_free(card);
260 return error;
261 }
262 }
263 }
264
265 if ((error = snd_card_register(card)) < 0) {
266 snd_card_free(card);
267 return error;
268 }
269 pnp_set_card_drvdata(pcard, card);
270 return 0;
271}
272
273static int __devinit snd_dt019x_pnp_probe(struct pnp_card_link *card,
274 const struct pnp_card_device_id *pid)
275{
276 static int dev;
277 int res;
278
279 for ( ; dev < SNDRV_CARDS; dev++) {
280 if (!enable[dev])
281 continue;
282 res = snd_card_dt019x_probe(dev, card, pid);
283 if (res < 0)
284 return res;
285 dev++;
286 return 0;
287 }
288 return -ENODEV;
289}
290
291static void __devexit snd_dt019x_pnp_remove(struct pnp_card_link * pcard)
292{
293 snd_card_t *card = (snd_card_t *) pnp_get_card_drvdata(pcard);
294 snd_card_disconnect(card);
295 snd_card_free_in_thread(card);
296}
297
298static struct pnp_card_driver dt019x_pnpc_driver = {
299 .flags = PNP_DRIVER_RES_DISABLE,
300 .name = "dt019x",
301 .id_table = snd_dt019x_pnpids,
302 .probe = snd_dt019x_pnp_probe,
303 .remove = __devexit_p(snd_dt019x_pnp_remove),
304};
305
306static int __init alsa_card_dt019x_init(void)
307{
308 int cards = 0;
309
310 cards += pnp_register_card_driver(&dt019x_pnpc_driver);
311
312#ifdef MODULE
313 if (!cards) {
314 pnp_unregister_card_driver(&dt019x_pnpc_driver);
315 snd_printk(KERN_ERR "no DT-019X / ALS-007 based soundcards found\n");
316 }
317#endif
318 return cards ? 0 : -ENODEV;
319}
320
321static void __exit alsa_card_dt019x_exit(void)
322{
323 pnp_unregister_card_driver(&dt019x_pnpc_driver);
324}
325
326module_init(alsa_card_dt019x_init)
327module_exit(alsa_card_dt019x_exit)
diff --git a/sound/isa/es1688/Makefile b/sound/isa/es1688/Makefile
new file mode 100644
index 000000000000..501c8bf903af
--- /dev/null
+++ b/sound/isa/es1688/Makefile
@@ -0,0 +1,11 @@
1#
2# Makefile for ALSA
3# Copyright (c) 2001 by Jaroslav Kysela <perex@suse.cz>
4#
5
6snd-es1688-lib-objs := es1688_lib.o
7snd-es1688-objs := es1688.o
8
9# Toplevel Module Dependency
10obj-$(CONFIG_SND_ES1688) += snd-es1688.o snd-es1688-lib.o
11obj-$(CONFIG_SND_GUSEXTREME) += snd-es1688-lib.o
diff --git a/sound/isa/es1688/es1688.c b/sound/isa/es1688/es1688.c
new file mode 100644
index 000000000000..c5eaec087b46
--- /dev/null
+++ b/sound/isa/es1688/es1688.c
@@ -0,0 +1,204 @@
1/*
2 * Driver for generic ESS AudioDrive ESx688 soundcards
3 * Copyright (c) by Jaroslav Kysela <perex@suse.cz>
4 *
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 *
20 */
21
22#include <sound/driver.h>
23#include <asm/dma.h>
24#include <linux/init.h>
25#include <linux/time.h>
26#include <linux/wait.h>
27#include <linux/moduleparam.h>
28#include <sound/core.h>
29#include <sound/es1688.h>
30#include <sound/mpu401.h>
31#include <sound/opl3.h>
32#define SNDRV_LEGACY_AUTO_PROBE
33#define SNDRV_LEGACY_FIND_FREE_IRQ
34#define SNDRV_LEGACY_FIND_FREE_DMA
35#include <sound/initval.h>
36
37MODULE_AUTHOR("Jaroslav Kysela <perex@suse.cz>");
38MODULE_DESCRIPTION("ESS ESx688 AudioDrive");
39MODULE_LICENSE("GPL");
40MODULE_SUPPORTED_DEVICE("{{ESS,ES688 PnP AudioDrive,pnp:ESS0100},"
41 "{ESS,ES1688 PnP AudioDrive,pnp:ESS0102},"
42 "{ESS,ES688 AudioDrive,pnp:ESS6881},"
43 "{ESS,ES1688 AudioDrive,pnp:ESS1681}}");
44
45static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-MAX */
46static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* ID for this card */
47static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE; /* Enable this card */
48static long port[SNDRV_CARDS] = SNDRV_DEFAULT_PORT; /* 0x220,0x240,0x260 */
49static long mpu_port[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = -1};
50static int irq[SNDRV_CARDS] = SNDRV_DEFAULT_IRQ; /* 5,7,9,10 */
51static int mpu_irq[SNDRV_CARDS] = SNDRV_DEFAULT_IRQ; /* 5,7,9,10 */
52static int dma8[SNDRV_CARDS] = SNDRV_DEFAULT_DMA; /* 0,1,3 */
53
54module_param_array(index, int, NULL, 0444);
55MODULE_PARM_DESC(index, "Index value for ESx688 soundcard.");
56module_param_array(id, charp, NULL, 0444);
57MODULE_PARM_DESC(id, "ID string for ESx688 soundcard.");
58module_param_array(enable, bool, NULL, 0444);
59MODULE_PARM_DESC(enable, "Enable ESx688 soundcard.");
60module_param_array(port, long, NULL, 0444);
61MODULE_PARM_DESC(port, "Port # for ESx688 driver.");
62module_param_array(mpu_port, long, NULL, 0444);
63MODULE_PARM_DESC(mpu_port, "MPU-401 port # for ESx688 driver.");
64module_param_array(irq, int, NULL, 0444);
65MODULE_PARM_DESC(irq, "IRQ # for ESx688 driver.");
66module_param_array(mpu_irq, int, NULL, 0444);
67MODULE_PARM_DESC(mpu_irq, "MPU-401 IRQ # for ESx688 driver.");
68module_param_array(dma8, int, NULL, 0444);
69MODULE_PARM_DESC(dma8, "8-bit DMA # for ESx688 driver.");
70
71static snd_card_t *snd_audiodrive_cards[SNDRV_CARDS] = SNDRV_DEFAULT_PTR;
72
73
74static int __init snd_audiodrive_probe(int dev)
75{
76 static int possible_irqs[] = {5, 9, 10, 7, -1};
77 static int possible_dmas[] = {1, 3, 0, -1};
78 int xirq, xdma, xmpu_irq;
79 snd_card_t *card;
80 es1688_t *chip;
81 opl3_t *opl3;
82 snd_pcm_t *pcm;
83 int err;
84
85 card = snd_card_new(index[dev], id[dev], THIS_MODULE, 0);
86 if (card == NULL)
87 return -ENOMEM;
88
89 xirq = irq[dev];
90 if (xirq == SNDRV_AUTO_IRQ) {
91 if ((xirq = snd_legacy_find_free_irq(possible_irqs)) < 0) {
92 snd_card_free(card);
93 snd_printk("unable to find a free IRQ\n");
94 return -EBUSY;
95 }
96 }
97 xmpu_irq = mpu_irq[dev];
98 xdma = dma8[dev];
99 if (xdma == SNDRV_AUTO_DMA) {
100 if ((xdma = snd_legacy_find_free_dma(possible_dmas)) < 0) {
101 snd_card_free(card);
102 snd_printk("unable to find a free DMA\n");
103 return -EBUSY;
104 }
105 }
106
107 if ((err = snd_es1688_create(card, port[dev], mpu_port[dev],
108 xirq, xmpu_irq, xdma,
109 ES1688_HW_AUTO, &chip)) < 0) {
110 snd_card_free(card);
111 return err;
112 }
113 if ((err = snd_es1688_pcm(chip, 0, &pcm)) < 0) {
114 snd_card_free(card);
115 return err;
116 }
117 if ((err = snd_es1688_mixer(chip)) < 0) {
118 snd_card_free(card);
119 return err;
120 }
121
122 strcpy(card->driver, "ES1688");
123 strcpy(card->shortname, pcm->name);
124 sprintf(card->longname, "%s at 0x%lx, irq %i, dma %i", pcm->name, chip->port, xirq, xdma);
125
126 if ((snd_opl3_create(card, chip->port, chip->port + 2, OPL3_HW_OPL3, 0, &opl3)) < 0) {
127 printk(KERN_ERR "es1688: opl3 not detected at 0x%lx\n", chip->port);
128 } else {
129 if ((err = snd_opl3_hwdep_new(opl3, 0, 1, NULL)) < 0) {
130 snd_card_free(card);
131 return err;
132 }
133 }
134
135 if (xmpu_irq >= 0 && xmpu_irq != SNDRV_AUTO_IRQ && chip->mpu_port > 0) {
136 if ((err = snd_mpu401_uart_new(card, 0, MPU401_HW_ES1688,
137 chip->mpu_port, 0,
138 xmpu_irq,
139 SA_INTERRUPT,
140 NULL)) < 0) {
141 snd_card_free(card);
142 return err;
143 }
144 }
145 if ((err = snd_card_register(card)) < 0) {
146 snd_card_free(card);
147 return err;
148 }
149 snd_audiodrive_cards[dev] = card;
150 return 0;
151
152}
153
154static int __init snd_audiodrive_legacy_auto_probe(unsigned long xport)
155{
156 static int dev;
157 int res;
158
159 for ( ; dev < SNDRV_CARDS; dev++) {
160 if (!enable[dev] || port[dev] != SNDRV_AUTO_PORT)
161 continue;
162 port[dev] = xport;
163 res = snd_audiodrive_probe(dev);
164 if (res < 0)
165 port[dev] = SNDRV_AUTO_PORT;
166 return res;
167 }
168 return -ENODEV;
169}
170
171static int __init alsa_card_es1688_init(void)
172{
173 static unsigned long possible_ports[] = {0x220, 0x240, 0x260, -1};
174 int dev, cards = 0, i;
175
176 for (dev = cards = 0; dev < SNDRV_CARDS && enable[dev]; dev++) {
177 if (port[dev] == SNDRV_AUTO_PORT)
178 continue;
179 if (snd_audiodrive_probe(dev) >= 0)
180 cards++;
181 }
182 i = snd_legacy_auto_probe(possible_ports, snd_audiodrive_legacy_auto_probe);
183 if (i > 0)
184 cards += i;
185
186 if (!cards) {
187#ifdef MODULE
188 printk(KERN_ERR "ESS AudioDrive ES1688 soundcard not found or device busy\n");
189#endif
190 return -ENODEV;
191 }
192 return 0;
193}
194
195static void __exit alsa_card_es1688_exit(void)
196{
197 int idx;
198
199 for (idx = 0; idx < SNDRV_CARDS; idx++)
200 snd_card_free(snd_audiodrive_cards[idx]);
201}
202
203module_init(alsa_card_es1688_init)
204module_exit(alsa_card_es1688_exit)
diff --git a/sound/isa/es1688/es1688_lib.c b/sound/isa/es1688/es1688_lib.c
new file mode 100644
index 000000000000..17f68d07d9b2
--- /dev/null
+++ b/sound/isa/es1688/es1688_lib.c
@@ -0,0 +1,1062 @@
1/*
2 * Copyright (c) by Jaroslav Kysela <perex@suse.cz>
3 * Routines for control of ESS ES1688/688/488 chip
4 *
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 *
20 */
21
22#include <sound/driver.h>
23#include <linux/init.h>
24#include <linux/interrupt.h>
25#include <linux/delay.h>
26#include <linux/slab.h>
27#include <linux/ioport.h>
28#include <sound/core.h>
29#include <sound/es1688.h>
30#include <sound/initval.h>
31
32#include <asm/io.h>
33#include <asm/dma.h>
34
35MODULE_AUTHOR("Jaroslav Kysela <perex@suse.cz>");
36MODULE_DESCRIPTION("ESS ESx688 lowlevel module");
37MODULE_LICENSE("GPL");
38
39static int snd_es1688_dsp_command(es1688_t *chip, unsigned char val)
40{
41 int i;
42
43 for (i = 10000; i; i--)
44 if ((inb(ES1688P(chip, STATUS)) & 0x80) == 0) {
45 outb(val, ES1688P(chip, COMMAND));
46 return 1;
47 }
48#ifdef CONFIG_SND_DEBUG
49 printk("snd_es1688_dsp_command: timeout (0x%x)\n", val);
50#endif
51 return 0;
52}
53
54static int snd_es1688_dsp_get_byte(es1688_t *chip)
55{
56 int i;
57
58 for (i = 1000; i; i--)
59 if (inb(ES1688P(chip, DATA_AVAIL)) & 0x80)
60 return inb(ES1688P(chip, READ));
61 snd_printd("es1688 get byte failed: 0x%lx = 0x%x!!!\n", ES1688P(chip, DATA_AVAIL), inb(ES1688P(chip, DATA_AVAIL)));
62 return -ENODEV;
63}
64
65static int snd_es1688_write(es1688_t *chip,
66 unsigned char reg, unsigned char data)
67{
68 if (!snd_es1688_dsp_command(chip, reg))
69 return 0;
70 return snd_es1688_dsp_command(chip, data);
71}
72
73static int snd_es1688_read(es1688_t *chip, unsigned char reg)
74{
75 /* Read a byte from an extended mode register of ES1688 */
76 if (!snd_es1688_dsp_command(chip, 0xc0))
77 return -1;
78 if (!snd_es1688_dsp_command(chip, reg))
79 return -1;
80 return snd_es1688_dsp_get_byte(chip);
81}
82
83void snd_es1688_mixer_write(es1688_t *chip,
84 unsigned char reg, unsigned char data)
85{
86 outb(reg, ES1688P(chip, MIXER_ADDR));
87 udelay(10);
88 outb(data, ES1688P(chip, MIXER_DATA));
89 udelay(10);
90}
91
92static unsigned char snd_es1688_mixer_read(es1688_t *chip, unsigned char reg)
93{
94 unsigned char result;
95
96 outb(reg, ES1688P(chip, MIXER_ADDR));
97 udelay(10);
98 result = inb(ES1688P(chip, MIXER_DATA));
99 udelay(10);
100 return result;
101}
102
103static int snd_es1688_reset(es1688_t *chip)
104{
105 int i;
106
107 outb(3, ES1688P(chip, RESET)); /* valid only for ESS chips, SB -> 1 */
108 udelay(10);
109 outb(0, ES1688P(chip, RESET));
110 udelay(30);
111 for (i = 0; i < 1000 && !(inb(ES1688P(chip, DATA_AVAIL)) & 0x80); i++);
112 if (inb(ES1688P(chip, READ)) != 0xaa) {
113 snd_printd("ess_reset at 0x%lx: failed!!!\n", chip->port);
114 return -ENODEV;
115 }
116 snd_es1688_dsp_command(chip, 0xc6); /* enable extended mode */
117 return 0;
118}
119
120static int snd_es1688_probe(es1688_t *chip)
121{
122 unsigned long flags;
123 unsigned short major, minor, hw;
124 int i;
125
126 /*
127 * initialization sequence
128 */
129
130 spin_lock_irqsave(&chip->reg_lock, flags); /* Some ESS1688 cards need this */
131 inb(ES1688P(chip, ENABLE1)); /* ENABLE1 */
132 inb(ES1688P(chip, ENABLE1)); /* ENABLE1 */
133 inb(ES1688P(chip, ENABLE1)); /* ENABLE1 */
134 inb(ES1688P(chip, ENABLE2)); /* ENABLE2 */
135 inb(ES1688P(chip, ENABLE1)); /* ENABLE1 */
136 inb(ES1688P(chip, ENABLE2)); /* ENABLE2 */
137 inb(ES1688P(chip, ENABLE1)); /* ENABLE1 */
138 inb(ES1688P(chip, ENABLE1)); /* ENABLE1 */
139 inb(ES1688P(chip, ENABLE2)); /* ENABLE2 */
140 inb(ES1688P(chip, ENABLE1)); /* ENABLE1 */
141 inb(ES1688P(chip, ENABLE0)); /* ENABLE0 */
142
143 if (snd_es1688_reset(chip) < 0) {
144 snd_printdd("ESS: [0x%lx] reset failed... 0x%x\n", chip->port, inb(ES1688P(chip, READ)));
145 spin_unlock_irqrestore(&chip->reg_lock, flags);
146 return -ENODEV;
147 }
148 snd_es1688_dsp_command(chip, 0xe7); /* return identification */
149
150 for (i = 1000, major = minor = 0; i; i--) {
151 if (inb(ES1688P(chip, DATA_AVAIL)) & 0x80) {
152 if (major == 0) {
153 major = inb(ES1688P(chip, READ));
154 } else {
155 minor = inb(ES1688P(chip, READ));
156 }
157 }
158 }
159
160 spin_unlock_irqrestore(&chip->reg_lock, flags);
161
162 snd_printdd("ESS: [0x%lx] found.. major = 0x%x, minor = 0x%x\n", chip->port, major, minor);
163
164 chip->version = (major << 8) | minor;
165 if (!chip->version)
166 return -ENODEV; /* probably SB */
167
168 hw = ES1688_HW_AUTO;
169 switch (chip->version & 0xfff0) {
170 case 0x4880:
171 snd_printk("[0x%lx] ESS: AudioDrive ES488 detected, but driver is in another place\n", chip->port);
172 return -ENODEV;
173 case 0x6880:
174 hw = (chip->version & 0x0f) >= 8 ? ES1688_HW_1688 : ES1688_HW_688;
175 break;
176 default:
177 snd_printk("[0x%lx] ESS: unknown AudioDrive chip with version 0x%x (Jazz16 soundcard?)\n", chip->port, chip->version);
178 return -ENODEV;
179 }
180
181 spin_lock_irqsave(&chip->reg_lock, flags);
182 snd_es1688_write(chip, 0xb1, 0x10); /* disable IRQ */
183 snd_es1688_write(chip, 0xb2, 0x00); /* disable DMA */
184 spin_unlock_irqrestore(&chip->reg_lock, flags);
185
186 /* enable joystick, but disable OPL3 */
187 spin_lock_irqsave(&chip->mixer_lock, flags);
188 snd_es1688_mixer_write(chip, 0x40, 0x01);
189 spin_unlock_irqrestore(&chip->mixer_lock, flags);
190
191 return 0;
192}
193
194static int snd_es1688_init(es1688_t * chip, int enable)
195{
196 static int irqs[16] = {-1, -1, 0, -1, -1, 1, -1, 2, -1, 0, 3, -1, -1, -1, -1, -1};
197 unsigned long flags;
198 int cfg, irq_bits, dma, dma_bits, tmp, tmp1;
199
200 /* ok.. setup MPU-401 port and joystick and OPL3 */
201 cfg = 0x01; /* enable joystick, but disable OPL3 */
202 if (enable && chip->mpu_port >= 0x300 && chip->mpu_irq > 0 && chip->hardware != ES1688_HW_688) {
203 tmp = (chip->mpu_port & 0x0f0) >> 4;
204 if (tmp <= 3) {
205 switch (chip->mpu_irq) {
206 case 9:
207 tmp1 = 4;
208 break;
209 case 5:
210 tmp1 = 5;
211 break;
212 case 7:
213 tmp1 = 6;
214 break;
215 case 10:
216 tmp1 = 7;
217 break;
218 default:
219 tmp1 = 0;
220 }
221 if (tmp1) {
222 cfg |= (tmp << 3) | (tmp1 << 5);
223 }
224 }
225 }
226#if 0
227 snd_printk("mpu cfg = 0x%x\n", cfg);
228#endif
229 spin_lock_irqsave(&chip->reg_lock, flags);
230 snd_es1688_mixer_write(chip, 0x40, cfg);
231 spin_unlock_irqrestore(&chip->reg_lock, flags);
232 /* --- */
233 spin_lock_irqsave(&chip->reg_lock, flags);
234 snd_es1688_read(chip, 0xb1);
235 snd_es1688_read(chip, 0xb2);
236 spin_unlock_irqrestore(&chip->reg_lock, flags);
237 if (enable) {
238 cfg = 0xf0; /* enable only DMA counter interrupt */
239 irq_bits = irqs[chip->irq & 0x0f];
240 if (irq_bits < 0) {
241 snd_printk("[0x%lx] ESS: bad IRQ %d for ES1688 chip!!\n", chip->port, chip->irq);
242#if 0
243 irq_bits = 0;
244 cfg = 0x10;
245#endif
246 return -EINVAL;
247 }
248 spin_lock_irqsave(&chip->reg_lock, flags);
249 snd_es1688_write(chip, 0xb1, cfg | (irq_bits << 2));
250 spin_unlock_irqrestore(&chip->reg_lock, flags);
251 cfg = 0xf0; /* extended mode DMA enable */
252 dma = chip->dma8;
253 if (dma > 3 || dma == 2) {
254 snd_printk("[0x%lx] ESS: bad DMA channel %d for ES1688 chip!!\n", chip->port, dma);
255#if 0
256 dma_bits = 0;
257 cfg = 0x00; /* disable all DMA */
258#endif
259 return -EINVAL;
260 } else {
261 dma_bits = dma;
262 if (dma != 3)
263 dma_bits++;
264 }
265 spin_lock_irqsave(&chip->reg_lock, flags);
266 snd_es1688_write(chip, 0xb2, cfg | (dma_bits << 2));
267 spin_unlock_irqrestore(&chip->reg_lock, flags);
268 } else {
269 spin_lock_irqsave(&chip->reg_lock, flags);
270 snd_es1688_write(chip, 0xb1, 0x10); /* disable IRQ */
271 snd_es1688_write(chip, 0xb2, 0x00); /* disable DMA */
272 spin_unlock_irqrestore(&chip->reg_lock, flags);
273 }
274 spin_lock_irqsave(&chip->reg_lock, flags);
275 snd_es1688_read(chip, 0xb1);
276 snd_es1688_read(chip, 0xb2);
277 snd_es1688_reset(chip);
278 spin_unlock_irqrestore(&chip->reg_lock, flags);
279 return 0;
280}
281
282/*
283
284 */
285
286static ratnum_t clocks[2] = {
287 {
288 .num = 795444,
289 .den_min = 1,
290 .den_max = 128,
291 .den_step = 1,
292 },
293 {
294 .num = 397722,
295 .den_min = 1,
296 .den_max = 128,
297 .den_step = 1,
298 }
299};
300
301static snd_pcm_hw_constraint_ratnums_t hw_constraints_clocks = {
302 .nrats = 2,
303 .rats = clocks,
304};
305
306static void snd_es1688_set_rate(es1688_t *chip, snd_pcm_substream_t *substream)
307{
308 snd_pcm_runtime_t *runtime = substream->runtime;
309 unsigned int bits, divider;
310
311 if (runtime->rate_num == clocks[0].num)
312 bits = 256 - runtime->rate_den;
313 else
314 bits = 128 - runtime->rate_den;
315 /* set filter register */
316 divider = 256 - 7160000*20/(8*82*runtime->rate);
317 /* write result to hardware */
318 snd_es1688_write(chip, 0xa1, bits);
319 snd_es1688_write(chip, 0xa2, divider);
320}
321
322static int snd_es1688_ioctl(snd_pcm_substream_t * substream,
323 unsigned int cmd, void *arg)
324{
325 return snd_pcm_lib_ioctl(substream, cmd, arg);
326}
327
328static int snd_es1688_trigger(es1688_t *chip, int cmd, unsigned char value)
329{
330 int val;
331
332 if (cmd == SNDRV_PCM_TRIGGER_STOP) {
333 value = 0x00;
334 } else if (cmd != SNDRV_PCM_TRIGGER_START) {
335 return -EINVAL;
336 }
337 spin_lock(&chip->reg_lock);
338 chip->trigger_value = value;
339 val = snd_es1688_read(chip, 0xb8);
340 if ((val < 0) || (val & 0x0f) == value) {
341 spin_unlock(&chip->reg_lock);
342 return -EINVAL; /* something is wrong */
343 }
344#if 0
345 printk("trigger: val = 0x%x, value = 0x%x\n", val, value);
346 printk("trigger: pointer = 0x%x\n", snd_dma_pointer(chip->dma8, chip->dma_size));
347#endif
348 snd_es1688_write(chip, 0xb8, (val & 0xf0) | value);
349 spin_unlock(&chip->reg_lock);
350 return 0;
351}
352
353static int snd_es1688_hw_params(snd_pcm_substream_t * substream,
354 snd_pcm_hw_params_t * hw_params)
355{
356 return snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(hw_params));
357}
358
359static int snd_es1688_hw_free(snd_pcm_substream_t * substream)
360{
361 return snd_pcm_lib_free_pages(substream);
362}
363
364static int snd_es1688_playback_prepare(snd_pcm_substream_t * substream)
365{
366 unsigned long flags;
367 es1688_t *chip = snd_pcm_substream_chip(substream);
368 snd_pcm_runtime_t *runtime = substream->runtime;
369 unsigned int size = snd_pcm_lib_buffer_bytes(substream);
370 unsigned int count = snd_pcm_lib_period_bytes(substream);
371
372 chip->dma_size = size;
373 spin_lock_irqsave(&chip->reg_lock, flags);
374 snd_es1688_reset(chip);
375 snd_es1688_set_rate(chip, substream);
376 snd_es1688_write(chip, 0xb8, 4); /* auto init DMA mode */
377 snd_es1688_write(chip, 0xa8, (snd_es1688_read(chip, 0xa8) & ~0x03) | (3 - runtime->channels));
378 snd_es1688_write(chip, 0xb9, 2); /* demand mode (4 bytes/request) */
379 if (runtime->channels == 1) {
380 if (snd_pcm_format_width(runtime->format) == 8) {
381 /* 8. bit mono */
382 snd_es1688_write(chip, 0xb6, 0x80);
383 snd_es1688_write(chip, 0xb7, 0x51);
384 snd_es1688_write(chip, 0xb7, 0xd0);
385 } else {
386 /* 16. bit mono */
387 snd_es1688_write(chip, 0xb6, 0x00);
388 snd_es1688_write(chip, 0xb7, 0x71);
389 snd_es1688_write(chip, 0xb7, 0xf4);
390 }
391 } else {
392 if (snd_pcm_format_width(runtime->format) == 8) {
393 /* 8. bit stereo */
394 snd_es1688_write(chip, 0xb6, 0x80);
395 snd_es1688_write(chip, 0xb7, 0x51);
396 snd_es1688_write(chip, 0xb7, 0x98);
397 } else {
398 /* 16. bit stereo */
399 snd_es1688_write(chip, 0xb6, 0x00);
400 snd_es1688_write(chip, 0xb7, 0x71);
401 snd_es1688_write(chip, 0xb7, 0xbc);
402 }
403 }
404 snd_es1688_write(chip, 0xb1, (snd_es1688_read(chip, 0xb1) & 0x0f) | 0x50);
405 snd_es1688_write(chip, 0xb2, (snd_es1688_read(chip, 0xb2) & 0x0f) | 0x50);
406 snd_es1688_dsp_command(chip, ES1688_DSP_CMD_SPKON);
407 spin_unlock_irqrestore(&chip->reg_lock, flags);
408 /* --- */
409 count = -count;
410 snd_dma_program(chip->dma8, runtime->dma_addr, size, DMA_MODE_WRITE | DMA_AUTOINIT);
411 spin_lock_irqsave(&chip->reg_lock, flags);
412 snd_es1688_write(chip, 0xa4, (unsigned char) count);
413 snd_es1688_write(chip, 0xa5, (unsigned char) (count >> 8));
414 spin_unlock_irqrestore(&chip->reg_lock, flags);
415 return 0;
416}
417
418static int snd_es1688_playback_trigger(snd_pcm_substream_t * substream,
419 int cmd)
420{
421 es1688_t *chip = snd_pcm_substream_chip(substream);
422 return snd_es1688_trigger(chip, cmd, 0x05);
423}
424
425static int snd_es1688_capture_prepare(snd_pcm_substream_t * substream)
426{
427 unsigned long flags;
428 es1688_t *chip = snd_pcm_substream_chip(substream);
429 snd_pcm_runtime_t *runtime = substream->runtime;
430 unsigned int size = snd_pcm_lib_buffer_bytes(substream);
431 unsigned int count = snd_pcm_lib_period_bytes(substream);
432
433 chip->dma_size = size;
434 spin_lock_irqsave(&chip->reg_lock, flags);
435 snd_es1688_reset(chip);
436 snd_es1688_set_rate(chip, substream);
437 snd_es1688_dsp_command(chip, ES1688_DSP_CMD_SPKOFF);
438 snd_es1688_write(chip, 0xb8, 0x0e); /* auto init DMA mode */
439 snd_es1688_write(chip, 0xa8, (snd_es1688_read(chip, 0xa8) & ~0x03) | (3 - runtime->channels));
440 snd_es1688_write(chip, 0xb9, 2); /* demand mode (4 bytes/request) */
441 if (runtime->channels == 1) {
442 if (snd_pcm_format_width(runtime->format) == 8) {
443 /* 8. bit mono */
444 snd_es1688_write(chip, 0xb7, 0x51);
445 snd_es1688_write(chip, 0xb7, 0xd0);
446 } else {
447 /* 16. bit mono */
448 snd_es1688_write(chip, 0xb7, 0x71);
449 snd_es1688_write(chip, 0xb7, 0xf4);
450 }
451 } else {
452 if (snd_pcm_format_width(runtime->format) == 8) {
453 /* 8. bit stereo */
454 snd_es1688_write(chip, 0xb7, 0x51);
455 snd_es1688_write(chip, 0xb7, 0x98);
456 } else {
457 /* 16. bit stereo */
458 snd_es1688_write(chip, 0xb7, 0x71);
459 snd_es1688_write(chip, 0xb7, 0xbc);
460 }
461 }
462 snd_es1688_write(chip, 0xb1, (snd_es1688_read(chip, 0xb1) & 0x0f) | 0x50);
463 snd_es1688_write(chip, 0xb2, (snd_es1688_read(chip, 0xb2) & 0x0f) | 0x50);
464 spin_unlock_irqrestore(&chip->reg_lock, flags);
465 /* --- */
466 count = -count;
467 snd_dma_program(chip->dma8, runtime->dma_addr, size, DMA_MODE_READ | DMA_AUTOINIT);
468 spin_lock_irqsave(&chip->reg_lock, flags);
469 snd_es1688_write(chip, 0xa4, (unsigned char) count);
470 snd_es1688_write(chip, 0xa5, (unsigned char) (count >> 8));
471 spin_unlock_irqrestore(&chip->reg_lock, flags);
472 return 0;
473}
474
475static int snd_es1688_capture_trigger(snd_pcm_substream_t * substream,
476 int cmd)
477{
478 es1688_t *chip = snd_pcm_substream_chip(substream);
479 return snd_es1688_trigger(chip, cmd, 0x0f);
480}
481
482static irqreturn_t snd_es1688_interrupt(int irq, void *dev_id, struct pt_regs *regs)
483{
484 es1688_t *chip = dev_id;
485
486 if (chip->trigger_value == 0x05) /* ok.. playback is active */
487 snd_pcm_period_elapsed(chip->playback_substream);
488 if (chip->trigger_value == 0x0f) /* ok.. capture is active */
489 snd_pcm_period_elapsed(chip->capture_substream);
490
491 inb(ES1688P(chip, DATA_AVAIL)); /* ack interrupt */
492 return IRQ_HANDLED;
493}
494
495static snd_pcm_uframes_t snd_es1688_playback_pointer(snd_pcm_substream_t * substream)
496{
497 es1688_t *chip = snd_pcm_substream_chip(substream);
498 size_t ptr;
499
500 if (chip->trigger_value != 0x05)
501 return 0;
502 ptr = snd_dma_pointer(chip->dma8, chip->dma_size);
503 return bytes_to_frames(substream->runtime, ptr);
504}
505
506static snd_pcm_uframes_t snd_es1688_capture_pointer(snd_pcm_substream_t * substream)
507{
508 es1688_t *chip = snd_pcm_substream_chip(substream);
509 size_t ptr;
510
511 if (chip->trigger_value != 0x0f)
512 return 0;
513 ptr = snd_dma_pointer(chip->dma8, chip->dma_size);
514 return bytes_to_frames(substream->runtime, ptr);
515}
516
517/*
518
519 */
520
521static snd_pcm_hardware_t snd_es1688_playback =
522{
523 .info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED |
524 SNDRV_PCM_INFO_MMAP_VALID),
525 .formats = SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S16_LE,
526 .rates = SNDRV_PCM_RATE_CONTINUOUS | SNDRV_PCM_RATE_8000_48000,
527 .rate_min = 4000,
528 .rate_max = 48000,
529 .channels_min = 1,
530 .channels_max = 2,
531 .buffer_bytes_max = 65536,
532 .period_bytes_min = 64,
533 .period_bytes_max = 65536,
534 .periods_min = 1,
535 .periods_max = 1024,
536 .fifo_size = 0,
537};
538
539static snd_pcm_hardware_t snd_es1688_capture =
540{
541 .info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED |
542 SNDRV_PCM_INFO_MMAP_VALID),
543 .formats = SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S16_LE,
544 .rates = SNDRV_PCM_RATE_CONTINUOUS | SNDRV_PCM_RATE_8000_48000,
545 .rate_min = 4000,
546 .rate_max = 48000,
547 .channels_min = 1,
548 .channels_max = 2,
549 .buffer_bytes_max = 65536,
550 .period_bytes_min = 64,
551 .period_bytes_max = 65536,
552 .periods_min = 1,
553 .periods_max = 1024,
554 .fifo_size = 0,
555};
556
557/*
558
559 */
560
561static int snd_es1688_playback_open(snd_pcm_substream_t * substream)
562{
563 es1688_t *chip = snd_pcm_substream_chip(substream);
564 snd_pcm_runtime_t *runtime = substream->runtime;
565
566 if (chip->capture_substream != NULL)
567 return -EAGAIN;
568 chip->playback_substream = substream;
569 runtime->hw = snd_es1688_playback;
570 snd_pcm_hw_constraint_ratnums(runtime, 0, SNDRV_PCM_HW_PARAM_RATE,
571 &hw_constraints_clocks);
572 return 0;
573}
574
575static int snd_es1688_capture_open(snd_pcm_substream_t * substream)
576{
577 es1688_t *chip = snd_pcm_substream_chip(substream);
578 snd_pcm_runtime_t *runtime = substream->runtime;
579
580 if (chip->playback_substream != NULL)
581 return -EAGAIN;
582 chip->capture_substream = substream;
583 runtime->hw = snd_es1688_capture;
584 snd_pcm_hw_constraint_ratnums(runtime, 0, SNDRV_PCM_HW_PARAM_RATE,
585 &hw_constraints_clocks);
586 return 0;
587}
588
589static int snd_es1688_playback_close(snd_pcm_substream_t * substream)
590{
591 es1688_t *chip = snd_pcm_substream_chip(substream);
592
593 chip->playback_substream = NULL;
594 return 0;
595}
596
597static int snd_es1688_capture_close(snd_pcm_substream_t * substream)
598{
599 es1688_t *chip = snd_pcm_substream_chip(substream);
600
601 chip->capture_substream = NULL;
602 return 0;
603}
604
605static int snd_es1688_free(es1688_t *chip)
606{
607 if (chip->res_port) {
608 snd_es1688_init(chip, 0);
609 release_resource(chip->res_port);
610 kfree_nocheck(chip->res_port);
611 }
612 if (chip->irq >= 0)
613 free_irq(chip->irq, (void *) chip);
614 if (chip->dma8 >= 0) {
615 disable_dma(chip->dma8);
616 free_dma(chip->dma8);
617 }
618 kfree(chip);
619 return 0;
620}
621
622static int snd_es1688_dev_free(snd_device_t *device)
623{
624 es1688_t *chip = device->device_data;
625 return snd_es1688_free(chip);
626}
627
628static const char *snd_es1688_chip_id(es1688_t *chip)
629{
630 static char tmp[16];
631 sprintf(tmp, "ES%s688 rev %i", chip->hardware == ES1688_HW_688 ? "" : "1", chip->version & 0x0f);
632 return tmp;
633}
634
635int snd_es1688_create(snd_card_t * card,
636 unsigned long port,
637 unsigned long mpu_port,
638 int irq,
639 int mpu_irq,
640 int dma8,
641 unsigned short hardware,
642 es1688_t **rchip)
643{
644 static snd_device_ops_t ops = {
645 .dev_free = snd_es1688_dev_free,
646 };
647
648 es1688_t *chip;
649 int err;
650
651 *rchip = NULL;
652 chip = kcalloc(1, sizeof(*chip), GFP_KERNEL);
653 if (chip == NULL)
654 return -ENOMEM;
655 chip->irq = -1;
656 chip->dma8 = -1;
657
658 if ((chip->res_port = request_region(port + 4, 12, "ES1688")) == NULL) {
659 snd_printk(KERN_ERR "es1688: can't grab port 0x%lx\n", port + 4);
660 snd_es1688_free(chip);
661 return -EBUSY;
662 }
663 if (request_irq(irq, snd_es1688_interrupt, SA_INTERRUPT, "ES1688", (void *) chip)) {
664 snd_printk(KERN_ERR "es1688: can't grab IRQ %d\n", irq);
665 snd_es1688_free(chip);
666 return -EBUSY;
667 }
668 chip->irq = irq;
669 if (request_dma(dma8, "ES1688")) {
670 snd_printk(KERN_ERR "es1688: can't grab DMA8 %d\n", dma8);
671 snd_es1688_free(chip);
672 return -EBUSY;
673 }
674 chip->dma8 = dma8;
675
676 spin_lock_init(&chip->reg_lock);
677 spin_lock_init(&chip->mixer_lock);
678 chip->card = card;
679 chip->port = port;
680 mpu_port &= ~0x000f;
681 if (mpu_port < 0x300 || mpu_port > 0x330)
682 mpu_port = 0;
683 chip->mpu_port = mpu_port;
684 chip->mpu_irq = mpu_irq;
685 chip->hardware = hardware;
686
687 if ((err = snd_es1688_probe(chip)) < 0) {
688 snd_es1688_free(chip);
689 return err;
690 }
691 if ((err = snd_es1688_init(chip, 1)) < 0) {
692 snd_es1688_free(chip);
693 return err;
694 }
695
696 /* Register device */
697 if ((err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops)) < 0) {
698 snd_es1688_free(chip);
699 return err;
700 }
701
702 *rchip = chip;
703 return 0;
704}
705
706static snd_pcm_ops_t snd_es1688_playback_ops = {
707 .open = snd_es1688_playback_open,
708 .close = snd_es1688_playback_close,
709 .ioctl = snd_es1688_ioctl,
710 .hw_params = snd_es1688_hw_params,
711 .hw_free = snd_es1688_hw_free,
712 .prepare = snd_es1688_playback_prepare,
713 .trigger = snd_es1688_playback_trigger,
714 .pointer = snd_es1688_playback_pointer,
715};
716
717static snd_pcm_ops_t snd_es1688_capture_ops = {
718 .open = snd_es1688_capture_open,
719 .close = snd_es1688_capture_close,
720 .ioctl = snd_es1688_ioctl,
721 .hw_params = snd_es1688_hw_params,
722 .hw_free = snd_es1688_hw_free,
723 .prepare = snd_es1688_capture_prepare,
724 .trigger = snd_es1688_capture_trigger,
725 .pointer = snd_es1688_capture_pointer,
726};
727
728static void snd_es1688_pcm_free(snd_pcm_t *pcm)
729{
730 es1688_t *chip = pcm->private_data;
731 chip->pcm = NULL;
732 snd_pcm_lib_preallocate_free_for_all(pcm);
733}
734
735int snd_es1688_pcm(es1688_t * chip, int device, snd_pcm_t ** rpcm)
736{
737 snd_pcm_t *pcm;
738 int err;
739
740 if ((err = snd_pcm_new(chip->card, "ESx688", device, 1, 1, &pcm)) < 0)
741 return err;
742
743 snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_es1688_playback_ops);
744 snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_es1688_capture_ops);
745
746 pcm->private_data = chip;
747 pcm->private_free = snd_es1688_pcm_free;
748 pcm->info_flags = SNDRV_PCM_INFO_HALF_DUPLEX;
749 sprintf(pcm->name, snd_es1688_chip_id(chip));
750 chip->pcm = pcm;
751
752 snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV,
753 snd_dma_isa_data(),
754 64*1024, 64*1024);
755
756 if (rpcm)
757 *rpcm = pcm;
758 return 0;
759}
760
761/*
762 * MIXER part
763 */
764
765static int snd_es1688_info_mux(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
766{
767 static char *texts[9] = {
768 "Mic", "Mic Master", "CD", "AOUT",
769 "Mic1", "Mix", "Line", "Master"
770 };
771
772 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
773 uinfo->count = 1;
774 uinfo->value.enumerated.items = 8;
775 if (uinfo->value.enumerated.item > 7)
776 uinfo->value.enumerated.item = 7;
777 strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]);
778 return 0;
779}
780
781static int snd_es1688_get_mux(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
782{
783 es1688_t *chip = snd_kcontrol_chip(kcontrol);
784 ucontrol->value.enumerated.item[0] = snd_es1688_mixer_read(chip, ES1688_REC_DEV) & 7;
785 return 0;
786}
787
788static int snd_es1688_put_mux(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
789{
790 es1688_t *chip = snd_kcontrol_chip(kcontrol);
791 unsigned long flags;
792 unsigned char oval, nval;
793 int change;
794
795 if (ucontrol->value.enumerated.item[0] > 8)
796 return -EINVAL;
797 spin_lock_irqsave(&chip->reg_lock, flags);
798 oval = snd_es1688_mixer_read(chip, ES1688_REC_DEV);
799 nval = (ucontrol->value.enumerated.item[0] & 7) | (oval & ~15);
800 change = nval != oval;
801 if (change)
802 snd_es1688_mixer_write(chip, ES1688_REC_DEV, nval);
803 spin_unlock_irqrestore(&chip->reg_lock, flags);
804 return change;
805}
806
807#define ES1688_SINGLE(xname, xindex, reg, shift, mask, invert) \
808{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xindex, \
809 .info = snd_es1688_info_single, \
810 .get = snd_es1688_get_single, .put = snd_es1688_put_single, \
811 .private_value = reg | (shift << 8) | (mask << 16) | (invert << 24) }
812
813static int snd_es1688_info_single(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
814{
815 int mask = (kcontrol->private_value >> 16) & 0xff;
816
817 uinfo->type = mask == 1 ? SNDRV_CTL_ELEM_TYPE_BOOLEAN : SNDRV_CTL_ELEM_TYPE_INTEGER;
818 uinfo->count = 1;
819 uinfo->value.integer.min = 0;
820 uinfo->value.integer.max = mask;
821 return 0;
822}
823
824static int snd_es1688_get_single(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
825{
826 es1688_t *chip = snd_kcontrol_chip(kcontrol);
827 unsigned long flags;
828 int reg = kcontrol->private_value & 0xff;
829 int shift = (kcontrol->private_value >> 8) & 0xff;
830 int mask = (kcontrol->private_value >> 16) & 0xff;
831 int invert = (kcontrol->private_value >> 24) & 0xff;
832
833 spin_lock_irqsave(&chip->reg_lock, flags);
834 ucontrol->value.integer.value[0] = (snd_es1688_mixer_read(chip, reg) >> shift) & mask;
835 spin_unlock_irqrestore(&chip->reg_lock, flags);
836 if (invert)
837 ucontrol->value.integer.value[0] = mask - ucontrol->value.integer.value[0];
838 return 0;
839}
840
841static int snd_es1688_put_single(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
842{
843 es1688_t *chip = snd_kcontrol_chip(kcontrol);
844 unsigned long flags;
845 int reg = kcontrol->private_value & 0xff;
846 int shift = (kcontrol->private_value >> 8) & 0xff;
847 int mask = (kcontrol->private_value >> 16) & 0xff;
848 int invert = (kcontrol->private_value >> 24) & 0xff;
849 int change;
850 unsigned char oval, nval;
851
852 nval = (ucontrol->value.integer.value[0] & mask);
853 if (invert)
854 nval = mask - nval;
855 nval <<= shift;
856 spin_lock_irqsave(&chip->reg_lock, flags);
857 oval = snd_es1688_mixer_read(chip, reg);
858 nval = (oval & ~(mask << shift)) | nval;
859 change = nval != oval;
860 if (change)
861 snd_es1688_mixer_write(chip, reg, nval);
862 spin_unlock_irqrestore(&chip->reg_lock, flags);
863 return change;
864}
865
866#define ES1688_DOUBLE(xname, xindex, left_reg, right_reg, shift_left, shift_right, mask, invert) \
867{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xindex, \
868 .info = snd_es1688_info_double, \
869 .get = snd_es1688_get_double, .put = snd_es1688_put_double, \
870 .private_value = left_reg | (right_reg << 8) | (shift_left << 16) | (shift_right << 19) | (mask << 24) | (invert << 22) }
871
872static int snd_es1688_info_double(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
873{
874 int mask = (kcontrol->private_value >> 24) & 0xff;
875
876 uinfo->type = mask == 1 ? SNDRV_CTL_ELEM_TYPE_BOOLEAN : SNDRV_CTL_ELEM_TYPE_INTEGER;
877 uinfo->count = 2;
878 uinfo->value.integer.min = 0;
879 uinfo->value.integer.max = mask;
880 return 0;
881}
882
883static int snd_es1688_get_double(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
884{
885 es1688_t *chip = snd_kcontrol_chip(kcontrol);
886 unsigned long flags;
887 int left_reg = kcontrol->private_value & 0xff;
888 int right_reg = (kcontrol->private_value >> 8) & 0xff;
889 int shift_left = (kcontrol->private_value >> 16) & 0x07;
890 int shift_right = (kcontrol->private_value >> 19) & 0x07;
891 int mask = (kcontrol->private_value >> 24) & 0xff;
892 int invert = (kcontrol->private_value >> 22) & 1;
893 unsigned char left, right;
894
895 spin_lock_irqsave(&chip->reg_lock, flags);
896 if (left_reg < 0xa0)
897 left = snd_es1688_mixer_read(chip, left_reg);
898 else
899 left = snd_es1688_read(chip, left_reg);
900 if (left_reg != right_reg) {
901 if (right_reg < 0xa0)
902 right = snd_es1688_mixer_read(chip, right_reg);
903 else
904 right = snd_es1688_read(chip, right_reg);
905 } else
906 right = left;
907 spin_unlock_irqrestore(&chip->reg_lock, flags);
908 ucontrol->value.integer.value[0] = (left >> shift_left) & mask;
909 ucontrol->value.integer.value[1] = (right >> shift_right) & mask;
910 if (invert) {
911 ucontrol->value.integer.value[0] = mask - ucontrol->value.integer.value[0];
912 ucontrol->value.integer.value[1] = mask - ucontrol->value.integer.value[1];
913 }
914 return 0;
915}
916
917static int snd_es1688_put_double(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
918{
919 es1688_t *chip = snd_kcontrol_chip(kcontrol);
920 unsigned long flags;
921 int left_reg = kcontrol->private_value & 0xff;
922 int right_reg = (kcontrol->private_value >> 8) & 0xff;
923 int shift_left = (kcontrol->private_value >> 16) & 0x07;
924 int shift_right = (kcontrol->private_value >> 19) & 0x07;
925 int mask = (kcontrol->private_value >> 24) & 0xff;
926 int invert = (kcontrol->private_value >> 22) & 1;
927 int change;
928 unsigned char val1, val2, oval1, oval2;
929
930 val1 = ucontrol->value.integer.value[0] & mask;
931 val2 = ucontrol->value.integer.value[1] & mask;
932 if (invert) {
933 val1 = mask - val1;
934 val2 = mask - val2;
935 }
936 val1 <<= shift_left;
937 val2 <<= shift_right;
938 spin_lock_irqsave(&chip->reg_lock, flags);
939 if (left_reg != right_reg) {
940 if (left_reg < 0xa0)
941 oval1 = snd_es1688_mixer_read(chip, left_reg);
942 else
943 oval1 = snd_es1688_read(chip, left_reg);
944 if (right_reg < 0xa0)
945 oval2 = snd_es1688_mixer_read(chip, right_reg);
946 else
947 oval2 = snd_es1688_read(chip, right_reg);
948 val1 = (oval1 & ~(mask << shift_left)) | val1;
949 val2 = (oval2 & ~(mask << shift_right)) | val2;
950 change = val1 != oval1 || val2 != oval2;
951 if (change) {
952 if (left_reg < 0xa0)
953 snd_es1688_mixer_write(chip, left_reg, val1);
954 else
955 snd_es1688_write(chip, left_reg, val1);
956 if (right_reg < 0xa0)
957 snd_es1688_mixer_write(chip, right_reg, val1);
958 else
959 snd_es1688_write(chip, right_reg, val1);
960 }
961 } else {
962 if (left_reg < 0xa0)
963 oval1 = snd_es1688_mixer_read(chip, left_reg);
964 else
965 oval1 = snd_es1688_read(chip, left_reg);
966 val1 = (oval1 & ~((mask << shift_left) | (mask << shift_right))) | val1 | val2;
967 change = val1 != oval1;
968 if (change) {
969 if (left_reg < 0xa0)
970 snd_es1688_mixer_write(chip, left_reg, val1);
971 else
972 snd_es1688_write(chip, left_reg, val1);
973 }
974
975 }
976 spin_unlock_irqrestore(&chip->reg_lock, flags);
977 return change;
978}
979
980static snd_kcontrol_new_t snd_es1688_controls[] = {
981ES1688_DOUBLE("Master Playback Volume", 0, ES1688_MASTER_DEV, ES1688_MASTER_DEV, 4, 0, 15, 0),
982ES1688_DOUBLE("PCM Playback Volume", 0, ES1688_PCM_DEV, ES1688_PCM_DEV, 4, 0, 15, 0),
983ES1688_DOUBLE("Line Playback Volume", 0, ES1688_LINE_DEV, ES1688_LINE_DEV, 4, 0, 15, 0),
984ES1688_DOUBLE("CD Playback Volume", 0, ES1688_CD_DEV, ES1688_CD_DEV, 4, 0, 15, 0),
985ES1688_DOUBLE("FM Playback Volume", 0, ES1688_FM_DEV, ES1688_FM_DEV, 4, 0, 15, 0),
986ES1688_DOUBLE("Mic Playback Volume", 0, ES1688_MIC_DEV, ES1688_MIC_DEV, 4, 0, 15, 0),
987ES1688_DOUBLE("Aux Playback Volume", 0, ES1688_AUX_DEV, ES1688_AUX_DEV, 4, 0, 15, 0),
988ES1688_SINGLE("PC Speaker Playback Volume", 0, ES1688_SPEAKER_DEV, 0, 7, 0),
989ES1688_DOUBLE("Capture Volume", 0, ES1688_RECLEV_DEV, ES1688_RECLEV_DEV, 4, 0, 15, 0),
990ES1688_SINGLE("Capture Switch", 0, ES1688_REC_DEV, 4, 1, 1),
991{
992 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
993 .name = "Capture Source",
994 .info = snd_es1688_info_mux,
995 .get = snd_es1688_get_mux,
996 .put = snd_es1688_put_mux,
997},
998};
999
1000#define ES1688_INIT_TABLE_SIZE (sizeof(snd_es1688_init_table)/2)
1001
1002static unsigned char snd_es1688_init_table[][2] = {
1003 { ES1688_MASTER_DEV, 0 },
1004 { ES1688_PCM_DEV, 0 },
1005 { ES1688_LINE_DEV, 0 },
1006 { ES1688_CD_DEV, 0 },
1007 { ES1688_FM_DEV, 0 },
1008 { ES1688_MIC_DEV, 0 },
1009 { ES1688_AUX_DEV, 0 },
1010 { ES1688_SPEAKER_DEV, 0 },
1011 { ES1688_RECLEV_DEV, 0 },
1012 { ES1688_REC_DEV, 0x17 }
1013};
1014
1015int snd_es1688_mixer(es1688_t *chip)
1016{
1017 snd_card_t *card;
1018 unsigned int idx;
1019 int err;
1020 unsigned char reg, val;
1021
1022 snd_assert(chip != NULL && chip->card != NULL, return -EINVAL);
1023
1024 card = chip->card;
1025
1026 strcpy(card->mixername, snd_es1688_chip_id(chip));
1027
1028 for (idx = 0; idx < ARRAY_SIZE(snd_es1688_controls); idx++) {
1029 if ((err = snd_ctl_add(card, snd_ctl_new1(&snd_es1688_controls[idx], chip))) < 0)
1030 return err;
1031 }
1032 for (idx = 0; idx < ES1688_INIT_TABLE_SIZE; idx++) {
1033 reg = snd_es1688_init_table[idx][0];
1034 val = snd_es1688_init_table[idx][1];
1035 if (reg < 0xa0)
1036 snd_es1688_mixer_write(chip, reg, val);
1037 else
1038 snd_es1688_write(chip, reg, val);
1039 }
1040 return 0;
1041}
1042
1043EXPORT_SYMBOL(snd_es1688_mixer_write);
1044EXPORT_SYMBOL(snd_es1688_create);
1045EXPORT_SYMBOL(snd_es1688_pcm);
1046EXPORT_SYMBOL(snd_es1688_mixer);
1047
1048/*
1049 * INIT part
1050 */
1051
1052static int __init alsa_es1688_init(void)
1053{
1054 return 0;
1055}
1056
1057static void __exit alsa_es1688_exit(void)
1058{
1059}
1060
1061module_init(alsa_es1688_init)
1062module_exit(alsa_es1688_exit)
diff --git a/sound/isa/es18xx.c b/sound/isa/es18xx.c
new file mode 100644
index 000000000000..1d832b2adb7c
--- /dev/null
+++ b/sound/isa/es18xx.c
@@ -0,0 +1,2224 @@
1/*
2 * Driver for generic ESS AudioDrive ES18xx soundcards
3 * Copyright (c) by Christian Fischbach <fishbach@pool.informatik.rwth-aachen.de>
4 * Copyright (c) by Abramo Bagnara <abramo@alsa-project.org>
5 *
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 *
21 */
22/* GENERAL NOTES:
23 *
24 * BUGS:
25 * - There are pops (we can't delay in trigger function, cause midlevel
26 * often need to trigger down and then up very quickly).
27 * Any ideas?
28 * - Support for 16 bit DMA seems to be broken. I've no hardware to tune it.
29 */
30
31/*
32 * ES1868 NOTES:
33 * - The chip has one half duplex pcm (with very limited full duplex support).
34 *
35 * - Duplex stereophonic sound is impossible.
36 * - Record and playback must share the same frequency rate.
37 *
38 * - The driver use dma2 for playback and dma1 for capture.
39 */
40
41/*
42 * ES1869 NOTES:
43 *
44 * - there are a first full duplex pcm and a second playback only pcm
45 * (incompatible with first pcm capture)
46 *
47 * - there is support for the capture volume and ESS Spatializer 3D effect.
48 *
49 * - contrarily to some pages in DS_1869.PDF the rates can be set
50 * independently.
51 *
52 * BUGS:
53 *
54 * - There is a major trouble I noted:
55 *
56 * using both channel for playback stereo 16 bit samples at 44100 Hz
57 * the second pcm (Audio1) DMA slows down irregularly and sound is garbled.
58 *
59 * The same happens using Audio1 for captureing.
60 *
61 * The Windows driver does not suffer of this (although it use Audio1
62 * only for captureing). I'm unable to discover why.
63 *
64 */
65
66
67#include <sound/driver.h>
68#include <asm/io.h>
69#include <asm/dma.h>
70#include <linux/init.h>
71#include <linux/pm.h>
72#include <linux/slab.h>
73#include <linux/pnp.h>
74#include <linux/isapnp.h>
75#include <linux/moduleparam.h>
76#include <sound/core.h>
77#include <sound/control.h>
78#include <sound/pcm.h>
79#include <sound/pcm_params.h>
80#include <sound/mpu401.h>
81#include <sound/opl3.h>
82#define SNDRV_LEGACY_AUTO_PROBE
83#define SNDRV_LEGACY_FIND_FREE_IRQ
84#define SNDRV_LEGACY_FIND_FREE_DMA
85#include <sound/initval.h>
86
87#define PFX "es18xx: "
88
89struct _snd_es18xx {
90 unsigned long port; /* port of ESS chip */
91 unsigned long mpu_port; /* MPU-401 port of ESS chip */
92 unsigned long fm_port; /* FM port */
93 unsigned long ctrl_port; /* Control port of ESS chip */
94 struct resource *res_port;
95 struct resource *res_mpu_port;
96 struct resource *res_ctrl_port;
97 int irq; /* IRQ number of ESS chip */
98 int dma1; /* DMA1 */
99 int dma2; /* DMA2 */
100 unsigned short version; /* version of ESS chip */
101 int caps; /* Chip capabilities */
102 unsigned short audio2_vol; /* volume level of audio2 */
103
104 unsigned short active; /* active channel mask */
105 unsigned int dma1_size;
106 unsigned int dma2_size;
107 unsigned int dma1_shift;
108 unsigned int dma2_shift;
109
110 snd_card_t *card;
111 snd_pcm_t *pcm;
112 snd_pcm_substream_t *playback_a_substream;
113 snd_pcm_substream_t *capture_a_substream;
114 snd_pcm_substream_t *playback_b_substream;
115
116 snd_rawmidi_t *rmidi;
117
118 snd_kcontrol_t *hw_volume;
119 snd_kcontrol_t *hw_switch;
120 snd_kcontrol_t *master_volume;
121 snd_kcontrol_t *master_switch;
122
123 spinlock_t reg_lock;
124 spinlock_t mixer_lock;
125 spinlock_t ctrl_lock;
126#ifdef CONFIG_PM
127 unsigned char pm_reg;
128#endif
129};
130
131#define AUDIO1_IRQ 0x01
132#define AUDIO2_IRQ 0x02
133#define HWV_IRQ 0x04
134#define MPU_IRQ 0x08
135
136#define ES18XX_PCM2 0x0001 /* Has two useable PCM */
137#define ES18XX_SPATIALIZER 0x0002 /* Has 3D Spatializer */
138#define ES18XX_RECMIX 0x0004 /* Has record mixer */
139#define ES18XX_DUPLEX_MONO 0x0008 /* Has mono duplex only */
140#define ES18XX_DUPLEX_SAME 0x0010 /* Playback and record must share the same rate */
141#define ES18XX_NEW_RATE 0x0020 /* More precise rate setting */
142#define ES18XX_AUXB 0x0040 /* AuxB mixer control */
143#define ES18XX_HWV 0x0080 /* Has hardware volume */
144#define ES18XX_MONO 0x0100 /* Mono_in mixer control */
145#define ES18XX_I2S 0x0200 /* I2S mixer control */
146#define ES18XX_MUTEREC 0x0400 /* Record source can be muted */
147#define ES18XX_CONTROL 0x0800 /* Has control ports */
148
149/* Power Management */
150#define ES18XX_PM 0x07
151#define ES18XX_PM_GPO0 0x01
152#define ES18XX_PM_GPO1 0x02
153#define ES18XX_PM_PDR 0x04
154#define ES18XX_PM_ANA 0x08
155#define ES18XX_PM_FM 0x020
156#define ES18XX_PM_SUS 0x080
157
158typedef struct _snd_es18xx es18xx_t;
159
160/* Lowlevel */
161
162#define DAC1 0x01
163#define ADC1 0x02
164#define DAC2 0x04
165#define MILLISECOND 10000
166
167static int snd_es18xx_dsp_command(es18xx_t *chip, unsigned char val)
168{
169 int i;
170
171 for(i = MILLISECOND; i; i--)
172 if ((inb(chip->port + 0x0C) & 0x80) == 0) {
173 outb(val, chip->port + 0x0C);
174 return 0;
175 }
176 snd_printk("dsp_command: timeout (0x%x)\n", val);
177 return -EINVAL;
178}
179
180static int snd_es18xx_dsp_get_byte(es18xx_t *chip)
181{
182 int i;
183
184 for(i = MILLISECOND/10; i; i--)
185 if (inb(chip->port + 0x0C) & 0x40)
186 return inb(chip->port + 0x0A);
187 snd_printk("dsp_get_byte failed: 0x%lx = 0x%x!!!\n", chip->port + 0x0A, inb(chip->port + 0x0A));
188 return -ENODEV;
189}
190
191#undef REG_DEBUG
192
193static int snd_es18xx_write(es18xx_t *chip,
194 unsigned char reg, unsigned char data)
195{
196 unsigned long flags;
197 int ret;
198
199 spin_lock_irqsave(&chip->reg_lock, flags);
200 ret = snd_es18xx_dsp_command(chip, reg);
201 if (ret < 0)
202 goto end;
203 ret = snd_es18xx_dsp_command(chip, data);
204 end:
205 spin_unlock_irqrestore(&chip->reg_lock, flags);
206#ifdef REG_DEBUG
207 snd_printk("Reg %02x set to %02x\n", reg, data);
208#endif
209 return ret;
210}
211
212static int snd_es18xx_read(es18xx_t *chip, unsigned char reg)
213{
214 unsigned long flags;
215 int ret, data;
216 spin_lock_irqsave(&chip->reg_lock, flags);
217 ret = snd_es18xx_dsp_command(chip, 0xC0);
218 if (ret < 0)
219 goto end;
220 ret = snd_es18xx_dsp_command(chip, reg);
221 if (ret < 0)
222 goto end;
223 data = snd_es18xx_dsp_get_byte(chip);
224 ret = data;
225#ifdef REG_DEBUG
226 snd_printk("Reg %02x now is %02x (%d)\n", reg, data, ret);
227#endif
228 end:
229 spin_unlock_irqrestore(&chip->reg_lock, flags);
230 return ret;
231}
232
233/* Return old value */
234static int snd_es18xx_bits(es18xx_t *chip, unsigned char reg,
235 unsigned char mask, unsigned char val)
236{
237 int ret;
238 unsigned char old, new, oval;
239 unsigned long flags;
240 spin_lock_irqsave(&chip->reg_lock, flags);
241 ret = snd_es18xx_dsp_command(chip, 0xC0);
242 if (ret < 0)
243 goto end;
244 ret = snd_es18xx_dsp_command(chip, reg);
245 if (ret < 0)
246 goto end;
247 ret = snd_es18xx_dsp_get_byte(chip);
248 if (ret < 0) {
249 goto end;
250 }
251 old = ret;
252 oval = old & mask;
253 if (val != oval) {
254 ret = snd_es18xx_dsp_command(chip, reg);
255 if (ret < 0)
256 goto end;
257 new = (old & ~mask) | (val & mask);
258 ret = snd_es18xx_dsp_command(chip, new);
259 if (ret < 0)
260 goto end;
261#ifdef REG_DEBUG
262 snd_printk("Reg %02x was %02x, set to %02x (%d)\n", reg, old, new, ret);
263#endif
264 }
265 ret = oval;
266 end:
267 spin_unlock_irqrestore(&chip->reg_lock, flags);
268 return ret;
269}
270
271static inline void snd_es18xx_mixer_write(es18xx_t *chip,
272 unsigned char reg, unsigned char data)
273{
274 unsigned long flags;
275 spin_lock_irqsave(&chip->mixer_lock, flags);
276 outb(reg, chip->port + 0x04);
277 outb(data, chip->port + 0x05);
278 spin_unlock_irqrestore(&chip->mixer_lock, flags);
279#ifdef REG_DEBUG
280 snd_printk("Mixer reg %02x set to %02x\n", reg, data);
281#endif
282}
283
284static inline int snd_es18xx_mixer_read(es18xx_t *chip, unsigned char reg)
285{
286 unsigned long flags;
287 int data;
288 spin_lock_irqsave(&chip->mixer_lock, flags);
289 outb(reg, chip->port + 0x04);
290 data = inb(chip->port + 0x05);
291 spin_unlock_irqrestore(&chip->mixer_lock, flags);
292#ifdef REG_DEBUG
293 snd_printk("Mixer reg %02x now is %02x\n", reg, data);
294#endif
295 return data;
296}
297
298/* Return old value */
299static inline int snd_es18xx_mixer_bits(es18xx_t *chip, unsigned char reg,
300 unsigned char mask, unsigned char val)
301{
302 unsigned char old, new, oval;
303 unsigned long flags;
304 spin_lock_irqsave(&chip->mixer_lock, flags);
305 outb(reg, chip->port + 0x04);
306 old = inb(chip->port + 0x05);
307 oval = old & mask;
308 if (val != oval) {
309 new = (old & ~mask) | (val & mask);
310 outb(new, chip->port + 0x05);
311#ifdef REG_DEBUG
312 snd_printk("Mixer reg %02x was %02x, set to %02x\n", reg, old, new);
313#endif
314 }
315 spin_unlock_irqrestore(&chip->mixer_lock, flags);
316 return oval;
317}
318
319static inline int snd_es18xx_mixer_writable(es18xx_t *chip, unsigned char reg,
320 unsigned char mask)
321{
322 int old, expected, new;
323 unsigned long flags;
324 spin_lock_irqsave(&chip->mixer_lock, flags);
325 outb(reg, chip->port + 0x04);
326 old = inb(chip->port + 0x05);
327 expected = old ^ mask;
328 outb(expected, chip->port + 0x05);
329 new = inb(chip->port + 0x05);
330 spin_unlock_irqrestore(&chip->mixer_lock, flags);
331#ifdef REG_DEBUG
332 snd_printk("Mixer reg %02x was %02x, set to %02x, now is %02x\n", reg, old, expected, new);
333#endif
334 return expected == new;
335}
336
337
338static int snd_es18xx_reset(es18xx_t *chip)
339{
340 int i;
341 outb(0x03, chip->port + 0x06);
342 inb(chip->port + 0x06);
343 outb(0x00, chip->port + 0x06);
344 for(i = 0; i < MILLISECOND && !(inb(chip->port + 0x0E) & 0x80); i++);
345 if (inb(chip->port + 0x0A) != 0xAA)
346 return -1;
347 return 0;
348}
349
350static int snd_es18xx_reset_fifo(es18xx_t *chip)
351{
352 outb(0x02, chip->port + 0x06);
353 inb(chip->port + 0x06);
354 outb(0x00, chip->port + 0x06);
355 return 0;
356}
357
358static ratnum_t new_clocks[2] = {
359 {
360 .num = 793800,
361 .den_min = 1,
362 .den_max = 128,
363 .den_step = 1,
364 },
365 {
366 .num = 768000,
367 .den_min = 1,
368 .den_max = 128,
369 .den_step = 1,
370 }
371};
372
373static snd_pcm_hw_constraint_ratnums_t new_hw_constraints_clocks = {
374 .nrats = 2,
375 .rats = new_clocks,
376};
377
378static ratnum_t old_clocks[2] = {
379 {
380 .num = 795444,
381 .den_min = 1,
382 .den_max = 128,
383 .den_step = 1,
384 },
385 {
386 .num = 397722,
387 .den_min = 1,
388 .den_max = 128,
389 .den_step = 1,
390 }
391};
392
393static snd_pcm_hw_constraint_ratnums_t old_hw_constraints_clocks = {
394 .nrats = 2,
395 .rats = old_clocks,
396};
397
398
399static void snd_es18xx_rate_set(es18xx_t *chip,
400 snd_pcm_substream_t *substream,
401 int mode)
402{
403 unsigned int bits, div0;
404 snd_pcm_runtime_t *runtime = substream->runtime;
405 if (chip->caps & ES18XX_NEW_RATE) {
406 if (runtime->rate_num == new_clocks[0].num)
407 bits = 128 - runtime->rate_den;
408 else
409 bits = 256 - runtime->rate_den;
410 } else {
411 if (runtime->rate_num == old_clocks[0].num)
412 bits = 256 - runtime->rate_den;
413 else
414 bits = 128 - runtime->rate_den;
415 }
416
417 /* set filter register */
418 div0 = 256 - 7160000*20/(8*82*runtime->rate);
419
420 if ((chip->caps & ES18XX_PCM2) && mode == DAC2) {
421 snd_es18xx_mixer_write(chip, 0x70, bits);
422 /*
423 * Comment from kernel oss driver:
424 * FKS: fascinating: 0x72 doesn't seem to work.
425 */
426 snd_es18xx_write(chip, 0xA2, div0);
427 snd_es18xx_mixer_write(chip, 0x72, div0);
428 } else {
429 snd_es18xx_write(chip, 0xA1, bits);
430 snd_es18xx_write(chip, 0xA2, div0);
431 }
432}
433
434static int snd_es18xx_playback_hw_params(snd_pcm_substream_t * substream,
435 snd_pcm_hw_params_t * hw_params)
436{
437 es18xx_t *chip = snd_pcm_substream_chip(substream);
438 int shift, err;
439
440 shift = 0;
441 if (params_channels(hw_params) == 2)
442 shift++;
443 if (snd_pcm_format_width(params_format(hw_params)) == 16)
444 shift++;
445
446 if (substream->number == 0 && (chip->caps & ES18XX_PCM2)) {
447 if ((chip->caps & ES18XX_DUPLEX_MONO) &&
448 (chip->capture_a_substream) &&
449 params_channels(hw_params) != 1) {
450 _snd_pcm_hw_param_setempty(hw_params, SNDRV_PCM_HW_PARAM_CHANNELS);
451 return -EBUSY;
452 }
453 chip->dma2_shift = shift;
454 } else {
455 chip->dma1_shift = shift;
456 }
457 if ((err = snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(hw_params))) < 0)
458 return err;
459 return 0;
460}
461
462static int snd_es18xx_pcm_hw_free(snd_pcm_substream_t * substream)
463{
464 return snd_pcm_lib_free_pages(substream);
465}
466
467static int snd_es18xx_playback1_prepare(es18xx_t *chip,
468 snd_pcm_substream_t *substream)
469{
470 snd_pcm_runtime_t *runtime = substream->runtime;
471 unsigned int size = snd_pcm_lib_buffer_bytes(substream);
472 unsigned int count = snd_pcm_lib_period_bytes(substream);
473
474 chip->dma2_size = size;
475
476 snd_es18xx_rate_set(chip, substream, DAC2);
477
478 /* Transfer Count Reload */
479 count = 0x10000 - count;
480 snd_es18xx_mixer_write(chip, 0x74, count & 0xff);
481 snd_es18xx_mixer_write(chip, 0x76, count >> 8);
482
483 /* Set format */
484 snd_es18xx_mixer_bits(chip, 0x7A, 0x07,
485 ((runtime->channels == 1) ? 0x00 : 0x02) |
486 (snd_pcm_format_width(runtime->format) == 16 ? 0x01 : 0x00) |
487 (snd_pcm_format_unsigned(runtime->format) ? 0x00 : 0x04));
488
489 /* Set DMA controller */
490 snd_dma_program(chip->dma2, runtime->dma_addr, size, DMA_MODE_WRITE | DMA_AUTOINIT);
491
492 return 0;
493}
494
495static int snd_es18xx_playback1_trigger(es18xx_t *chip,
496 snd_pcm_substream_t * substream,
497 int cmd)
498{
499 switch (cmd) {
500 case SNDRV_PCM_TRIGGER_START:
501 case SNDRV_PCM_TRIGGER_RESUME:
502 if (chip->active & DAC2)
503 return 0;
504 chip->active |= DAC2;
505 /* Start DMA */
506 if (chip->dma2 >= 4)
507 snd_es18xx_mixer_write(chip, 0x78, 0xb3);
508 else
509 snd_es18xx_mixer_write(chip, 0x78, 0x93);
510#ifdef AVOID_POPS
511 /* Avoid pops */
512 udelay(100000);
513 if (chip->caps & ES18XX_PCM2)
514 /* Restore Audio 2 volume */
515 snd_es18xx_mixer_write(chip, 0x7C, chip->audio2_vol);
516 else
517 /* Enable PCM output */
518 snd_es18xx_dsp_command(chip, 0xD1);
519#endif
520 break;
521 case SNDRV_PCM_TRIGGER_STOP:
522 case SNDRV_PCM_TRIGGER_SUSPEND:
523 if (!(chip->active & DAC2))
524 return 0;
525 chip->active &= ~DAC2;
526 /* Stop DMA */
527 snd_es18xx_mixer_write(chip, 0x78, 0x00);
528#ifdef AVOID_POPS
529 udelay(25000);
530 if (chip->caps & ES18XX_PCM2)
531 /* Set Audio 2 volume to 0 */
532 snd_es18xx_mixer_write(chip, 0x7C, 0);
533 else
534 /* Disable PCM output */
535 snd_es18xx_dsp_command(chip, 0xD3);
536#endif
537 break;
538 default:
539 return -EINVAL;
540 }
541
542 return 0;
543}
544
545static int snd_es18xx_capture_hw_params(snd_pcm_substream_t * substream,
546 snd_pcm_hw_params_t * hw_params)
547{
548 es18xx_t *chip = snd_pcm_substream_chip(substream);
549 int shift, err;
550
551 shift = 0;
552 if ((chip->caps & ES18XX_DUPLEX_MONO) &&
553 chip->playback_a_substream &&
554 params_channels(hw_params) != 1) {
555 _snd_pcm_hw_param_setempty(hw_params, SNDRV_PCM_HW_PARAM_CHANNELS);
556 return -EBUSY;
557 }
558 if (params_channels(hw_params) == 2)
559 shift++;
560 if (snd_pcm_format_width(params_format(hw_params)) == 16)
561 shift++;
562 chip->dma1_shift = shift;
563 if ((err = snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(hw_params))) < 0)
564 return err;
565 return 0;
566}
567
568static int snd_es18xx_capture_prepare(snd_pcm_substream_t *substream)
569{
570 es18xx_t *chip = snd_pcm_substream_chip(substream);
571 snd_pcm_runtime_t *runtime = substream->runtime;
572 unsigned int size = snd_pcm_lib_buffer_bytes(substream);
573 unsigned int count = snd_pcm_lib_period_bytes(substream);
574
575 chip->dma1_size = size;
576
577 snd_es18xx_reset_fifo(chip);
578
579 /* Set stereo/mono */
580 snd_es18xx_bits(chip, 0xA8, 0x03, runtime->channels == 1 ? 0x02 : 0x01);
581
582 snd_es18xx_rate_set(chip, substream, ADC1);
583
584 /* Transfer Count Reload */
585 count = 0x10000 - count;
586 snd_es18xx_write(chip, 0xA4, count & 0xff);
587 snd_es18xx_write(chip, 0xA5, count >> 8);
588
589#ifdef AVOID_POPS
590 udelay(100000);
591#endif
592
593 /* Set format */
594 snd_es18xx_write(chip, 0xB7,
595 snd_pcm_format_unsigned(runtime->format) ? 0x51 : 0x71);
596 snd_es18xx_write(chip, 0xB7, 0x90 |
597 ((runtime->channels == 1) ? 0x40 : 0x08) |
598 (snd_pcm_format_width(runtime->format) == 16 ? 0x04 : 0x00) |
599 (snd_pcm_format_unsigned(runtime->format) ? 0x00 : 0x20));
600
601 /* Set DMA controler */
602 snd_dma_program(chip->dma1, runtime->dma_addr, size, DMA_MODE_READ | DMA_AUTOINIT);
603
604 return 0;
605}
606
607static int snd_es18xx_capture_trigger(snd_pcm_substream_t *substream,
608 int cmd)
609{
610 es18xx_t *chip = snd_pcm_substream_chip(substream);
611
612 switch (cmd) {
613 case SNDRV_PCM_TRIGGER_START:
614 case SNDRV_PCM_TRIGGER_RESUME:
615 if (chip->active & ADC1)
616 return 0;
617 chip->active |= ADC1;
618 /* Start DMA */
619 snd_es18xx_write(chip, 0xB8, 0x0f);
620 break;
621 case SNDRV_PCM_TRIGGER_STOP:
622 case SNDRV_PCM_TRIGGER_SUSPEND:
623 if (!(chip->active & ADC1))
624 return 0;
625 chip->active &= ~ADC1;
626 /* Stop DMA */
627 snd_es18xx_write(chip, 0xB8, 0x00);
628 break;
629 default:
630 return -EINVAL;
631 }
632
633 return 0;
634}
635
636static int snd_es18xx_playback2_prepare(es18xx_t *chip,
637 snd_pcm_substream_t *substream)
638{
639 snd_pcm_runtime_t *runtime = substream->runtime;
640 unsigned int size = snd_pcm_lib_buffer_bytes(substream);
641 unsigned int count = snd_pcm_lib_period_bytes(substream);
642
643 chip->dma1_size = size;
644
645 snd_es18xx_reset_fifo(chip);
646
647 /* Set stereo/mono */
648 snd_es18xx_bits(chip, 0xA8, 0x03, runtime->channels == 1 ? 0x02 : 0x01);
649
650 snd_es18xx_rate_set(chip, substream, DAC1);
651
652 /* Transfer Count Reload */
653 count = 0x10000 - count;
654 snd_es18xx_write(chip, 0xA4, count & 0xff);
655 snd_es18xx_write(chip, 0xA5, count >> 8);
656
657 /* Set format */
658 snd_es18xx_write(chip, 0xB6,
659 snd_pcm_format_unsigned(runtime->format) ? 0x80 : 0x00);
660 snd_es18xx_write(chip, 0xB7,
661 snd_pcm_format_unsigned(runtime->format) ? 0x51 : 0x71);
662 snd_es18xx_write(chip, 0xB7, 0x90 |
663 (runtime->channels == 1 ? 0x40 : 0x08) |
664 (snd_pcm_format_width(runtime->format) == 16 ? 0x04 : 0x00) |
665 (snd_pcm_format_unsigned(runtime->format) ? 0x00 : 0x20));
666
667 /* Set DMA controler */
668 snd_dma_program(chip->dma1, runtime->dma_addr, size, DMA_MODE_WRITE | DMA_AUTOINIT);
669
670 return 0;
671}
672
673static int snd_es18xx_playback2_trigger(es18xx_t *chip,
674 snd_pcm_substream_t *substream,
675 int cmd)
676{
677 switch (cmd) {
678 case SNDRV_PCM_TRIGGER_START:
679 case SNDRV_PCM_TRIGGER_RESUME:
680 if (chip->active & DAC1)
681 return 0;
682 chip->active |= DAC1;
683 /* Start DMA */
684 snd_es18xx_write(chip, 0xB8, 0x05);
685#ifdef AVOID_POPS
686 /* Avoid pops */
687 udelay(100000);
688 /* Enable Audio 1 */
689 snd_es18xx_dsp_command(chip, 0xD1);
690#endif
691 break;
692 case SNDRV_PCM_TRIGGER_STOP:
693 case SNDRV_PCM_TRIGGER_SUSPEND:
694 if (!(chip->active & DAC1))
695 return 0;
696 chip->active &= ~DAC1;
697 /* Stop DMA */
698 snd_es18xx_write(chip, 0xB8, 0x00);
699#ifdef AVOID_POPS
700 /* Avoid pops */
701 udelay(25000);
702 /* Disable Audio 1 */
703 snd_es18xx_dsp_command(chip, 0xD3);
704#endif
705 break;
706 default:
707 return -EINVAL;
708 }
709
710 return 0;
711}
712
713static int snd_es18xx_playback_prepare(snd_pcm_substream_t *substream)
714{
715 es18xx_t *chip = snd_pcm_substream_chip(substream);
716 if (substream->number == 0 && (chip->caps & ES18XX_PCM2))
717 return snd_es18xx_playback1_prepare(chip, substream);
718 else
719 return snd_es18xx_playback2_prepare(chip, substream);
720}
721
722static int snd_es18xx_playback_trigger(snd_pcm_substream_t *substream,
723 int cmd)
724{
725 es18xx_t *chip = snd_pcm_substream_chip(substream);
726 if (substream->number == 0 && (chip->caps & ES18XX_PCM2))
727 return snd_es18xx_playback1_trigger(chip, substream, cmd);
728 else
729 return snd_es18xx_playback2_trigger(chip, substream, cmd);
730}
731
732static irqreturn_t snd_es18xx_interrupt(int irq, void *dev_id, struct pt_regs *regs)
733{
734 es18xx_t *chip = dev_id;
735 unsigned char status;
736
737 if (chip->caps & ES18XX_CONTROL) {
738 /* Read Interrupt status */
739 status = inb(chip->ctrl_port + 6);
740 } else {
741 /* Read Interrupt status */
742 status = snd_es18xx_mixer_read(chip, 0x7f) >> 4;
743 }
744#if 0
745 else {
746 status = 0;
747 if (inb(chip->port + 0x0C) & 0x01)
748 status |= AUDIO1_IRQ;
749 if (snd_es18xx_mixer_read(chip, 0x7A) & 0x80)
750 status |= AUDIO2_IRQ;
751 if ((chip->caps & ES18XX_HWV) &&
752 snd_es18xx_mixer_read(chip, 0x64) & 0x10)
753 status |= HWV_IRQ;
754 }
755#endif
756
757 /* Audio 1 & Audio 2 */
758 if (status & AUDIO2_IRQ) {
759 if (chip->active & DAC2)
760 snd_pcm_period_elapsed(chip->playback_a_substream);
761 /* ack interrupt */
762 snd_es18xx_mixer_bits(chip, 0x7A, 0x80, 0x00);
763 }
764 if (status & AUDIO1_IRQ) {
765 /* ok.. capture is active */
766 if (chip->active & ADC1)
767 snd_pcm_period_elapsed(chip->capture_a_substream);
768 /* ok.. playback2 is active */
769 else if (chip->active & DAC1)
770 snd_pcm_period_elapsed(chip->playback_b_substream);
771 /* ack interrupt */
772 inb(chip->port + 0x0E);
773 }
774
775 /* MPU */
776 if ((status & MPU_IRQ) && chip->rmidi)
777 snd_mpu401_uart_interrupt(irq, chip->rmidi->private_data, regs);
778
779 /* Hardware volume */
780 if (status & HWV_IRQ) {
781 int split = snd_es18xx_mixer_read(chip, 0x64) & 0x80;
782 snd_ctl_notify(chip->card, SNDRV_CTL_EVENT_MASK_VALUE, &chip->hw_switch->id);
783 snd_ctl_notify(chip->card, SNDRV_CTL_EVENT_MASK_VALUE, &chip->hw_volume->id);
784 if (!split) {
785 snd_ctl_notify(chip->card, SNDRV_CTL_EVENT_MASK_VALUE, &chip->master_switch->id);
786 snd_ctl_notify(chip->card, SNDRV_CTL_EVENT_MASK_VALUE, &chip->master_volume->id);
787 }
788 /* ack interrupt */
789 snd_es18xx_mixer_write(chip, 0x66, 0x00);
790 }
791 return IRQ_HANDLED;
792}
793
794static snd_pcm_uframes_t snd_es18xx_playback_pointer(snd_pcm_substream_t * substream)
795{
796 es18xx_t *chip = snd_pcm_substream_chip(substream);
797 int pos;
798
799 if (substream->number == 0 && (chip->caps & ES18XX_PCM2)) {
800 if (!(chip->active & DAC2))
801 return 0;
802 pos = snd_dma_pointer(chip->dma2, chip->dma2_size);
803 return pos >> chip->dma2_shift;
804 } else {
805 if (!(chip->active & DAC1))
806 return 0;
807 pos = snd_dma_pointer(chip->dma1, chip->dma1_size);
808 return pos >> chip->dma1_shift;
809 }
810}
811
812static snd_pcm_uframes_t snd_es18xx_capture_pointer(snd_pcm_substream_t * substream)
813{
814 es18xx_t *chip = snd_pcm_substream_chip(substream);
815 int pos;
816
817 if (!(chip->active & ADC1))
818 return 0;
819 pos = snd_dma_pointer(chip->dma1, chip->dma1_size);
820 return pos >> chip->dma1_shift;
821}
822
823static snd_pcm_hardware_t snd_es18xx_playback =
824{
825 .info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED |
826 SNDRV_PCM_INFO_RESUME |
827 SNDRV_PCM_INFO_MMAP_VALID),
828 .formats = (SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S8 |
829 SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_U16_LE),
830 .rates = SNDRV_PCM_RATE_CONTINUOUS | SNDRV_PCM_RATE_8000_48000,
831 .rate_min = 4000,
832 .rate_max = 48000,
833 .channels_min = 1,
834 .channels_max = 2,
835 .buffer_bytes_max = 65536,
836 .period_bytes_min = 64,
837 .period_bytes_max = 65536,
838 .periods_min = 1,
839 .periods_max = 1024,
840 .fifo_size = 0,
841};
842
843static snd_pcm_hardware_t snd_es18xx_capture =
844{
845 .info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED |
846 SNDRV_PCM_INFO_RESUME |
847 SNDRV_PCM_INFO_MMAP_VALID),
848 .formats = (SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S8 |
849 SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_U16_LE),
850 .rates = SNDRV_PCM_RATE_CONTINUOUS | SNDRV_PCM_RATE_8000_48000,
851 .rate_min = 4000,
852 .rate_max = 48000,
853 .channels_min = 1,
854 .channels_max = 2,
855 .buffer_bytes_max = 65536,
856 .period_bytes_min = 64,
857 .period_bytes_max = 65536,
858 .periods_min = 1,
859 .periods_max = 1024,
860 .fifo_size = 0,
861};
862
863static int snd_es18xx_playback_open(snd_pcm_substream_t * substream)
864{
865 snd_pcm_runtime_t *runtime = substream->runtime;
866 es18xx_t *chip = snd_pcm_substream_chip(substream);
867
868 if (substream->number == 0 && (chip->caps & ES18XX_PCM2)) {
869 if ((chip->caps & ES18XX_DUPLEX_MONO) &&
870 chip->capture_a_substream &&
871 chip->capture_a_substream->runtime->channels != 1)
872 return -EAGAIN;
873 chip->playback_a_substream = substream;
874 } else if (substream->number <= 1) {
875 if (chip->capture_a_substream)
876 return -EAGAIN;
877 chip->playback_b_substream = substream;
878 } else {
879 snd_BUG();
880 return -EINVAL;
881 }
882 substream->runtime->hw = snd_es18xx_playback;
883 snd_pcm_hw_constraint_ratnums(runtime, 0, SNDRV_PCM_HW_PARAM_RATE,
884 (chip->caps & ES18XX_NEW_RATE) ? &new_hw_constraints_clocks : &old_hw_constraints_clocks);
885 return 0;
886}
887
888static int snd_es18xx_capture_open(snd_pcm_substream_t * substream)
889{
890 snd_pcm_runtime_t *runtime = substream->runtime;
891 es18xx_t *chip = snd_pcm_substream_chip(substream);
892
893 if (chip->playback_b_substream)
894 return -EAGAIN;
895 if ((chip->caps & ES18XX_DUPLEX_MONO) &&
896 chip->playback_a_substream &&
897 chip->playback_a_substream->runtime->channels != 1)
898 return -EAGAIN;
899 chip->capture_a_substream = substream;
900 substream->runtime->hw = snd_es18xx_capture;
901 snd_pcm_hw_constraint_ratnums(runtime, 0, SNDRV_PCM_HW_PARAM_RATE,
902 (chip->caps & ES18XX_NEW_RATE) ? &new_hw_constraints_clocks : &old_hw_constraints_clocks);
903 return 0;
904}
905
906static int snd_es18xx_playback_close(snd_pcm_substream_t * substream)
907{
908 es18xx_t *chip = snd_pcm_substream_chip(substream);
909
910 if (substream->number == 0 && (chip->caps & ES18XX_PCM2))
911 chip->playback_a_substream = NULL;
912 else
913 chip->playback_b_substream = NULL;
914
915 snd_pcm_lib_free_pages(substream);
916 return 0;
917}
918
919static int snd_es18xx_capture_close(snd_pcm_substream_t * substream)
920{
921 es18xx_t *chip = snd_pcm_substream_chip(substream);
922
923 chip->capture_a_substream = NULL;
924 snd_pcm_lib_free_pages(substream);
925 return 0;
926}
927
928/*
929 * MIXER part
930 */
931
932static int snd_es18xx_info_mux(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
933{
934 static char *texts[8] = {
935 "Mic", "Mic Master", "CD", "AOUT",
936 "Mic1", "Mix", "Line", "Master"
937 };
938
939 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
940 uinfo->count = 1;
941 uinfo->value.enumerated.items = 8;
942 if (uinfo->value.enumerated.item > 7)
943 uinfo->value.enumerated.item = 7;
944 strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]);
945 return 0;
946}
947
948static int snd_es18xx_get_mux(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
949{
950 es18xx_t *chip = snd_kcontrol_chip(kcontrol);
951 ucontrol->value.enumerated.item[0] = snd_es18xx_mixer_read(chip, 0x1c) & 0x07;
952 return 0;
953}
954
955static int snd_es18xx_put_mux(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
956{
957 es18xx_t *chip = snd_kcontrol_chip(kcontrol);
958 unsigned char val = ucontrol->value.enumerated.item[0];
959
960 if (val > 7)
961 return -EINVAL;
962 return snd_es18xx_mixer_bits(chip, 0x1c, 0x07, val) != val;
963}
964
965static int snd_es18xx_info_spatializer_enable(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
966{
967 uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
968 uinfo->count = 1;
969 uinfo->value.integer.min = 0;
970 uinfo->value.integer.max = 1;
971 return 0;
972}
973
974static int snd_es18xx_get_spatializer_enable(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
975{
976 es18xx_t *chip = snd_kcontrol_chip(kcontrol);
977 unsigned char val = snd_es18xx_mixer_read(chip, 0x50);
978 ucontrol->value.integer.value[0] = !!(val & 8);
979 return 0;
980}
981
982static int snd_es18xx_put_spatializer_enable(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
983{
984 es18xx_t *chip = snd_kcontrol_chip(kcontrol);
985 unsigned char oval, nval;
986 int change;
987 nval = ucontrol->value.integer.value[0] ? 0x0c : 0x04;
988 oval = snd_es18xx_mixer_read(chip, 0x50) & 0x0c;
989 change = nval != oval;
990 if (change) {
991 snd_es18xx_mixer_write(chip, 0x50, nval & ~0x04);
992 snd_es18xx_mixer_write(chip, 0x50, nval);
993 }
994 return change;
995}
996
997static int snd_es18xx_info_hw_volume(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
998{
999 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
1000 uinfo->count = 2;
1001 uinfo->value.integer.min = 0;
1002 uinfo->value.integer.max = 63;
1003 return 0;
1004}
1005
1006static int snd_es18xx_get_hw_volume(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
1007{
1008 es18xx_t *chip = snd_kcontrol_chip(kcontrol);
1009 ucontrol->value.integer.value[0] = snd_es18xx_mixer_read(chip, 0x61) & 0x3f;
1010 ucontrol->value.integer.value[1] = snd_es18xx_mixer_read(chip, 0x63) & 0x3f;
1011 return 0;
1012}
1013
1014static int snd_es18xx_info_hw_switch(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
1015{
1016 uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
1017 uinfo->count = 2;
1018 uinfo->value.integer.min = 0;
1019 uinfo->value.integer.max = 1;
1020 return 0;
1021}
1022
1023static int snd_es18xx_get_hw_switch(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
1024{
1025 es18xx_t *chip = snd_kcontrol_chip(kcontrol);
1026 ucontrol->value.integer.value[0] = !(snd_es18xx_mixer_read(chip, 0x61) & 0x40);
1027 ucontrol->value.integer.value[1] = !(snd_es18xx_mixer_read(chip, 0x63) & 0x40);
1028 return 0;
1029}
1030
1031static void snd_es18xx_hwv_free(snd_kcontrol_t *kcontrol)
1032{
1033 es18xx_t *chip = snd_kcontrol_chip(kcontrol);
1034 chip->master_volume = NULL;
1035 chip->master_switch = NULL;
1036 chip->hw_volume = NULL;
1037 chip->hw_switch = NULL;
1038}
1039
1040static int snd_es18xx_reg_bits(es18xx_t *chip, unsigned char reg,
1041 unsigned char mask, unsigned char val)
1042{
1043 if (reg < 0xa0)
1044 return snd_es18xx_mixer_bits(chip, reg, mask, val);
1045 else
1046 return snd_es18xx_bits(chip, reg, mask, val);
1047}
1048
1049static int snd_es18xx_reg_read(es18xx_t *chip, unsigned char reg)
1050{
1051 if (reg < 0xa0)
1052 return snd_es18xx_mixer_read(chip, reg);
1053 else
1054 return snd_es18xx_read(chip, reg);
1055}
1056
1057#define ES18XX_SINGLE(xname, xindex, reg, shift, mask, invert) \
1058{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xindex, \
1059 .info = snd_es18xx_info_single, \
1060 .get = snd_es18xx_get_single, .put = snd_es18xx_put_single, \
1061 .private_value = reg | (shift << 8) | (mask << 16) | (invert << 24) }
1062
1063static int snd_es18xx_info_single(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
1064{
1065 int mask = (kcontrol->private_value >> 16) & 0xff;
1066
1067 uinfo->type = mask == 1 ? SNDRV_CTL_ELEM_TYPE_BOOLEAN : SNDRV_CTL_ELEM_TYPE_INTEGER;
1068 uinfo->count = 1;
1069 uinfo->value.integer.min = 0;
1070 uinfo->value.integer.max = mask;
1071 return 0;
1072}
1073
1074static int snd_es18xx_get_single(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
1075{
1076 es18xx_t *chip = snd_kcontrol_chip(kcontrol);
1077 int reg = kcontrol->private_value & 0xff;
1078 int shift = (kcontrol->private_value >> 8) & 0xff;
1079 int mask = (kcontrol->private_value >> 16) & 0xff;
1080 int invert = (kcontrol->private_value >> 24) & 0xff;
1081 int val;
1082
1083 val = snd_es18xx_reg_read(chip, reg);
1084 ucontrol->value.integer.value[0] = (val >> shift) & mask;
1085 if (invert)
1086 ucontrol->value.integer.value[0] = mask - ucontrol->value.integer.value[0];
1087 return 0;
1088}
1089
1090static int snd_es18xx_put_single(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
1091{
1092 es18xx_t *chip = snd_kcontrol_chip(kcontrol);
1093 int reg = kcontrol->private_value & 0xff;
1094 int shift = (kcontrol->private_value >> 8) & 0xff;
1095 int mask = (kcontrol->private_value >> 16) & 0xff;
1096 int invert = (kcontrol->private_value >> 24) & 0xff;
1097 unsigned char val;
1098
1099 val = (ucontrol->value.integer.value[0] & mask);
1100 if (invert)
1101 val = mask - val;
1102 mask <<= shift;
1103 val <<= shift;
1104 return snd_es18xx_reg_bits(chip, reg, mask, val) != val;
1105}
1106
1107#define ES18XX_DOUBLE(xname, xindex, left_reg, right_reg, shift_left, shift_right, mask, invert) \
1108{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xindex, \
1109 .info = snd_es18xx_info_double, \
1110 .get = snd_es18xx_get_double, .put = snd_es18xx_put_double, \
1111 .private_value = left_reg | (right_reg << 8) | (shift_left << 16) | (shift_right << 19) | (mask << 24) | (invert << 22) }
1112
1113static int snd_es18xx_info_double(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
1114{
1115 int mask = (kcontrol->private_value >> 24) & 0xff;
1116
1117 uinfo->type = mask == 1 ? SNDRV_CTL_ELEM_TYPE_BOOLEAN : SNDRV_CTL_ELEM_TYPE_INTEGER;
1118 uinfo->count = 2;
1119 uinfo->value.integer.min = 0;
1120 uinfo->value.integer.max = mask;
1121 return 0;
1122}
1123
1124static int snd_es18xx_get_double(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
1125{
1126 es18xx_t *chip = snd_kcontrol_chip(kcontrol);
1127 int left_reg = kcontrol->private_value & 0xff;
1128 int right_reg = (kcontrol->private_value >> 8) & 0xff;
1129 int shift_left = (kcontrol->private_value >> 16) & 0x07;
1130 int shift_right = (kcontrol->private_value >> 19) & 0x07;
1131 int mask = (kcontrol->private_value >> 24) & 0xff;
1132 int invert = (kcontrol->private_value >> 22) & 1;
1133 unsigned char left, right;
1134
1135 left = snd_es18xx_reg_read(chip, left_reg);
1136 if (left_reg != right_reg)
1137 right = snd_es18xx_reg_read(chip, right_reg);
1138 else
1139 right = left;
1140 ucontrol->value.integer.value[0] = (left >> shift_left) & mask;
1141 ucontrol->value.integer.value[1] = (right >> shift_right) & mask;
1142 if (invert) {
1143 ucontrol->value.integer.value[0] = mask - ucontrol->value.integer.value[0];
1144 ucontrol->value.integer.value[1] = mask - ucontrol->value.integer.value[1];
1145 }
1146 return 0;
1147}
1148
1149static int snd_es18xx_put_double(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
1150{
1151 es18xx_t *chip = snd_kcontrol_chip(kcontrol);
1152 int left_reg = kcontrol->private_value & 0xff;
1153 int right_reg = (kcontrol->private_value >> 8) & 0xff;
1154 int shift_left = (kcontrol->private_value >> 16) & 0x07;
1155 int shift_right = (kcontrol->private_value >> 19) & 0x07;
1156 int mask = (kcontrol->private_value >> 24) & 0xff;
1157 int invert = (kcontrol->private_value >> 22) & 1;
1158 int change;
1159 unsigned char val1, val2, mask1, mask2;
1160
1161 val1 = ucontrol->value.integer.value[0] & mask;
1162 val2 = ucontrol->value.integer.value[1] & mask;
1163 if (invert) {
1164 val1 = mask - val1;
1165 val2 = mask - val2;
1166 }
1167 val1 <<= shift_left;
1168 val2 <<= shift_right;
1169 mask1 = mask << shift_left;
1170 mask2 = mask << shift_right;
1171 if (left_reg != right_reg) {
1172 change = 0;
1173 if (snd_es18xx_reg_bits(chip, left_reg, mask1, val1) != val1)
1174 change = 1;
1175 if (snd_es18xx_reg_bits(chip, right_reg, mask2, val2) != val2)
1176 change = 1;
1177 } else {
1178 change = (snd_es18xx_reg_bits(chip, left_reg, mask1 | mask2,
1179 val1 | val2) != (val1 | val2));
1180 }
1181 return change;
1182}
1183
1184static snd_kcontrol_new_t snd_es18xx_base_controls[] = {
1185ES18XX_DOUBLE("Master Playback Volume", 0, 0x60, 0x62, 0, 0, 63, 0),
1186ES18XX_DOUBLE("Master Playback Switch", 0, 0x60, 0x62, 6, 6, 1, 1),
1187ES18XX_DOUBLE("Line Playback Volume", 0, 0x3e, 0x3e, 4, 0, 15, 0),
1188ES18XX_DOUBLE("CD Playback Volume", 0, 0x38, 0x38, 4, 0, 15, 0),
1189ES18XX_DOUBLE("FM Playback Volume", 0, 0x36, 0x36, 4, 0, 15, 0),
1190ES18XX_DOUBLE("Mono Playback Volume", 0, 0x6d, 0x6d, 4, 0, 15, 0),
1191ES18XX_DOUBLE("Mic Playback Volume", 0, 0x1a, 0x1a, 4, 0, 15, 0),
1192ES18XX_DOUBLE("Aux Playback Volume", 0, 0x3a, 0x3a, 4, 0, 15, 0),
1193ES18XX_SINGLE("PC Speaker Playback Volume", 0, 0x3c, 0, 7, 0),
1194ES18XX_SINGLE("Record Monitor", 0, 0xa8, 3, 1, 0),
1195ES18XX_DOUBLE("Capture Volume", 0, 0xb4, 0xb4, 4, 0, 15, 0),
1196ES18XX_SINGLE("Capture Switch", 0, 0x1c, 4, 1, 1),
1197{
1198 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1199 .name = "Capture Source",
1200 .info = snd_es18xx_info_mux,
1201 .get = snd_es18xx_get_mux,
1202 .put = snd_es18xx_put_mux,
1203}
1204};
1205
1206static snd_kcontrol_new_t snd_es18xx_mono_in_control =
1207ES18XX_DOUBLE("Mono Input Playback Volume", 0, 0x6d, 0x6d, 4, 0, 15, 0);
1208
1209static snd_kcontrol_new_t snd_es18xx_recmix_controls[] = {
1210ES18XX_DOUBLE("PCM Capture Volume", 0, 0x69, 0x69, 4, 0, 15, 0),
1211ES18XX_DOUBLE("Mic Capture Volume", 0, 0x68, 0x68, 4, 0, 15, 0),
1212ES18XX_DOUBLE("Line Capture Volume", 0, 0x6e, 0x6e, 4, 0, 15, 0),
1213ES18XX_DOUBLE("FM Capture Volume", 0, 0x6b, 0x6b, 4, 0, 15, 0),
1214ES18XX_DOUBLE("Mono Capture Volume", 0, 0x6f, 0x6f, 4, 0, 15, 0),
1215ES18XX_DOUBLE("CD Capture Volume", 0, 0x6a, 0x6a, 4, 0, 15, 0),
1216ES18XX_DOUBLE("Aux Capture Volume", 0, 0x6c, 0x6c, 4, 0, 15, 0)
1217};
1218
1219static snd_kcontrol_new_t snd_es18xx_pcm1_controls[] = {
1220ES18XX_DOUBLE("PCM Playback Volume", 0, 0x14, 0x14, 4, 0, 15, 0),
1221};
1222
1223static snd_kcontrol_new_t snd_es18xx_pcm2_controls[] = {
1224ES18XX_DOUBLE("PCM Playback Volume", 0, 0x7c, 0x7c, 4, 0, 15, 0),
1225ES18XX_DOUBLE("PCM Playback Volume", 1, 0x14, 0x14, 4, 0, 15, 0)
1226};
1227
1228static snd_kcontrol_new_t snd_es18xx_spatializer_controls[] = {
1229ES18XX_SINGLE("3D Control - Level", 0, 0x52, 0, 63, 0),
1230{
1231 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1232 .name = "3D Control - Switch",
1233 .info = snd_es18xx_info_spatializer_enable,
1234 .get = snd_es18xx_get_spatializer_enable,
1235 .put = snd_es18xx_put_spatializer_enable,
1236}
1237};
1238
1239static snd_kcontrol_new_t snd_es18xx_micpre1_control =
1240ES18XX_SINGLE("Mic Boost (+26dB)", 0, 0xa9, 2, 1, 0);
1241
1242static snd_kcontrol_new_t snd_es18xx_micpre2_control =
1243ES18XX_SINGLE("Mic Boost (+26dB)", 0, 0x7d, 3, 1, 0);
1244
1245static snd_kcontrol_new_t snd_es18xx_hw_volume_controls[] = {
1246{
1247 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1248 .name = "Hardware Master Playback Volume",
1249 .access = SNDRV_CTL_ELEM_ACCESS_READ,
1250 .info = snd_es18xx_info_hw_volume,
1251 .get = snd_es18xx_get_hw_volume,
1252},
1253{
1254 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1255 .name = "Hardware Master Playback Switch",
1256 .access = SNDRV_CTL_ELEM_ACCESS_READ,
1257 .info = snd_es18xx_info_hw_switch,
1258 .get = snd_es18xx_get_hw_switch,
1259},
1260ES18XX_SINGLE("Hardware Master Volume Split", 0, 0x64, 7, 1, 0),
1261};
1262
1263#if 0
1264static int __devinit snd_es18xx_config_read(es18xx_t *chip, unsigned char reg)
1265{
1266 int data;
1267 unsigned long flags;
1268 spin_lock_irqsave(&chip->ctrl_lock, flags);
1269 outb(reg, chip->ctrl_port);
1270 data = inb(chip->ctrl_port + 1);
1271 spin_unlock_irqrestore(&chip->ctrl_lock, flags);
1272 return data;
1273}
1274#endif
1275
1276static void __devinit snd_es18xx_config_write(es18xx_t *chip,
1277 unsigned char reg, unsigned char data)
1278{
1279 /* No need for spinlocks, this function is used only in
1280 otherwise protected init code */
1281 outb(reg, chip->ctrl_port);
1282 outb(data, chip->ctrl_port + 1);
1283#ifdef REG_DEBUG
1284 snd_printk("Config reg %02x set to %02x\n", reg, data);
1285#endif
1286}
1287
1288static int __devinit snd_es18xx_initialize(es18xx_t *chip)
1289{
1290 int mask = 0;
1291
1292 /* enable extended mode */
1293 snd_es18xx_dsp_command(chip, 0xC6);
1294 /* Reset mixer registers */
1295 snd_es18xx_mixer_write(chip, 0x00, 0x00);
1296
1297 /* Audio 1 DMA demand mode (4 bytes/request) */
1298 snd_es18xx_write(chip, 0xB9, 2);
1299 if (chip->caps & ES18XX_CONTROL) {
1300 /* Hardware volume IRQ */
1301 snd_es18xx_config_write(chip, 0x27, chip->irq);
1302 if (chip->fm_port > 0 && chip->fm_port != SNDRV_AUTO_PORT) {
1303 /* FM I/O */
1304 snd_es18xx_config_write(chip, 0x62, chip->fm_port >> 8);
1305 snd_es18xx_config_write(chip, 0x63, chip->fm_port & 0xff);
1306 }
1307 if (chip->mpu_port > 0 && chip->mpu_port != SNDRV_AUTO_PORT) {
1308 /* MPU-401 I/O */
1309 snd_es18xx_config_write(chip, 0x64, chip->mpu_port >> 8);
1310 snd_es18xx_config_write(chip, 0x65, chip->mpu_port & 0xff);
1311 /* MPU-401 IRQ */
1312 snd_es18xx_config_write(chip, 0x28, chip->irq);
1313 }
1314 /* Audio1 IRQ */
1315 snd_es18xx_config_write(chip, 0x70, chip->irq);
1316 /* Audio2 IRQ */
1317 snd_es18xx_config_write(chip, 0x72, chip->irq);
1318 /* Audio1 DMA */
1319 snd_es18xx_config_write(chip, 0x74, chip->dma1);
1320 /* Audio2 DMA */
1321 snd_es18xx_config_write(chip, 0x75, chip->dma2);
1322
1323 /* Enable Audio 1 IRQ */
1324 snd_es18xx_write(chip, 0xB1, 0x50);
1325 /* Enable Audio 2 IRQ */
1326 snd_es18xx_mixer_write(chip, 0x7A, 0x40);
1327 /* Enable Audio 1 DMA */
1328 snd_es18xx_write(chip, 0xB2, 0x50);
1329 /* Enable MPU and hardware volume interrupt */
1330 snd_es18xx_mixer_write(chip, 0x64, 0x42);
1331 }
1332 else {
1333 int irqmask, dma1mask, dma2mask;
1334 switch (chip->irq) {
1335 case 2:
1336 case 9:
1337 irqmask = 0;
1338 break;
1339 case 5:
1340 irqmask = 1;
1341 break;
1342 case 7:
1343 irqmask = 2;
1344 break;
1345 case 10:
1346 irqmask = 3;
1347 break;
1348 default:
1349 snd_printk("invalid irq %d\n", chip->irq);
1350 return -ENODEV;
1351 }
1352 switch (chip->dma1) {
1353 case 0:
1354 dma1mask = 1;
1355 break;
1356 case 1:
1357 dma1mask = 2;
1358 break;
1359 case 3:
1360 dma1mask = 3;
1361 break;
1362 default:
1363 snd_printk("invalid dma1 %d\n", chip->dma1);
1364 return -ENODEV;
1365 }
1366 switch (chip->dma2) {
1367 case 0:
1368 dma2mask = 0;
1369 break;
1370 case 1:
1371 dma2mask = 1;
1372 break;
1373 case 3:
1374 dma2mask = 2;
1375 break;
1376 case 5:
1377 dma2mask = 3;
1378 break;
1379 default:
1380 snd_printk("invalid dma2 %d\n", chip->dma2);
1381 return -ENODEV;
1382 }
1383
1384 /* Enable and set Audio 1 IRQ */
1385 snd_es18xx_write(chip, 0xB1, 0x50 | (irqmask << 2));
1386 /* Enable and set Audio 1 DMA */
1387 snd_es18xx_write(chip, 0xB2, 0x50 | (dma1mask << 2));
1388 /* Set Audio 2 DMA */
1389 snd_es18xx_mixer_bits(chip, 0x7d, 0x07, 0x04 | dma2mask);
1390 /* Enable Audio 2 IRQ and DMA
1391 Set capture mixer input */
1392 snd_es18xx_mixer_write(chip, 0x7A, 0x68);
1393 /* Enable and set hardware volume interrupt */
1394 snd_es18xx_mixer_write(chip, 0x64, 0x06);
1395 if (chip->mpu_port > 0 && chip->mpu_port != SNDRV_AUTO_PORT) {
1396 /* MPU401 share irq with audio
1397 Joystick enabled
1398 FM enabled */
1399 snd_es18xx_mixer_write(chip, 0x40, 0x43 | (chip->mpu_port & 0xf0) >> 1);
1400 }
1401 snd_es18xx_mixer_write(chip, 0x7f, ((irqmask + 1) << 1) | 0x01);
1402 }
1403 if (chip->caps & ES18XX_NEW_RATE) {
1404 /* Change behaviour of register A1
1405 4x oversampling
1406 2nd channel DAC asynchronous */
1407 snd_es18xx_mixer_write(chip, 0x71, 0x32);
1408 }
1409 if (!(chip->caps & ES18XX_PCM2)) {
1410 /* Enable DMA FIFO */
1411 snd_es18xx_write(chip, 0xB7, 0x80);
1412 }
1413 if (chip->caps & ES18XX_SPATIALIZER) {
1414 /* Set spatializer parameters to recommended values */
1415 snd_es18xx_mixer_write(chip, 0x54, 0x8f);
1416 snd_es18xx_mixer_write(chip, 0x56, 0x95);
1417 snd_es18xx_mixer_write(chip, 0x58, 0x94);
1418 snd_es18xx_mixer_write(chip, 0x5a, 0x80);
1419 }
1420 /* Mute input source */
1421 if (chip->caps & ES18XX_MUTEREC)
1422 mask = 0x10;
1423 if (chip->caps & ES18XX_RECMIX)
1424 snd_es18xx_mixer_write(chip, 0x1c, 0x05 | mask);
1425 else {
1426 snd_es18xx_mixer_write(chip, 0x1c, 0x00 | mask);
1427 snd_es18xx_write(chip, 0xb4, 0x00);
1428 }
1429#ifndef AVOID_POPS
1430 /* Enable PCM output */
1431 snd_es18xx_dsp_command(chip, 0xD1);
1432#endif
1433
1434 return 0;
1435}
1436
1437static int __devinit snd_es18xx_identify(es18xx_t *chip)
1438{
1439 int hi,lo;
1440
1441 /* reset */
1442 if (snd_es18xx_reset(chip) < 0) {
1443 snd_printk("reset at 0x%lx failed!!!\n", chip->port);
1444 return -ENODEV;
1445 }
1446
1447 snd_es18xx_dsp_command(chip, 0xe7);
1448 hi = snd_es18xx_dsp_get_byte(chip);
1449 if (hi < 0) {
1450 return hi;
1451 }
1452 lo = snd_es18xx_dsp_get_byte(chip);
1453 if ((lo & 0xf0) != 0x80) {
1454 return -ENODEV;
1455 }
1456 if (hi == 0x48) {
1457 chip->version = 0x488;
1458 return 0;
1459 }
1460 if (hi != 0x68) {
1461 return -ENODEV;
1462 }
1463 if ((lo & 0x0f) < 8) {
1464 chip->version = 0x688;
1465 return 0;
1466 }
1467
1468 outb(0x40, chip->port + 0x04);
1469 hi = inb(chip->port + 0x05);
1470 lo = inb(chip->port + 0x05);
1471 if (hi != lo) {
1472 chip->version = hi << 8 | lo;
1473 chip->ctrl_port = inb(chip->port + 0x05) << 8;
1474 chip->ctrl_port += inb(chip->port + 0x05);
1475
1476 if ((chip->res_ctrl_port = request_region(chip->ctrl_port, 8, "ES18xx - CTRL")) == NULL) {
1477 snd_printk(KERN_ERR PFX "unable go grab port 0x%lx\n", chip->ctrl_port);
1478 return -EBUSY;
1479 }
1480
1481 return 0;
1482 }
1483
1484 /* If has Hardware volume */
1485 if (snd_es18xx_mixer_writable(chip, 0x64, 0x04)) {
1486 /* If has Audio2 */
1487 if (snd_es18xx_mixer_writable(chip, 0x70, 0x7f)) {
1488 /* If has volume count */
1489 if (snd_es18xx_mixer_writable(chip, 0x64, 0x20)) {
1490 chip->version = 0x1887;
1491 } else {
1492 chip->version = 0x1888;
1493 }
1494 } else {
1495 chip->version = 0x1788;
1496 }
1497 }
1498 else
1499 chip->version = 0x1688;
1500 return 0;
1501}
1502
1503static int __devinit snd_es18xx_probe(es18xx_t *chip)
1504{
1505 if (snd_es18xx_identify(chip) < 0) {
1506 snd_printk(KERN_ERR PFX "[0x%lx] ESS chip not found\n", chip->port);
1507 return -ENODEV;
1508 }
1509
1510 switch (chip->version) {
1511 case 0x1868:
1512 chip->caps = ES18XX_DUPLEX_MONO | ES18XX_DUPLEX_SAME | ES18XX_CONTROL | ES18XX_HWV;
1513 break;
1514 case 0x1869:
1515 chip->caps = ES18XX_PCM2 | ES18XX_SPATIALIZER | ES18XX_RECMIX | ES18XX_NEW_RATE | ES18XX_AUXB | ES18XX_MONO | ES18XX_MUTEREC | ES18XX_CONTROL | ES18XX_HWV;
1516 break;
1517 case 0x1878:
1518 chip->caps = ES18XX_DUPLEX_MONO | ES18XX_DUPLEX_SAME | ES18XX_I2S | ES18XX_CONTROL | ES18XX_HWV;
1519 break;
1520 case 0x1879:
1521 chip->caps = ES18XX_PCM2 | ES18XX_SPATIALIZER | ES18XX_RECMIX | ES18XX_NEW_RATE | ES18XX_AUXB | ES18XX_I2S | ES18XX_CONTROL | ES18XX_HWV;
1522 break;
1523 case 0x1887:
1524 chip->caps = ES18XX_PCM2 | ES18XX_RECMIX | ES18XX_AUXB | ES18XX_DUPLEX_SAME | ES18XX_HWV;
1525 break;
1526 case 0x1888:
1527 chip->caps = ES18XX_PCM2 | ES18XX_RECMIX | ES18XX_AUXB | ES18XX_DUPLEX_SAME | ES18XX_HWV;
1528 break;
1529 default:
1530 snd_printk("[0x%lx] unsupported chip ES%x\n",
1531 chip->port, chip->version);
1532 return -ENODEV;
1533 }
1534
1535 snd_printd("[0x%lx] ESS%x chip found\n", chip->port, chip->version);
1536
1537 if (chip->dma1 == chip->dma2)
1538 chip->caps &= ~(ES18XX_PCM2 | ES18XX_DUPLEX_SAME);
1539
1540 return snd_es18xx_initialize(chip);
1541}
1542
1543static snd_pcm_ops_t snd_es18xx_playback_ops = {
1544 .open = snd_es18xx_playback_open,
1545 .close = snd_es18xx_playback_close,
1546 .ioctl = snd_pcm_lib_ioctl,
1547 .hw_params = snd_es18xx_playback_hw_params,
1548 .hw_free = snd_es18xx_pcm_hw_free,
1549 .prepare = snd_es18xx_playback_prepare,
1550 .trigger = snd_es18xx_playback_trigger,
1551 .pointer = snd_es18xx_playback_pointer,
1552};
1553
1554static snd_pcm_ops_t snd_es18xx_capture_ops = {
1555 .open = snd_es18xx_capture_open,
1556 .close = snd_es18xx_capture_close,
1557 .ioctl = snd_pcm_lib_ioctl,
1558 .hw_params = snd_es18xx_capture_hw_params,
1559 .hw_free = snd_es18xx_pcm_hw_free,
1560 .prepare = snd_es18xx_capture_prepare,
1561 .trigger = snd_es18xx_capture_trigger,
1562 .pointer = snd_es18xx_capture_pointer,
1563};
1564
1565static void snd_es18xx_pcm_free(snd_pcm_t *pcm)
1566{
1567 es18xx_t *codec = pcm->private_data;
1568 codec->pcm = NULL;
1569 snd_pcm_lib_preallocate_free_for_all(pcm);
1570}
1571
1572static int __devinit snd_es18xx_pcm(es18xx_t *chip, int device, snd_pcm_t ** rpcm)
1573{
1574 snd_pcm_t *pcm;
1575 char str[16];
1576 int err;
1577
1578 if (rpcm)
1579 *rpcm = NULL;
1580 sprintf(str, "ES%x", chip->version);
1581 if (chip->caps & ES18XX_PCM2) {
1582 err = snd_pcm_new(chip->card, str, device, 2, 1, &pcm);
1583 } else {
1584 err = snd_pcm_new(chip->card, str, device, 1, 1, &pcm);
1585 }
1586 if (err < 0)
1587 return err;
1588
1589 snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_es18xx_playback_ops);
1590 snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_es18xx_capture_ops);
1591
1592 /* global setup */
1593 pcm->private_data = chip;
1594 pcm->private_free = snd_es18xx_pcm_free;
1595 pcm->info_flags = 0;
1596 if (chip->caps & ES18XX_DUPLEX_SAME)
1597 pcm->info_flags |= SNDRV_PCM_INFO_JOINT_DUPLEX;
1598 if (! (chip->caps & ES18XX_PCM2))
1599 pcm->info_flags |= SNDRV_PCM_INFO_HALF_DUPLEX;
1600 sprintf(pcm->name, "ESS AudioDrive ES%x", chip->version);
1601 chip->pcm = pcm;
1602
1603 snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV,
1604 snd_dma_isa_data(),
1605 64*1024,
1606 chip->dma1 > 3 || chip->dma2 > 3 ? 128*1024 : 64*1024);
1607
1608 if (rpcm)
1609 *rpcm = pcm;
1610 return 0;
1611}
1612
1613/* Power Management support functions */
1614#ifdef CONFIG_PM
1615static int snd_es18xx_suspend(snd_card_t *card, pm_message_t state)
1616{
1617 es18xx_t *chip = card->pm_private_data;
1618
1619 snd_pcm_suspend_all(chip->pcm);
1620
1621 /* power down */
1622 chip->pm_reg = (unsigned char)snd_es18xx_read(chip, ES18XX_PM);
1623 chip->pm_reg |= (ES18XX_PM_FM | ES18XX_PM_SUS);
1624 snd_es18xx_write(chip, ES18XX_PM, chip->pm_reg);
1625 snd_es18xx_write(chip, ES18XX_PM, chip->pm_reg ^= ES18XX_PM_SUS);
1626
1627 return 0;
1628}
1629
1630static int snd_es18xx_resume(snd_card_t *card)
1631{
1632 es18xx_t *chip = card->pm_private_data;
1633
1634 /* restore PM register, we won't wake till (not 0x07) i/o activity though */
1635 snd_es18xx_write(chip, ES18XX_PM, chip->pm_reg ^= ES18XX_PM_FM);
1636
1637 return 0;
1638}
1639#endif /* CONFIG_PM */
1640
1641static int snd_es18xx_free(es18xx_t *chip)
1642{
1643 if (chip->res_port) {
1644 release_resource(chip->res_port);
1645 kfree_nocheck(chip->res_port);
1646 }
1647 if (chip->res_ctrl_port) {
1648 release_resource(chip->res_ctrl_port);
1649 kfree_nocheck(chip->res_ctrl_port);
1650 }
1651 if (chip->res_mpu_port) {
1652 release_resource(chip->res_mpu_port);
1653 kfree_nocheck(chip->res_mpu_port);
1654 }
1655 if (chip->irq >= 0)
1656 free_irq(chip->irq, (void *) chip);
1657 if (chip->dma1 >= 0) {
1658 disable_dma(chip->dma1);
1659 free_dma(chip->dma1);
1660 }
1661 if (chip->dma2 >= 0 && chip->dma1 != chip->dma2) {
1662 disable_dma(chip->dma2);
1663 free_dma(chip->dma2);
1664 }
1665 kfree(chip);
1666 return 0;
1667}
1668
1669static int snd_es18xx_dev_free(snd_device_t *device)
1670{
1671 es18xx_t *chip = device->device_data;
1672 return snd_es18xx_free(chip);
1673}
1674
1675static int __devinit snd_es18xx_new_device(snd_card_t * card,
1676 unsigned long port,
1677 unsigned long mpu_port,
1678 unsigned long fm_port,
1679 int irq, int dma1, int dma2,
1680 es18xx_t ** rchip)
1681{
1682 es18xx_t *chip;
1683 static snd_device_ops_t ops = {
1684 .dev_free = snd_es18xx_dev_free,
1685 };
1686 int err;
1687
1688 *rchip = NULL;
1689 chip = kcalloc(1, sizeof(*chip), GFP_KERNEL);
1690 if (chip == NULL)
1691 return -ENOMEM;
1692 spin_lock_init(&chip->reg_lock);
1693 spin_lock_init(&chip->mixer_lock);
1694 spin_lock_init(&chip->ctrl_lock);
1695 chip->card = card;
1696 chip->port = port;
1697 chip->mpu_port = mpu_port;
1698 chip->fm_port = fm_port;
1699 chip->irq = -1;
1700 chip->dma1 = -1;
1701 chip->dma2 = -1;
1702 chip->audio2_vol = 0x00;
1703 chip->active = 0;
1704
1705 if ((chip->res_port = request_region(port, 16, "ES18xx")) == NULL) {
1706 snd_es18xx_free(chip);
1707 snd_printk(KERN_ERR PFX "unable to grap ports 0x%lx-0x%lx\n", port, port + 16 - 1);
1708 return -EBUSY;
1709 }
1710
1711 if (request_irq(irq, snd_es18xx_interrupt, SA_INTERRUPT, "ES18xx", (void *) chip)) {
1712 snd_es18xx_free(chip);
1713 snd_printk(KERN_ERR PFX "unable to grap IRQ %d\n", irq);
1714 return -EBUSY;
1715 }
1716 chip->irq = irq;
1717
1718 if (request_dma(dma1, "ES18xx DMA 1")) {
1719 snd_es18xx_free(chip);
1720 snd_printk(KERN_ERR PFX "unable to grap DMA1 %d\n", dma1);
1721 return -EBUSY;
1722 }
1723 chip->dma1 = dma1;
1724
1725 if (dma2 != dma1 && request_dma(dma2, "ES18xx DMA 2")) {
1726 snd_es18xx_free(chip);
1727 snd_printk(KERN_ERR PFX "unable to grap DMA2 %d\n", dma2);
1728 return -EBUSY;
1729 }
1730 chip->dma2 = dma2;
1731
1732 if (snd_es18xx_probe(chip) < 0) {
1733 snd_es18xx_free(chip);
1734 return -ENODEV;
1735 }
1736 if ((err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops)) < 0) {
1737 snd_es18xx_free(chip);
1738 return err;
1739 }
1740 *rchip = chip;
1741 return 0;
1742}
1743
1744static int __devinit snd_es18xx_mixer(es18xx_t *chip)
1745{
1746 snd_card_t *card;
1747 int err;
1748 unsigned int idx;
1749
1750 card = chip->card;
1751
1752 strcpy(card->mixername, chip->pcm->name);
1753
1754 for (idx = 0; idx < ARRAY_SIZE(snd_es18xx_base_controls); idx++) {
1755 snd_kcontrol_t *kctl;
1756 kctl = snd_ctl_new1(&snd_es18xx_base_controls[idx], chip);
1757 if (chip->caps & ES18XX_HWV) {
1758 switch (idx) {
1759 case 0:
1760 chip->master_volume = kctl;
1761 kctl->private_free = snd_es18xx_hwv_free;
1762 break;
1763 case 1:
1764 chip->master_switch = kctl;
1765 kctl->private_free = snd_es18xx_hwv_free;
1766 break;
1767 }
1768 }
1769 if ((err = snd_ctl_add(card, kctl)) < 0)
1770 return err;
1771 }
1772 if (chip->caps & ES18XX_PCM2) {
1773 for (idx = 0; idx < ARRAY_SIZE(snd_es18xx_pcm2_controls); idx++) {
1774 if ((err = snd_ctl_add(card, snd_ctl_new1(&snd_es18xx_pcm2_controls[idx], chip))) < 0)
1775 return err;
1776 }
1777 } else {
1778 for (idx = 0; idx < ARRAY_SIZE(snd_es18xx_pcm1_controls); idx++) {
1779 if ((err = snd_ctl_add(card, snd_ctl_new1(&snd_es18xx_pcm1_controls[idx], chip))) < 0)
1780 return err;
1781 }
1782 }
1783
1784 if (chip->caps & ES18XX_MONO) {
1785 if ((err = snd_ctl_add(card, snd_ctl_new1(&snd_es18xx_mono_in_control, chip))) < 0)
1786 return err;
1787 }
1788 if (chip->caps & ES18XX_RECMIX) {
1789 for (idx = 0; idx < ARRAY_SIZE(snd_es18xx_recmix_controls); idx++) {
1790 if ((err = snd_ctl_add(card, snd_ctl_new1(&snd_es18xx_recmix_controls[idx], chip))) < 0)
1791 return err;
1792 }
1793 }
1794 switch (chip->version) {
1795 default:
1796 if ((err = snd_ctl_add(card, snd_ctl_new1(&snd_es18xx_micpre1_control, chip))) < 0)
1797 return err;
1798 break;
1799 case 0x1869:
1800 case 0x1879:
1801 if ((err = snd_ctl_add(card, snd_ctl_new1(&snd_es18xx_micpre2_control, chip))) < 0)
1802 return err;
1803 break;
1804 }
1805 if (chip->caps & ES18XX_SPATIALIZER) {
1806 for (idx = 0; idx < ARRAY_SIZE(snd_es18xx_spatializer_controls); idx++) {
1807 if ((err = snd_ctl_add(card, snd_ctl_new1(&snd_es18xx_spatializer_controls[idx], chip))) < 0)
1808 return err;
1809 }
1810 }
1811 if (chip->caps & ES18XX_HWV) {
1812 for (idx = 0; idx < ARRAY_SIZE(snd_es18xx_hw_volume_controls); idx++) {
1813 snd_kcontrol_t *kctl;
1814 kctl = snd_ctl_new1(&snd_es18xx_hw_volume_controls[idx], chip);
1815 if (idx == 0)
1816 chip->hw_volume = kctl;
1817 else
1818 chip->hw_switch = kctl;
1819 kctl->private_free = snd_es18xx_hwv_free;
1820 if ((err = snd_ctl_add(card, kctl)) < 0)
1821 return err;
1822
1823 }
1824 }
1825 return 0;
1826}
1827
1828
1829/* Card level */
1830
1831MODULE_AUTHOR("Christian Fischbach <fishbach@pool.informatik.rwth-aachen.de>, Abramo Bagnara <abramo@alsa-project.org>");
1832MODULE_DESCRIPTION("ESS ES18xx AudioDrive");
1833MODULE_LICENSE("GPL");
1834MODULE_SUPPORTED_DEVICE("{{ESS,ES1868 PnP AudioDrive},"
1835 "{ESS,ES1869 PnP AudioDrive},"
1836 "{ESS,ES1878 PnP AudioDrive},"
1837 "{ESS,ES1879 PnP AudioDrive},"
1838 "{ESS,ES1887 PnP AudioDrive},"
1839 "{ESS,ES1888 PnP AudioDrive},"
1840 "{ESS,ES1887 AudioDrive},"
1841 "{ESS,ES1888 AudioDrive}}");
1842
1843static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-MAX */
1844static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* ID for this card */
1845static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_ISAPNP; /* Enable this card */
1846#ifdef CONFIG_PNP
1847static int isapnp[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 1};
1848#endif
1849static long port[SNDRV_CARDS] = SNDRV_DEFAULT_PORT; /* 0x220,0x240,0x260,0x280 */
1850#ifndef CONFIG_PNP
1851static long mpu_port[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = -1};
1852#else
1853static long mpu_port[SNDRV_CARDS] = SNDRV_DEFAULT_PORT;
1854#endif
1855static long fm_port[SNDRV_CARDS] = SNDRV_DEFAULT_PORT;
1856static int irq[SNDRV_CARDS] = SNDRV_DEFAULT_IRQ; /* 5,7,9,10 */
1857static int dma1[SNDRV_CARDS] = SNDRV_DEFAULT_DMA; /* 0,1,3 */
1858static int dma2[SNDRV_CARDS] = SNDRV_DEFAULT_DMA; /* 0,1,3 */
1859
1860module_param_array(index, int, NULL, 0444);
1861MODULE_PARM_DESC(index, "Index value for ES18xx soundcard.");
1862module_param_array(id, charp, NULL, 0444);
1863MODULE_PARM_DESC(id, "ID string for ES18xx soundcard.");
1864module_param_array(enable, bool, NULL, 0444);
1865MODULE_PARM_DESC(enable, "Enable ES18xx soundcard.");
1866#ifdef CONFIG_PNP
1867module_param_array(isapnp, bool, NULL, 0444);
1868MODULE_PARM_DESC(isapnp, "PnP detection for specified soundcard.");
1869#endif
1870module_param_array(port, long, NULL, 0444);
1871MODULE_PARM_DESC(port, "Port # for ES18xx driver.");
1872module_param_array(mpu_port, long, NULL, 0444);
1873MODULE_PARM_DESC(mpu_port, "MPU-401 port # for ES18xx driver.");
1874module_param_array(fm_port, long, NULL, 0444);
1875MODULE_PARM_DESC(fm_port, "FM port # for ES18xx driver.");
1876module_param_array(irq, int, NULL, 0444);
1877MODULE_PARM_DESC(irq, "IRQ # for ES18xx driver.");
1878module_param_array(dma1, int, NULL, 0444);
1879MODULE_PARM_DESC(dma1, "DMA 1 # for ES18xx driver.");
1880module_param_array(dma2, int, NULL, 0444);
1881MODULE_PARM_DESC(dma2, "DMA 2 # for ES18xx driver.");
1882
1883struct snd_audiodrive {
1884#ifdef CONFIG_PNP
1885 struct pnp_dev *dev;
1886 struct pnp_dev *devc;
1887#endif
1888};
1889
1890static snd_card_t *snd_audiodrive_legacy[SNDRV_CARDS] = SNDRV_DEFAULT_PTR;
1891
1892#ifdef CONFIG_PNP
1893
1894static struct pnp_card_device_id snd_audiodrive_pnpids[] = {
1895 /* ESS 1868 (integrated on Compaq dual P-Pro motherboard and Genius 18PnP 3D) */
1896 { .id = "ESS1868", .devs = { { "ESS1868" }, { "ESS0000" } } },
1897 /* ESS 1868 (integrated on Maxisound Cards) */
1898 { .id = "ESS1868", .devs = { { "ESS8601" }, { "ESS8600" } } },
1899 /* ESS 1868 (integrated on Maxisound Cards) */
1900 { .id = "ESS1868", .devs = { { "ESS8611" }, { "ESS8610" } } },
1901 /* ESS ES1869 Plug and Play AudioDrive */
1902 { .id = "ESS0003", .devs = { { "ESS1869" }, { "ESS0006" } } },
1903 /* ESS 1869 */
1904 { .id = "ESS1869", .devs = { { "ESS1869" }, { "ESS0006" } } },
1905 /* ESS 1878 */
1906 { .id = "ESS1878", .devs = { { "ESS1878" }, { "ESS0004" } } },
1907 /* ESS 1879 */
1908 { .id = "ESS1879", .devs = { { "ESS1879" }, { "ESS0009" } } },
1909 /* --- */
1910 { .id = "" } /* end */
1911};
1912
1913MODULE_DEVICE_TABLE(pnp_card, snd_audiodrive_pnpids);
1914
1915static int __devinit snd_audiodrive_pnp(int dev, struct snd_audiodrive *acard,
1916 struct pnp_card_link *card,
1917 const struct pnp_card_device_id *id)
1918{
1919 struct pnp_dev *pdev;
1920 struct pnp_resource_table * cfg = kmalloc(sizeof(struct pnp_resource_table), GFP_KERNEL);
1921 int err;
1922
1923 if (!cfg)
1924 return -ENOMEM;
1925 acard->dev = pnp_request_card_device(card, id->devs[0].id, NULL);
1926 if (acard->dev == NULL) {
1927 kfree(cfg);
1928 return -EBUSY;
1929 }
1930 acard->devc = pnp_request_card_device(card, id->devs[1].id, NULL);
1931 if (acard->devc == NULL) {
1932 kfree(cfg);
1933 return -EBUSY;
1934 }
1935 /* Control port initialization */
1936 err = pnp_activate_dev(acard->devc);
1937 if (err < 0) {
1938 snd_printk(KERN_ERR PFX "PnP control configure failure (out of resources?)\n");
1939 return -EAGAIN;
1940 }
1941 snd_printdd("pnp: port=0x%lx\n", pnp_port_start(acard->devc, 0));
1942 /* PnP initialization */
1943 pdev = acard->dev;
1944 pnp_init_resource_table(cfg);
1945 if (port[dev] != SNDRV_AUTO_PORT)
1946 pnp_resource_change(&cfg->port_resource[0], port[dev], 16);
1947 if (fm_port[dev] != SNDRV_AUTO_PORT)
1948 pnp_resource_change(&cfg->port_resource[1], fm_port[dev], 4);
1949 if (mpu_port[dev] != SNDRV_AUTO_PORT)
1950 pnp_resource_change(&cfg->port_resource[2], mpu_port[dev], 2);
1951 if (dma1[dev] != SNDRV_AUTO_DMA)
1952 pnp_resource_change(&cfg->dma_resource[0], dma1[dev], 1);
1953 if (dma2[dev] != SNDRV_AUTO_DMA)
1954 pnp_resource_change(&cfg->dma_resource[1], dma2[dev], 1);
1955 if (irq[dev] != SNDRV_AUTO_IRQ)
1956 pnp_resource_change(&cfg->irq_resource[0], irq[dev], 1);
1957 err = pnp_manual_config_dev(pdev, cfg, 0);
1958 if (err < 0)
1959 snd_printk(KERN_ERR PFX "PnP manual resources are invalid, using auto config\n");
1960 err = pnp_activate_dev(pdev);
1961 if (err < 0) {
1962 snd_printk(KERN_ERR PFX "PnP configure failure (out of resources?)\n");
1963 kfree(cfg);
1964 return -EBUSY;
1965 }
1966 /* ok. hack using Vendor-Defined Card-Level registers */
1967 /* skip csn and logdev initialization - already done in isapnp_configure */
1968 if (pnp_device_is_isapnp(pdev)) {
1969 isapnp_cfg_begin(isapnp_card_number(pdev), isapnp_csn_number(pdev));
1970 isapnp_write_byte(0x27, pnp_irq(pdev, 0)); /* Hardware Volume IRQ Number */
1971 if (mpu_port[dev] != SNDRV_AUTO_PORT)
1972 isapnp_write_byte(0x28, pnp_irq(pdev, 0)); /* MPU-401 IRQ Number */
1973 isapnp_write_byte(0x72, pnp_irq(pdev, 0)); /* second IRQ */
1974 isapnp_cfg_end();
1975 } else {
1976 snd_printk(KERN_ERR PFX "unable to install ISA PnP hack, expect malfunction\n");
1977 }
1978 port[dev] = pnp_port_start(pdev, 0);
1979 fm_port[dev] = pnp_port_start(pdev, 1);
1980 mpu_port[dev] = pnp_port_start(pdev, 2);
1981 dma1[dev] = pnp_dma(pdev, 0);
1982 dma2[dev] = pnp_dma(pdev, 1);
1983 irq[dev] = pnp_irq(pdev, 0);
1984 snd_printdd("PnP ES18xx: port=0x%lx, fm port=0x%lx, mpu port=0x%lx\n", port[dev], fm_port[dev], mpu_port[dev]);
1985 snd_printdd("PnP ES18xx: dma1=%i, dma2=%i, irq=%i\n", dma1[dev], dma2[dev], irq[dev]);
1986 kfree(cfg);
1987 return 0;
1988}
1989#endif /* CONFIG_PNP */
1990
1991static int __devinit snd_audiodrive_probe(int dev, struct pnp_card_link *pcard,
1992 const struct pnp_card_device_id *pid)
1993{
1994 static int possible_irqs[] = {5, 9, 10, 7, 11, 12, -1};
1995 static int possible_dmas[] = {1, 0, 3, 5, -1};
1996 int xirq, xdma1, xdma2;
1997 snd_card_t *card;
1998 struct snd_audiodrive *acard;
1999 snd_rawmidi_t *rmidi = NULL;
2000 es18xx_t *chip;
2001 opl3_t *opl3;
2002 int err;
2003
2004 card = snd_card_new(index[dev], id[dev], THIS_MODULE,
2005 sizeof(struct snd_audiodrive));
2006 if (card == NULL)
2007 return -ENOMEM;
2008 acard = (struct snd_audiodrive *)card->private_data;
2009#ifdef CONFIG_PNP
2010 if (isapnp[dev]) {
2011 if ((err = snd_audiodrive_pnp(dev, acard, pcard, pid)) < 0) {
2012 snd_card_free(card);
2013 return err;
2014 }
2015 snd_card_set_dev(card, &pcard->card->dev);
2016 }
2017#endif
2018
2019 xirq = irq[dev];
2020 if (xirq == SNDRV_AUTO_IRQ) {
2021 if ((xirq = snd_legacy_find_free_irq(possible_irqs)) < 0) {
2022 snd_card_free(card);
2023 snd_printk("unable to find a free IRQ\n");
2024 return -EBUSY;
2025 }
2026 }
2027 xdma1 = dma1[dev];
2028 if (xdma1 == SNDRV_AUTO_DMA) {
2029 if ((xdma1 = snd_legacy_find_free_dma(possible_dmas)) < 0) {
2030 snd_card_free(card);
2031 snd_printk("unable to find a free DMA1\n");
2032 return -EBUSY;
2033 }
2034 }
2035 xdma2 = dma2[dev];
2036 if (xdma2 == SNDRV_AUTO_DMA) {
2037 if ((xdma2 = snd_legacy_find_free_dma(possible_dmas)) < 0) {
2038 snd_card_free(card);
2039 snd_printk("unable to find a free DMA2\n");
2040 return -EBUSY;
2041 }
2042 }
2043
2044 if ((err = snd_es18xx_new_device(card,
2045 port[dev],
2046 mpu_port[dev],
2047 fm_port[dev],
2048 xirq, xdma1, xdma2,
2049 &chip)) < 0) {
2050 snd_card_free(card);
2051 return err;
2052 }
2053
2054 sprintf(card->driver, "ES%x", chip->version);
2055 sprintf(card->shortname, "ESS AudioDrive ES%x", chip->version);
2056 if (xdma1 != xdma2)
2057 sprintf(card->longname, "%s at 0x%lx, irq %d, dma1 %d, dma2 %d",
2058 card->shortname,
2059 chip->port,
2060 xirq, xdma1, xdma2);
2061 else
2062 sprintf(card->longname, "%s at 0x%lx, irq %d, dma %d",
2063 card->shortname,
2064 chip->port,
2065 xirq, xdma1);
2066
2067 if ((err = snd_es18xx_pcm(chip, 0, NULL)) < 0) {
2068 snd_card_free(card);
2069 return err;
2070 }
2071 if ((err = snd_es18xx_mixer(chip)) < 0) {
2072 snd_card_free(card);
2073 return err;
2074 }
2075
2076 if (fm_port[dev] > 0 && fm_port[dev] != SNDRV_AUTO_PORT) {
2077 if (snd_opl3_create(card, chip->fm_port, chip->fm_port + 2, OPL3_HW_OPL3, 0, &opl3) < 0) {
2078 snd_printk(KERN_ERR PFX "opl3 not detected at 0x%lx\n", chip->fm_port);
2079 } else {
2080 if ((err = snd_opl3_hwdep_new(opl3, 0, 1, NULL)) < 0) {
2081 snd_card_free(card);
2082 return err;
2083 }
2084 }
2085 }
2086
2087 if (mpu_port[dev] > 0 && mpu_port[dev] != SNDRV_AUTO_PORT) {
2088 if ((err = snd_mpu401_uart_new(card, 0, MPU401_HW_ES18XX,
2089 chip->mpu_port, 0,
2090 xirq, 0,
2091 &rmidi)) < 0) {
2092 snd_card_free(card);
2093 return err;
2094 }
2095 chip->rmidi = rmidi;
2096 }
2097
2098 /* Power Management */
2099 snd_card_set_isa_pm_callback(card, snd_es18xx_suspend, snd_es18xx_resume, chip);
2100
2101 if ((err = snd_card_register(card)) < 0) {
2102 snd_card_free(card);
2103 return err;
2104 }
2105 if (pcard)
2106 pnp_set_card_drvdata(pcard, card);
2107 else
2108 snd_audiodrive_legacy[dev] = card;
2109 return 0;
2110}
2111
2112static int __devinit snd_audiodrive_probe_legacy_port(unsigned long xport)
2113{
2114 static int dev;
2115 int res;
2116
2117 for ( ; dev < SNDRV_CARDS; dev++) {
2118 if (!enable[dev] || port[dev] != SNDRV_AUTO_PORT)
2119 continue;
2120#ifdef CONFIG_PNP
2121 if (isapnp[dev])
2122 continue;
2123#endif
2124 port[dev] = xport;
2125 res = snd_audiodrive_probe(dev, NULL, NULL);
2126 if (res < 0)
2127 port[dev] = SNDRV_AUTO_PORT;
2128 return res;
2129 }
2130 return -ENODEV;
2131}
2132
2133
2134#ifdef CONFIG_PNP
2135static int __devinit snd_audiodrive_pnp_detect(struct pnp_card_link *card,
2136 const struct pnp_card_device_id *id)
2137{
2138 static int dev;
2139 int res;
2140
2141 for ( ; dev < SNDRV_CARDS; dev++) {
2142 if (!enable[dev] || !isapnp[dev])
2143 continue;
2144 res = snd_audiodrive_probe(dev, card, id);
2145 if (res < 0)
2146 return res;
2147 dev++;
2148 return 0;
2149 }
2150
2151 return -ENODEV;
2152}
2153
2154static void __devexit snd_audiodrive_pnp_remove(struct pnp_card_link * pcard)
2155{
2156 snd_card_t *card = (snd_card_t *) pnp_get_card_drvdata(pcard);
2157
2158 snd_card_disconnect(card);
2159 snd_card_free_in_thread(card);
2160}
2161
2162static struct pnp_card_driver es18xx_pnpc_driver = {
2163 .flags = PNP_DRIVER_RES_DISABLE,
2164 .name = "es18xx",
2165 .id_table = snd_audiodrive_pnpids,
2166 .probe = snd_audiodrive_pnp_detect,
2167 .remove = __devexit_p(snd_audiodrive_pnp_remove),
2168};
2169#endif /* CONFIG_PNP */
2170
2171static int __init alsa_card_es18xx_init(void)
2172{
2173 static unsigned long possible_ports[] = {0x220, 0x240, 0x260, 0x280, -1};
2174 int dev, cards = 0, i;
2175
2176 /* legacy non-auto cards at first */
2177 for (dev = 0; dev < SNDRV_CARDS; dev++) {
2178 if (!enable[dev] || port[dev] == SNDRV_AUTO_PORT)
2179 continue;
2180#ifdef CONFIG_PNP
2181 if (isapnp[dev])
2182 continue;
2183#endif
2184 if (snd_audiodrive_probe(dev, NULL, NULL) >= 0)
2185 cards++;
2186 }
2187 /* legacy auto configured cards */
2188 i = snd_legacy_auto_probe(possible_ports, snd_audiodrive_probe_legacy_port);
2189 if (i > 0)
2190 cards += i;
2191
2192#ifdef CONFIG_PNP
2193 /* ISA PnP cards at last */
2194 i = pnp_register_card_driver(&es18xx_pnpc_driver);
2195 if (i > 0)
2196 cards += i;
2197
2198#endif
2199 if(!cards) {
2200#ifdef CONFIG_PNP
2201 pnp_unregister_card_driver(&es18xx_pnpc_driver);
2202#endif
2203#ifdef MODULE
2204 snd_printk(KERN_ERR "ESS AudioDrive ES18xx soundcard not found or device busy\n");
2205#endif
2206 return -ENODEV;
2207 }
2208 return 0;
2209}
2210
2211static void __exit alsa_card_es18xx_exit(void)
2212{
2213 int idx;
2214
2215#ifdef CONFIG_PNP
2216 /* PnP cards first */
2217 pnp_unregister_card_driver(&es18xx_pnpc_driver);
2218#endif
2219 for(idx = 0; idx < SNDRV_CARDS; idx++)
2220 snd_card_free(snd_audiodrive_legacy[idx]);
2221}
2222
2223module_init(alsa_card_es18xx_init)
2224module_exit(alsa_card_es18xx_exit)
diff --git a/sound/isa/gus/Makefile b/sound/isa/gus/Makefile
new file mode 100644
index 000000000000..bae5dbd6c8e5
--- /dev/null
+++ b/sound/isa/gus/Makefile
@@ -0,0 +1,36 @@
1#
2# Makefile for ALSA
3# Copyright (c) 2001 by Jaroslav Kysela <perex@suse.cz>
4#
5
6snd-gus-lib-objs := gus_main.o \
7 gus_io.o gus_irq.o gus_timer.o \
8 gus_mem.o gus_mem_proc.o gus_dram.o gus_dma.o gus_volume.o \
9 gus_pcm.o gus_mixer.o \
10 gus_uart.o \
11 gus_reset.o
12snd-gus-synth-objs := gus_synth.o gus_sample.o gus_simple.o gus_instr.o
13
14snd-gusclassic-objs := gusclassic.o
15snd-gusextreme-objs := gusextreme.o
16snd-gusmax-objs := gusmax.o
17snd-interwave-objs := interwave.o
18snd-interwave-stb-objs := interwave-stb.o
19
20#
21# this function returns:
22# "m" - CONFIG_SND_SEQUENCER is m
23# <empty string> - CONFIG_SND_SEQUENCER is undefined
24# otherwise parameter #1 value
25#
26sequencer = $(if $(subst y,,$(CONFIG_SND_SEQUENCER)),$(if $(1),m),$(if $(CONFIG_SND_SEQUENCER),$(1)))
27
28# Toplevel Module Dependency
29obj-$(CONFIG_SND_GUSCLASSIC) += snd-gusclassic.o snd-gus-lib.o
30obj-$(CONFIG_SND_GUSMAX) += snd-gusmax.o snd-gus-lib.o
31obj-$(CONFIG_SND_GUSEXTREME) += snd-gusextreme.o snd-gus-lib.o
32obj-$(CONFIG_SND_INTERWAVE) += snd-interwave.o snd-gus-lib.o
33obj-$(CONFIG_SND_INTERWAVE_STB) += snd-interwave-stb.o snd-gus-lib.o
34obj-$(call sequencer,$(CONFIG_SND_GUS_SYNTH)) += snd-gus-synth.o
35
36obj-m := $(sort $(obj-m))
diff --git a/sound/isa/gus/gus_dma.c b/sound/isa/gus/gus_dma.c
new file mode 100644
index 000000000000..de4b56d80b35
--- /dev/null
+++ b/sound/isa/gus/gus_dma.c
@@ -0,0 +1,244 @@
1/*
2 * Routines for GF1 DMA control
3 * Copyright (c) by Jaroslav Kysela <perex@suse.cz>
4 *
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 *
20 */
21
22#include <sound/driver.h>
23#include <asm/dma.h>
24#include <linux/slab.h>
25#include <sound/core.h>
26#include <sound/gus.h>
27
28static void snd_gf1_dma_ack(snd_gus_card_t * gus)
29{
30 unsigned long flags;
31
32 spin_lock_irqsave(&gus->reg_lock, flags);
33 snd_gf1_write8(gus, SNDRV_GF1_GB_DRAM_DMA_CONTROL, 0x00);
34 snd_gf1_look8(gus, SNDRV_GF1_GB_DRAM_DMA_CONTROL);
35 spin_unlock_irqrestore(&gus->reg_lock, flags);
36}
37
38static void snd_gf1_dma_program(snd_gus_card_t * gus,
39 unsigned int addr,
40 unsigned long buf_addr,
41 unsigned int count,
42 unsigned int cmd)
43{
44 unsigned long flags;
45 unsigned int address;
46 unsigned char dma_cmd;
47 unsigned int address_high;
48
49 // snd_printk("dma_transfer: addr=0x%x, buf=0x%lx, count=0x%x\n", addr, (long) buf, count);
50
51 if (gus->gf1.dma1 > 3) {
52 if (gus->gf1.enh_mode) {
53 address = addr >> 1;
54 } else {
55 if (addr & 0x1f) {
56 snd_printd("snd_gf1_dma_transfer: unaligned address (0x%x)?\n", addr);
57 return;
58 }
59 address = (addr & 0x000c0000) | ((addr & 0x0003ffff) >> 1);
60 }
61 } else {
62 address = addr;
63 }
64
65 dma_cmd = SNDRV_GF1_DMA_ENABLE | (unsigned short) cmd;
66#if 0
67 dma_cmd |= 0x08;
68#endif
69 if (dma_cmd & SNDRV_GF1_DMA_16BIT) {
70 count++;
71 count &= ~1; /* align */
72 }
73 if (gus->gf1.dma1 > 3) {
74 dma_cmd |= SNDRV_GF1_DMA_WIDTH16;
75 count++;
76 count &= ~1; /* align */
77 }
78 snd_gf1_dma_ack(gus);
79 snd_dma_program(gus->gf1.dma1, buf_addr, count, dma_cmd & SNDRV_GF1_DMA_READ ? DMA_MODE_READ : DMA_MODE_WRITE);
80#if 0
81 snd_printk("address = 0x%x, count = 0x%x, dma_cmd = 0x%x\n", address << 1, count, dma_cmd);
82#endif
83 spin_lock_irqsave(&gus->reg_lock, flags);
84 if (gus->gf1.enh_mode) {
85 address_high = ((address >> 16) & 0x000000f0) | (address & 0x0000000f);
86 snd_gf1_write16(gus, SNDRV_GF1_GW_DRAM_DMA_LOW, (unsigned short) (address >> 4));
87 snd_gf1_write8(gus, SNDRV_GF1_GB_DRAM_DMA_HIGH, (unsigned char) address_high);
88 } else
89 snd_gf1_write16(gus, SNDRV_GF1_GW_DRAM_DMA_LOW, (unsigned short) (address >> 4));
90 snd_gf1_write8(gus, SNDRV_GF1_GB_DRAM_DMA_CONTROL, dma_cmd);
91 spin_unlock_irqrestore(&gus->reg_lock, flags);
92}
93
94static snd_gf1_dma_block_t *snd_gf1_dma_next_block(snd_gus_card_t * gus)
95{
96 snd_gf1_dma_block_t *block;
97
98 /* PCM block have bigger priority than synthesizer one */
99 if (gus->gf1.dma_data_pcm) {
100 block = gus->gf1.dma_data_pcm;
101 if (gus->gf1.dma_data_pcm_last == block) {
102 gus->gf1.dma_data_pcm =
103 gus->gf1.dma_data_pcm_last = NULL;
104 } else {
105 gus->gf1.dma_data_pcm = block->next;
106 }
107 } else if (gus->gf1.dma_data_synth) {
108 block = gus->gf1.dma_data_synth;
109 if (gus->gf1.dma_data_synth_last == block) {
110 gus->gf1.dma_data_synth =
111 gus->gf1.dma_data_synth_last = NULL;
112 } else {
113 gus->gf1.dma_data_synth = block->next;
114 }
115 } else {
116 block = NULL;
117 }
118 if (block) {
119 gus->gf1.dma_ack = block->ack;
120 gus->gf1.dma_private_data = block->private_data;
121 }
122 return block;
123}
124
125
126static void snd_gf1_dma_interrupt(snd_gus_card_t * gus)
127{
128 snd_gf1_dma_block_t *block;
129
130 snd_gf1_dma_ack(gus);
131 if (gus->gf1.dma_ack)
132 gus->gf1.dma_ack(gus, gus->gf1.dma_private_data);
133 spin_lock(&gus->dma_lock);
134 if (gus->gf1.dma_data_pcm == NULL &&
135 gus->gf1.dma_data_synth == NULL) {
136 gus->gf1.dma_ack = NULL;
137 gus->gf1.dma_flags &= ~SNDRV_GF1_DMA_TRIGGER;
138 spin_unlock(&gus->dma_lock);
139 return;
140 }
141 block = snd_gf1_dma_next_block(gus);
142 spin_unlock(&gus->dma_lock);
143 snd_gf1_dma_program(gus, block->addr, block->buf_addr, block->count, (unsigned short) block->cmd);
144 kfree(block);
145#if 0
146 printk("program dma (IRQ) - addr = 0x%x, buffer = 0x%lx, count = 0x%x, cmd = 0x%x\n", addr, (long) buffer, count, cmd);
147#endif
148}
149
150int snd_gf1_dma_init(snd_gus_card_t * gus)
151{
152 down(&gus->dma_mutex);
153 gus->gf1.dma_shared++;
154 if (gus->gf1.dma_shared > 1) {
155 up(&gus->dma_mutex);
156 return 0;
157 }
158 gus->gf1.interrupt_handler_dma_write = snd_gf1_dma_interrupt;
159 gus->gf1.dma_data_pcm =
160 gus->gf1.dma_data_pcm_last =
161 gus->gf1.dma_data_synth =
162 gus->gf1.dma_data_synth_last = NULL;
163 up(&gus->dma_mutex);
164 return 0;
165}
166
167int snd_gf1_dma_done(snd_gus_card_t * gus)
168{
169 snd_gf1_dma_block_t *block;
170
171 down(&gus->dma_mutex);
172 gus->gf1.dma_shared--;
173 if (!gus->gf1.dma_shared) {
174 snd_dma_disable(gus->gf1.dma1);
175 snd_gf1_set_default_handlers(gus, SNDRV_GF1_HANDLER_DMA_WRITE);
176 snd_gf1_dma_ack(gus);
177 while ((block = gus->gf1.dma_data_pcm)) {
178 gus->gf1.dma_data_pcm = block->next;
179 kfree(block);
180 }
181 while ((block = gus->gf1.dma_data_synth)) {
182 gus->gf1.dma_data_synth = block->next;
183 kfree(block);
184 }
185 gus->gf1.dma_data_pcm_last =
186 gus->gf1.dma_data_synth_last = NULL;
187 }
188 up(&gus->dma_mutex);
189 return 0;
190}
191
192int snd_gf1_dma_transfer_block(snd_gus_card_t * gus,
193 snd_gf1_dma_block_t * __block,
194 int atomic,
195 int synth)
196{
197 unsigned long flags;
198 snd_gf1_dma_block_t *block;
199
200 block = kmalloc(sizeof(*block), atomic ? GFP_ATOMIC : GFP_KERNEL);
201 if (block == NULL) {
202 snd_printk("gf1: DMA transfer failure; not enough memory\n");
203 return -ENOMEM;
204 }
205 *block = *__block;
206 block->next = NULL;
207#if 0
208 printk("addr = 0x%x, buffer = 0x%lx, count = 0x%x, cmd = 0x%x\n", block->addr, (long) block->buffer, block->count, block->cmd);
209#endif
210#if 0
211 printk("gus->gf1.dma_data_pcm_last = 0x%lx\n", (long)gus->gf1.dma_data_pcm_last);
212 printk("gus->gf1.dma_data_pcm = 0x%lx\n", (long)gus->gf1.dma_data_pcm);
213#endif
214 spin_lock_irqsave(&gus->dma_lock, flags);
215 if (synth) {
216 if (gus->gf1.dma_data_synth_last) {
217 gus->gf1.dma_data_synth_last->next = block;
218 gus->gf1.dma_data_synth_last = block;
219 } else {
220 gus->gf1.dma_data_synth =
221 gus->gf1.dma_data_synth_last = block;
222 }
223 } else {
224 if (gus->gf1.dma_data_pcm_last) {
225 gus->gf1.dma_data_pcm_last->next = block;
226 gus->gf1.dma_data_pcm_last = block;
227 } else {
228 gus->gf1.dma_data_pcm =
229 gus->gf1.dma_data_pcm_last = block;
230 }
231 }
232 if (!(gus->gf1.dma_flags & SNDRV_GF1_DMA_TRIGGER)) {
233 gus->gf1.dma_flags |= SNDRV_GF1_DMA_TRIGGER;
234 block = snd_gf1_dma_next_block(gus);
235 spin_unlock_irqrestore(&gus->dma_lock, flags);
236 if (block == NULL)
237 return 0;
238 snd_gf1_dma_program(gus, block->addr, block->buf_addr, block->count, (unsigned short) block->cmd);
239 kfree(block);
240 return 0;
241 }
242 spin_unlock_irqrestore(&gus->dma_lock, flags);
243 return 0;
244}
diff --git a/sound/isa/gus/gus_dram.c b/sound/isa/gus/gus_dram.c
new file mode 100644
index 000000000000..22120b868b5c
--- /dev/null
+++ b/sound/isa/gus/gus_dram.c
@@ -0,0 +1,103 @@
1/*
2 * Copyright (c) by Jaroslav Kysela <perex@suse.cz>
3 * DRAM access routines
4 *
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 *
20 */
21
22#include <sound/driver.h>
23#include <linux/time.h>
24#include <sound/core.h>
25#include <sound/gus.h>
26#include <sound/info.h>
27
28
29static int snd_gus_dram_poke(snd_gus_card_t *gus, char __user *_buffer,
30 unsigned int address, unsigned int size)
31{
32 unsigned long flags;
33 unsigned int size1, size2;
34 char buffer[256], *pbuffer;
35
36 while (size > 0) {
37 size1 = size > sizeof(buffer) ? sizeof(buffer) : size;
38 if (copy_from_user(buffer, _buffer, size1))
39 return -EFAULT;
40 if (gus->interwave) {
41 spin_lock_irqsave(&gus->reg_lock, flags);
42 snd_gf1_write8(gus, SNDRV_GF1_GB_MEMORY_CONTROL, 0x01);
43 snd_gf1_dram_addr(gus, address);
44 outsb(GUSP(gus, DRAM), buffer, size1);
45 spin_unlock_irqrestore(&gus->reg_lock, flags);
46 address += size1;
47 } else {
48 pbuffer = buffer;
49 size2 = size1;
50 while (size2--)
51 snd_gf1_poke(gus, address++, *pbuffer++);
52 }
53 size -= size1;
54 _buffer += size1;
55 }
56 return 0;
57}
58
59
60int snd_gus_dram_write(snd_gus_card_t *gus, char __user *buffer,
61 unsigned int address, unsigned int size)
62{
63 return snd_gus_dram_poke(gus, buffer, address, size);
64}
65
66static int snd_gus_dram_peek(snd_gus_card_t *gus, char __user *_buffer,
67 unsigned int address, unsigned int size,
68 int rom)
69{
70 unsigned long flags;
71 unsigned int size1, size2;
72 char buffer[256], *pbuffer;
73
74 while (size > 0) {
75 size1 = size > sizeof(buffer) ? sizeof(buffer) : size;
76 if (gus->interwave) {
77 spin_lock_irqsave(&gus->reg_lock, flags);
78 snd_gf1_write8(gus, SNDRV_GF1_GB_MEMORY_CONTROL, rom ? 0x03 : 0x01);
79 snd_gf1_dram_addr(gus, address);
80 insb(GUSP(gus, DRAM), buffer, size1);
81 snd_gf1_write8(gus, SNDRV_GF1_GB_MEMORY_CONTROL, 0x01);
82 spin_unlock_irqrestore(&gus->reg_lock, flags);
83 address += size1;
84 } else {
85 pbuffer = buffer;
86 size2 = size1;
87 while (size2--)
88 *pbuffer++ = snd_gf1_peek(gus, address++);
89 }
90 if (copy_to_user(_buffer, buffer, size1))
91 return -EFAULT;
92 size -= size1;
93 _buffer += size1;
94 }
95 return 0;
96}
97
98int snd_gus_dram_read(snd_gus_card_t *gus, char __user *buffer,
99 unsigned int address, unsigned int size,
100 int rom)
101{
102 return snd_gus_dram_peek(gus, buffer, address, size, rom);
103}
diff --git a/sound/isa/gus/gus_instr.c b/sound/isa/gus/gus_instr.c
new file mode 100644
index 000000000000..591a9a17feb5
--- /dev/null
+++ b/sound/isa/gus/gus_instr.c
@@ -0,0 +1,173 @@
1/*
2 * Routines for Gravis UltraSound soundcards - Synthesizer
3 * Copyright (c) by Jaroslav Kysela <perex@suse.cz>
4 *
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 *
20 */
21
22#include <sound/driver.h>
23#include <linux/time.h>
24#include <sound/core.h>
25#include <sound/gus.h>
26
27/*
28 *
29 */
30
31int snd_gus_iwffff_put_sample(void *private_data, iwffff_wave_t *wave,
32 char __user *data, long len, int atomic)
33{
34 snd_gus_card_t *gus = private_data;
35 snd_gf1_mem_block_t *block;
36 int err;
37
38 if (wave->format & IWFFFF_WAVE_ROM)
39 return 0; /* it's probably ok - verify the address? */
40 if (wave->format & IWFFFF_WAVE_STEREO)
41 return -EINVAL; /* not supported */
42 block = snd_gf1_mem_alloc(&gus->gf1.mem_alloc,
43 SNDRV_GF1_MEM_OWNER_WAVE_IWFFFF,
44 NULL, wave->size,
45 wave->format & IWFFFF_WAVE_16BIT, 1,
46 wave->share_id);
47 if (block == NULL)
48 return -ENOMEM;
49 err = snd_gus_dram_write(gus, data,
50 block->ptr, wave->size);
51 if (err < 0) {
52 snd_gf1_mem_lock(&gus->gf1.mem_alloc, 0);
53 snd_gf1_mem_xfree(&gus->gf1.mem_alloc, block);
54 snd_gf1_mem_lock(&gus->gf1.mem_alloc, 1);
55 return err;
56 }
57 wave->address.memory = block->ptr;
58 return 0;
59}
60
61int snd_gus_iwffff_get_sample(void *private_data, iwffff_wave_t *wave,
62 char __user *data, long len, int atomic)
63{
64 snd_gus_card_t *gus = private_data;
65
66 return snd_gus_dram_read(gus, data, wave->address.memory, wave->size,
67 wave->format & IWFFFF_WAVE_ROM ? 1 : 0);
68}
69
70int snd_gus_iwffff_remove_sample(void *private_data, iwffff_wave_t *wave,
71 int atomic)
72{
73 snd_gus_card_t *gus = private_data;
74
75 if (wave->format & IWFFFF_WAVE_ROM)
76 return 0; /* it's probably ok - verify the address? */
77 return snd_gf1_mem_free(&gus->gf1.mem_alloc, wave->address.memory);
78}
79
80/*
81 *
82 */
83
84int snd_gus_gf1_put_sample(void *private_data, gf1_wave_t *wave,
85 char __user *data, long len, int atomic)
86{
87 snd_gus_card_t *gus = private_data;
88 snd_gf1_mem_block_t *block;
89 int err;
90
91 if (wave->format & GF1_WAVE_STEREO)
92 return -EINVAL; /* not supported */
93 block = snd_gf1_mem_alloc(&gus->gf1.mem_alloc,
94 SNDRV_GF1_MEM_OWNER_WAVE_GF1,
95 NULL, wave->size,
96 wave->format & GF1_WAVE_16BIT, 1,
97 wave->share_id);
98 if (block == NULL)
99 return -ENOMEM;
100 err = snd_gus_dram_write(gus, data,
101 block->ptr, wave->size);
102 if (err < 0) {
103 snd_gf1_mem_lock(&gus->gf1.mem_alloc, 0);
104 snd_gf1_mem_xfree(&gus->gf1.mem_alloc, block);
105 snd_gf1_mem_lock(&gus->gf1.mem_alloc, 1);
106 return err;
107 }
108 wave->address.memory = block->ptr;
109 return 0;
110}
111
112int snd_gus_gf1_get_sample(void *private_data, gf1_wave_t *wave,
113 char __user *data, long len, int atomic)
114{
115 snd_gus_card_t *gus = private_data;
116
117 return snd_gus_dram_read(gus, data, wave->address.memory, wave->size, 0);
118}
119
120int snd_gus_gf1_remove_sample(void *private_data, gf1_wave_t *wave,
121 int atomic)
122{
123 snd_gus_card_t *gus = private_data;
124
125 return snd_gf1_mem_free(&gus->gf1.mem_alloc, wave->address.memory);
126}
127
128/*
129 *
130 */
131
132int snd_gus_simple_put_sample(void *private_data, simple_instrument_t *instr,
133 char __user *data, long len, int atomic)
134{
135 snd_gus_card_t *gus = private_data;
136 snd_gf1_mem_block_t *block;
137 int err;
138
139 if (instr->format & SIMPLE_WAVE_STEREO)
140 return -EINVAL; /* not supported */
141 block = snd_gf1_mem_alloc(&gus->gf1.mem_alloc,
142 SNDRV_GF1_MEM_OWNER_WAVE_SIMPLE,
143 NULL, instr->size,
144 instr->format & SIMPLE_WAVE_16BIT, 1,
145 instr->share_id);
146 if (block == NULL)
147 return -ENOMEM;
148 err = snd_gus_dram_write(gus, data, block->ptr, instr->size);
149 if (err < 0) {
150 snd_gf1_mem_lock(&gus->gf1.mem_alloc, 0);
151 snd_gf1_mem_xfree(&gus->gf1.mem_alloc, block);
152 snd_gf1_mem_lock(&gus->gf1.mem_alloc, 1);
153 return err;
154 }
155 instr->address.memory = block->ptr;
156 return 0;
157}
158
159int snd_gus_simple_get_sample(void *private_data, simple_instrument_t *instr,
160 char __user *data, long len, int atomic)
161{
162 snd_gus_card_t *gus = private_data;
163
164 return snd_gus_dram_read(gus, data, instr->address.memory, instr->size, 0);
165}
166
167int snd_gus_simple_remove_sample(void *private_data, simple_instrument_t *instr,
168 int atomic)
169{
170 snd_gus_card_t *gus = private_data;
171
172 return snd_gf1_mem_free(&gus->gf1.mem_alloc, instr->address.memory);
173}
diff --git a/sound/isa/gus/gus_io.c b/sound/isa/gus/gus_io.c
new file mode 100644
index 000000000000..f0570f2bf75f
--- /dev/null
+++ b/sound/isa/gus/gus_io.c
@@ -0,0 +1,531 @@
1/*
2 * Copyright (c) by Jaroslav Kysela <perex@suse.cz>
3 * I/O routines for GF1/InterWave synthesizer chips
4 *
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 *
20 */
21
22#include <sound/driver.h>
23#include <linux/delay.h>
24#include <linux/time.h>
25#include <sound/core.h>
26#include <sound/gus.h>
27
28void snd_gf1_delay(snd_gus_card_t * gus)
29{
30 int i;
31
32 for (i = 0; i < 6; i++) {
33 mb();
34 inb(GUSP(gus, DRAM));
35 }
36}
37
38/*
39 * =======================================================================
40 */
41
42/*
43 * ok.. stop of control registers (wave & ramp) need some special things..
44 * big UltraClick (tm) elimination...
45 */
46
47static inline void __snd_gf1_ctrl_stop(snd_gus_card_t * gus, unsigned char reg)
48{
49 unsigned char value;
50
51 outb(reg | 0x80, gus->gf1.reg_regsel);
52 mb();
53 value = inb(gus->gf1.reg_data8);
54 mb();
55 outb(reg, gus->gf1.reg_regsel);
56 mb();
57 outb((value | 0x03) & ~(0x80 | 0x20), gus->gf1.reg_data8);
58 mb();
59}
60
61static inline void __snd_gf1_write8(snd_gus_card_t * gus,
62 unsigned char reg,
63 unsigned char data)
64{
65 outb(reg, gus->gf1.reg_regsel);
66 mb();
67 outb(data, gus->gf1.reg_data8);
68 mb();
69}
70
71static inline unsigned char __snd_gf1_look8(snd_gus_card_t * gus,
72 unsigned char reg)
73{
74 outb(reg, gus->gf1.reg_regsel);
75 mb();
76 return inb(gus->gf1.reg_data8);
77}
78
79static inline void __snd_gf1_write16(snd_gus_card_t * gus,
80 unsigned char reg, unsigned int data)
81{
82 outb(reg, gus->gf1.reg_regsel);
83 mb();
84 outw((unsigned short) data, gus->gf1.reg_data16);
85 mb();
86}
87
88static inline unsigned short __snd_gf1_look16(snd_gus_card_t * gus,
89 unsigned char reg)
90{
91 outb(reg, gus->gf1.reg_regsel);
92 mb();
93 return inw(gus->gf1.reg_data16);
94}
95
96static inline void __snd_gf1_adlib_write(snd_gus_card_t * gus,
97 unsigned char reg, unsigned char data)
98{
99 outb(reg, gus->gf1.reg_timerctrl);
100 inb(gus->gf1.reg_timerctrl);
101 inb(gus->gf1.reg_timerctrl);
102 outb(data, gus->gf1.reg_timerdata);
103 inb(gus->gf1.reg_timerctrl);
104 inb(gus->gf1.reg_timerctrl);
105}
106
107static inline void __snd_gf1_write_addr(snd_gus_card_t * gus, unsigned char reg,
108 unsigned int addr, int w_16bit)
109{
110 if (gus->gf1.enh_mode) {
111 if (w_16bit)
112 addr = ((addr >> 1) & ~0x0000000f) | (addr & 0x0000000f);
113 __snd_gf1_write8(gus, SNDRV_GF1_VB_UPPER_ADDRESS, (unsigned char) ((addr >> 26) & 0x03));
114 } else if (w_16bit)
115 addr = (addr & 0x00c0000f) | ((addr & 0x003ffff0) >> 1);
116 __snd_gf1_write16(gus, reg, (unsigned short) (addr >> 11));
117 __snd_gf1_write16(gus, reg + 1, (unsigned short) (addr << 5));
118}
119
120static inline unsigned int __snd_gf1_read_addr(snd_gus_card_t * gus,
121 unsigned char reg, short w_16bit)
122{
123 unsigned int res;
124
125 res = ((unsigned int) __snd_gf1_look16(gus, reg | 0x80) << 11) & 0xfff800;
126 res |= ((unsigned int) __snd_gf1_look16(gus, (reg + 1) | 0x80) >> 5) & 0x0007ff;
127 if (gus->gf1.enh_mode) {
128 res |= (unsigned int) __snd_gf1_look8(gus, SNDRV_GF1_VB_UPPER_ADDRESS | 0x80) << 26;
129 if (w_16bit)
130 res = ((res << 1) & 0xffffffe0) | (res & 0x0000000f);
131 } else if (w_16bit)
132 res = ((res & 0x001ffff0) << 1) | (res & 0x00c0000f);
133 return res;
134}
135
136
137/*
138 * =======================================================================
139 */
140
141void snd_gf1_ctrl_stop(snd_gus_card_t * gus, unsigned char reg)
142{
143 __snd_gf1_ctrl_stop(gus, reg);
144}
145
146void snd_gf1_write8(snd_gus_card_t * gus,
147 unsigned char reg,
148 unsigned char data)
149{
150 __snd_gf1_write8(gus, reg, data);
151}
152
153unsigned char snd_gf1_look8(snd_gus_card_t * gus, unsigned char reg)
154{
155 return __snd_gf1_look8(gus, reg);
156}
157
158void snd_gf1_write16(snd_gus_card_t * gus,
159 unsigned char reg,
160 unsigned int data)
161{
162 __snd_gf1_write16(gus, reg, data);
163}
164
165unsigned short snd_gf1_look16(snd_gus_card_t * gus, unsigned char reg)
166{
167 return __snd_gf1_look16(gus, reg);
168}
169
170void snd_gf1_adlib_write(snd_gus_card_t * gus,
171 unsigned char reg,
172 unsigned char data)
173{
174 __snd_gf1_adlib_write(gus, reg, data);
175}
176
177void snd_gf1_write_addr(snd_gus_card_t * gus, unsigned char reg,
178 unsigned int addr, short w_16bit)
179{
180 __snd_gf1_write_addr(gus, reg, addr, w_16bit);
181}
182
183unsigned int snd_gf1_read_addr(snd_gus_card_t * gus,
184 unsigned char reg,
185 short w_16bit)
186{
187 return __snd_gf1_read_addr(gus, reg, w_16bit);
188}
189
190/*
191
192 */
193
194void snd_gf1_i_ctrl_stop(snd_gus_card_t * gus, unsigned char reg)
195{
196 unsigned long flags;
197
198 spin_lock_irqsave(&gus->reg_lock, flags);
199 __snd_gf1_ctrl_stop(gus, reg);
200 spin_unlock_irqrestore(&gus->reg_lock, flags);
201}
202
203void snd_gf1_i_write8(snd_gus_card_t * gus,
204 unsigned char reg,
205 unsigned char data)
206{
207 unsigned long flags;
208
209 spin_lock_irqsave(&gus->reg_lock, flags);
210 __snd_gf1_write8(gus, reg, data);
211 spin_unlock_irqrestore(&gus->reg_lock, flags);
212}
213
214unsigned char snd_gf1_i_look8(snd_gus_card_t * gus, unsigned char reg)
215{
216 unsigned long flags;
217 unsigned char res;
218
219 spin_lock_irqsave(&gus->reg_lock, flags);
220 res = __snd_gf1_look8(gus, reg);
221 spin_unlock_irqrestore(&gus->reg_lock, flags);
222 return res;
223}
224
225void snd_gf1_i_write16(snd_gus_card_t * gus,
226 unsigned char reg,
227 unsigned int data)
228{
229 unsigned long flags;
230
231 spin_lock_irqsave(&gus->reg_lock, flags);
232 __snd_gf1_write16(gus, reg, data);
233 spin_unlock_irqrestore(&gus->reg_lock, flags);
234}
235
236unsigned short snd_gf1_i_look16(snd_gus_card_t * gus, unsigned char reg)
237{
238 unsigned long flags;
239 unsigned short res;
240
241 spin_lock_irqsave(&gus->reg_lock, flags);
242 res = __snd_gf1_look16(gus, reg);
243 spin_unlock_irqrestore(&gus->reg_lock, flags);
244 return res;
245}
246
247void snd_gf1_i_adlib_write(snd_gus_card_t * gus,
248 unsigned char reg,
249 unsigned char data)
250{
251 unsigned long flags;
252
253 spin_lock_irqsave(&gus->reg_lock, flags);
254 __snd_gf1_adlib_write(gus, reg, data);
255 spin_unlock_irqrestore(&gus->reg_lock, flags);
256}
257
258void snd_gf1_i_write_addr(snd_gus_card_t * gus, unsigned char reg,
259 unsigned int addr, short w_16bit)
260{
261 unsigned long flags;
262
263 spin_lock_irqsave(&gus->reg_lock, flags);
264 __snd_gf1_write_addr(gus, reg, addr, w_16bit);
265 spin_unlock_irqrestore(&gus->reg_lock, flags);
266}
267
268unsigned int snd_gf1_i_read_addr(snd_gus_card_t * gus,
269 unsigned char reg, short w_16bit)
270{
271 unsigned int res;
272 unsigned long flags;
273
274 spin_lock_irqsave(&gus->reg_lock, flags);
275 res = __snd_gf1_read_addr(gus, reg, w_16bit);
276 spin_unlock_irqrestore(&gus->reg_lock, flags);
277 return res;
278}
279
280/*
281
282 */
283
284void snd_gf1_dram_addr(snd_gus_card_t * gus, unsigned int addr)
285{
286 outb(0x43, gus->gf1.reg_regsel);
287 mb();
288 outw((unsigned short) addr, gus->gf1.reg_data16);
289 mb();
290 outb(0x44, gus->gf1.reg_regsel);
291 mb();
292 outb((unsigned char) (addr >> 16), gus->gf1.reg_data8);
293 mb();
294}
295
296void snd_gf1_poke(snd_gus_card_t * gus, unsigned int addr, unsigned char data)
297{
298 unsigned long flags;
299
300 spin_lock_irqsave(&gus->reg_lock, flags);
301 outb(SNDRV_GF1_GW_DRAM_IO_LOW, gus->gf1.reg_regsel);
302 mb();
303 outw((unsigned short) addr, gus->gf1.reg_data16);
304 mb();
305 outb(SNDRV_GF1_GB_DRAM_IO_HIGH, gus->gf1.reg_regsel);
306 mb();
307 outb((unsigned char) (addr >> 16), gus->gf1.reg_data8);
308 mb();
309 outb(data, gus->gf1.reg_dram);
310 spin_unlock_irqrestore(&gus->reg_lock, flags);
311}
312
313unsigned char snd_gf1_peek(snd_gus_card_t * gus, unsigned int addr)
314{
315 unsigned long flags;
316 unsigned char res;
317
318 spin_lock_irqsave(&gus->reg_lock, flags);
319 outb(SNDRV_GF1_GW_DRAM_IO_LOW, gus->gf1.reg_regsel);
320 mb();
321 outw((unsigned short) addr, gus->gf1.reg_data16);
322 mb();
323 outb(SNDRV_GF1_GB_DRAM_IO_HIGH, gus->gf1.reg_regsel);
324 mb();
325 outb((unsigned char) (addr >> 16), gus->gf1.reg_data8);
326 mb();
327 res = inb(gus->gf1.reg_dram);
328 spin_unlock_irqrestore(&gus->reg_lock, flags);
329 return res;
330}
331
332void snd_gf1_pokew(snd_gus_card_t * gus, unsigned int addr, unsigned short data)
333{
334 unsigned long flags;
335
336#ifdef CONFIG_SND_DEBUG
337 if (!gus->interwave)
338 snd_printk("snd_gf1_pokew - GF1!!!\n");
339#endif
340 spin_lock_irqsave(&gus->reg_lock, flags);
341 outb(SNDRV_GF1_GW_DRAM_IO_LOW, gus->gf1.reg_regsel);
342 mb();
343 outw((unsigned short) addr, gus->gf1.reg_data16);
344 mb();
345 outb(SNDRV_GF1_GB_DRAM_IO_HIGH, gus->gf1.reg_regsel);
346 mb();
347 outb((unsigned char) (addr >> 16), gus->gf1.reg_data8);
348 mb();
349 outb(SNDRV_GF1_GW_DRAM_IO16, gus->gf1.reg_regsel);
350 mb();
351 outw(data, gus->gf1.reg_data16);
352 spin_unlock_irqrestore(&gus->reg_lock, flags);
353}
354
355unsigned short snd_gf1_peekw(snd_gus_card_t * gus, unsigned int addr)
356{
357 unsigned long flags;
358 unsigned short res;
359
360#ifdef CONFIG_SND_DEBUG
361 if (!gus->interwave)
362 snd_printk("snd_gf1_peekw - GF1!!!\n");
363#endif
364 spin_lock_irqsave(&gus->reg_lock, flags);
365 outb(SNDRV_GF1_GW_DRAM_IO_LOW, gus->gf1.reg_regsel);
366 mb();
367 outw((unsigned short) addr, gus->gf1.reg_data16);
368 mb();
369 outb(SNDRV_GF1_GB_DRAM_IO_HIGH, gus->gf1.reg_regsel);
370 mb();
371 outb((unsigned char) (addr >> 16), gus->gf1.reg_data8);
372 mb();
373 outb(SNDRV_GF1_GW_DRAM_IO16, gus->gf1.reg_regsel);
374 mb();
375 res = inw(gus->gf1.reg_data16);
376 spin_unlock_irqrestore(&gus->reg_lock, flags);
377 return res;
378}
379
380void snd_gf1_dram_setmem(snd_gus_card_t * gus, unsigned int addr,
381 unsigned short value, unsigned int count)
382{
383 unsigned long port;
384 unsigned long flags;
385
386#ifdef CONFIG_SND_DEBUG
387 if (!gus->interwave)
388 snd_printk("snd_gf1_dram_setmem - GF1!!!\n");
389#endif
390 addr &= ~1;
391 count >>= 1;
392 port = GUSP(gus, GF1DATALOW);
393 spin_lock_irqsave(&gus->reg_lock, flags);
394 outb(SNDRV_GF1_GW_DRAM_IO_LOW, gus->gf1.reg_regsel);
395 mb();
396 outw((unsigned short) addr, gus->gf1.reg_data16);
397 mb();
398 outb(SNDRV_GF1_GB_DRAM_IO_HIGH, gus->gf1.reg_regsel);
399 mb();
400 outb((unsigned char) (addr >> 16), gus->gf1.reg_data8);
401 mb();
402 outb(SNDRV_GF1_GW_DRAM_IO16, gus->gf1.reg_regsel);
403 while (count--)
404 outw(value, port);
405 spin_unlock_irqrestore(&gus->reg_lock, flags);
406}
407
408/*
409
410 */
411
412void snd_gf1_select_active_voices(snd_gus_card_t * gus)
413{
414 unsigned short voices;
415
416 static unsigned short voices_tbl[32 - 14 + 1] =
417 {
418 44100, 41160, 38587, 36317, 34300, 32494, 30870, 29400, 28063, 26843,
419 25725, 24696, 23746, 22866, 22050, 21289, 20580, 19916, 19293
420 };
421
422 voices = gus->gf1.active_voices;
423 if (voices > 32)
424 voices = 32;
425 if (voices < 14)
426 voices = 14;
427 if (gus->gf1.enh_mode)
428 voices = 32;
429 gus->gf1.active_voices = voices;
430 gus->gf1.playback_freq =
431 gus->gf1.enh_mode ? 44100 : voices_tbl[voices - 14];
432 if (!gus->gf1.enh_mode) {
433 snd_gf1_i_write8(gus, SNDRV_GF1_GB_ACTIVE_VOICES, 0xc0 | (voices - 1));
434 udelay(100);
435 }
436}
437
438#ifdef CONFIG_SND_DEBUG
439
440void snd_gf1_print_voice_registers(snd_gus_card_t * gus)
441{
442 unsigned char mode;
443 int voice, ctrl;
444
445 voice = gus->gf1.active_voice;
446 printk(" -%i- GF1 voice ctrl, ramp ctrl = 0x%x, 0x%x\n", voice, ctrl = snd_gf1_i_read8(gus, 0), snd_gf1_i_read8(gus, 0x0d));
447 printk(" -%i- GF1 frequency = 0x%x\n", voice, snd_gf1_i_read16(gus, 1));
448 printk(" -%i- GF1 loop start, end = 0x%x (0x%x), 0x%x (0x%x)\n", voice, snd_gf1_i_read_addr(gus, 2, ctrl & 4), snd_gf1_i_read_addr(gus, 2, (ctrl & 4) ^ 4), snd_gf1_i_read_addr(gus, 4, ctrl & 4), snd_gf1_i_read_addr(gus, 4, (ctrl & 4) ^ 4));
449 printk(" -%i- GF1 ramp start, end, rate = 0x%x, 0x%x, 0x%x\n", voice, snd_gf1_i_read8(gus, 7), snd_gf1_i_read8(gus, 8), snd_gf1_i_read8(gus, 6));
450 printk(" -%i- GF1 volume = 0x%x\n", voice, snd_gf1_i_read16(gus, 9));
451 printk(" -%i- GF1 position = 0x%x (0x%x)\n", voice, snd_gf1_i_read_addr(gus, 0x0a, ctrl & 4), snd_gf1_i_read_addr(gus, 0x0a, (ctrl & 4) ^ 4));
452 if (gus->interwave && snd_gf1_i_read8(gus, 0x19) & 0x01) { /* enhanced mode */
453 mode = snd_gf1_i_read8(gus, 0x15);
454 printk(" -%i- GFA1 mode = 0x%x\n", voice, mode);
455 if (mode & 0x01) { /* Effect processor */
456 printk(" -%i- GFA1 effect address = 0x%x\n", voice, snd_gf1_i_read_addr(gus, 0x11, ctrl & 4));
457 printk(" -%i- GFA1 effect volume = 0x%x\n", voice, snd_gf1_i_read16(gus, 0x16));
458 printk(" -%i- GFA1 effect volume final = 0x%x\n", voice, snd_gf1_i_read16(gus, 0x1d));
459 printk(" -%i- GFA1 effect acumulator = 0x%x\n", voice, snd_gf1_i_read8(gus, 0x14));
460 }
461 if (mode & 0x20) {
462 printk(" -%i- GFA1 left offset = 0x%x (%i)\n", voice, snd_gf1_i_read16(gus, 0x13), snd_gf1_i_read16(gus, 0x13) >> 4);
463 printk(" -%i- GFA1 left offset final = 0x%x (%i)\n", voice, snd_gf1_i_read16(gus, 0x1c), snd_gf1_i_read16(gus, 0x1c) >> 4);
464 printk(" -%i- GFA1 right offset = 0x%x (%i)\n", voice, snd_gf1_i_read16(gus, 0x0c), snd_gf1_i_read16(gus, 0x0c) >> 4);
465 printk(" -%i- GFA1 right offset final = 0x%x (%i)\n", voice, snd_gf1_i_read16(gus, 0x1b), snd_gf1_i_read16(gus, 0x1b) >> 4);
466 } else
467 printk(" -%i- GF1 pan = 0x%x\n", voice, snd_gf1_i_read8(gus, 0x0c));
468 } else
469 printk(" -%i- GF1 pan = 0x%x\n", voice, snd_gf1_i_read8(gus, 0x0c));
470}
471
472void snd_gf1_print_global_registers(snd_gus_card_t * gus)
473{
474 unsigned char global_mode = 0x00;
475
476 printk(" -G- GF1 active voices = 0x%x\n", snd_gf1_i_look8(gus, SNDRV_GF1_GB_ACTIVE_VOICES));
477 if (gus->interwave) {
478 global_mode = snd_gf1_i_read8(gus, SNDRV_GF1_GB_GLOBAL_MODE);
479 printk(" -G- GF1 global mode = 0x%x\n", global_mode);
480 }
481 if (global_mode & 0x02) /* LFO enabled? */
482 printk(" -G- GF1 LFO base = 0x%x\n", snd_gf1_i_look16(gus, SNDRV_GF1_GW_LFO_BASE));
483 printk(" -G- GF1 voices IRQ read = 0x%x\n", snd_gf1_i_look8(gus, SNDRV_GF1_GB_VOICES_IRQ_READ));
484 printk(" -G- GF1 DRAM DMA control = 0x%x\n", snd_gf1_i_look8(gus, SNDRV_GF1_GB_DRAM_DMA_CONTROL));
485 printk(" -G- GF1 DRAM DMA high/low = 0x%x/0x%x\n", snd_gf1_i_look8(gus, SNDRV_GF1_GB_DRAM_DMA_HIGH), snd_gf1_i_read16(gus, SNDRV_GF1_GW_DRAM_DMA_LOW));
486 printk(" -G- GF1 DRAM IO high/low = 0x%x/0x%x\n", snd_gf1_i_look8(gus, SNDRV_GF1_GB_DRAM_IO_HIGH), snd_gf1_i_read16(gus, SNDRV_GF1_GW_DRAM_IO_LOW));
487 if (!gus->interwave)
488 printk(" -G- GF1 record DMA control = 0x%x\n", snd_gf1_i_look8(gus, SNDRV_GF1_GB_REC_DMA_CONTROL));
489 printk(" -G- GF1 DRAM IO 16 = 0x%x\n", snd_gf1_i_look16(gus, SNDRV_GF1_GW_DRAM_IO16));
490 if (gus->gf1.enh_mode) {
491 printk(" -G- GFA1 memory config = 0x%x\n", snd_gf1_i_look16(gus, SNDRV_GF1_GW_MEMORY_CONFIG));
492 printk(" -G- GFA1 memory control = 0x%x\n", snd_gf1_i_look8(gus, SNDRV_GF1_GB_MEMORY_CONTROL));
493 printk(" -G- GFA1 FIFO record base = 0x%x\n", snd_gf1_i_look16(gus, SNDRV_GF1_GW_FIFO_RECORD_BASE_ADDR));
494 printk(" -G- GFA1 FIFO playback base = 0x%x\n", snd_gf1_i_look16(gus, SNDRV_GF1_GW_FIFO_PLAY_BASE_ADDR));
495 printk(" -G- GFA1 interleave control = 0x%x\n", snd_gf1_i_look16(gus, SNDRV_GF1_GW_INTERLEAVE));
496 }
497}
498
499void snd_gf1_print_setup_registers(snd_gus_card_t * gus)
500{
501 printk(" -S- mix control = 0x%x\n", inb(GUSP(gus, MIXCNTRLREG)));
502 printk(" -S- IRQ status = 0x%x\n", inb(GUSP(gus, IRQSTAT)));
503 printk(" -S- timer control = 0x%x\n", inb(GUSP(gus, TIMERCNTRL)));
504 printk(" -S- timer data = 0x%x\n", inb(GUSP(gus, TIMERDATA)));
505 printk(" -S- status read = 0x%x\n", inb(GUSP(gus, REGCNTRLS)));
506 printk(" -S- Sound Blaster control = 0x%x\n", snd_gf1_i_look8(gus, SNDRV_GF1_GB_SOUND_BLASTER_CONTROL));
507 printk(" -S- AdLib timer 1/2 = 0x%x/0x%x\n", snd_gf1_i_look8(gus, SNDRV_GF1_GB_ADLIB_TIMER_1), snd_gf1_i_look8(gus, SNDRV_GF1_GB_ADLIB_TIMER_2));
508 printk(" -S- reset = 0x%x\n", snd_gf1_i_look8(gus, SNDRV_GF1_GB_RESET));
509 if (gus->interwave) {
510 printk(" -S- compatibility = 0x%x\n", snd_gf1_i_look8(gus, SNDRV_GF1_GB_COMPATIBILITY));
511 printk(" -S- decode control = 0x%x\n", snd_gf1_i_look8(gus, SNDRV_GF1_GB_DECODE_CONTROL));
512 printk(" -S- version number = 0x%x\n", snd_gf1_i_look8(gus, SNDRV_GF1_GB_VERSION_NUMBER));
513 printk(" -S- MPU-401 emul. control A/B = 0x%x/0x%x\n", snd_gf1_i_look8(gus, SNDRV_GF1_GB_MPU401_CONTROL_A), snd_gf1_i_look8(gus, SNDRV_GF1_GB_MPU401_CONTROL_B));
514 printk(" -S- emulation IRQ = 0x%x\n", snd_gf1_i_look8(gus, SNDRV_GF1_GB_EMULATION_IRQ));
515 }
516}
517
518void snd_gf1_peek_print_block(snd_gus_card_t * gus, unsigned int addr, int count, int w_16bit)
519{
520 if (!w_16bit) {
521 while (count-- > 0)
522 printk(count > 0 ? "%02x:" : "%02x", snd_gf1_peek(gus, addr++));
523 } else {
524 while (count-- > 0) {
525 printk(count > 0 ? "%04x:" : "%04x", snd_gf1_peek(gus, addr) | (snd_gf1_peek(gus, addr + 1) << 8));
526 addr += 2;
527 }
528 }
529}
530
531#endif
diff --git a/sound/isa/gus/gus_irq.c b/sound/isa/gus/gus_irq.c
new file mode 100644
index 000000000000..1e2a15eb8106
--- /dev/null
+++ b/sound/isa/gus/gus_irq.c
@@ -0,0 +1,142 @@
1/*
2 * Routine for IRQ handling from GF1/InterWave chip
3 * Copyright (c) by Jaroslav Kysela <perex@suse.cz>
4 *
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 *
20 */
21
22#include <sound/driver.h>
23#include <sound/core.h>
24#include <sound/info.h>
25#include <sound/gus.h>
26
27#ifdef CONFIG_SND_DEBUG
28#define STAT_ADD(x) ((x)++)
29#else
30#define STAT_ADD(x) while (0) { ; }
31#endif
32
33irqreturn_t snd_gus_interrupt(int irq, void *dev_id, struct pt_regs *regs)
34{
35 snd_gus_card_t * gus = dev_id;
36 unsigned char status;
37 int loop = 100;
38 int handled = 0;
39
40__again:
41 status = inb(gus->gf1.reg_irqstat);
42 if (status == 0)
43 return IRQ_RETVAL(handled);
44 handled = 1;
45 // snd_printk("IRQ: status = 0x%x\n", status);
46 if (status & 0x02) {
47 STAT_ADD(gus->gf1.interrupt_stat_midi_in);
48 gus->gf1.interrupt_handler_midi_in(gus);
49 }
50 if (status & 0x01) {
51 STAT_ADD(gus->gf1.interrupt_stat_midi_out);
52 gus->gf1.interrupt_handler_midi_out(gus);
53 }
54 if (status & (0x20 | 0x40)) {
55 unsigned int already, _current_;
56 unsigned char voice_status, voice;
57 snd_gus_voice_t *pvoice;
58
59 already = 0;
60 while (((voice_status = snd_gf1_i_read8(gus, SNDRV_GF1_GB_VOICES_IRQ)) & 0xc0) != 0xc0) {
61 voice = voice_status & 0x1f;
62 _current_ = 1 << voice;
63 if (already & _current_)
64 continue; /* multi request */
65 already |= _current_; /* mark request */
66#if 0
67 printk("voice = %i, voice_status = 0x%x, voice_verify = %i\n", voice, voice_status, inb(GUSP(gus, GF1PAGE)));
68#endif
69 pvoice = &gus->gf1.voices[voice];
70 if (pvoice->use) {
71 if (!(voice_status & 0x80)) { /* voice position IRQ */
72 STAT_ADD(pvoice->interrupt_stat_wave);
73 pvoice->handler_wave(gus, pvoice);
74 }
75 if (!(voice_status & 0x40)) { /* volume ramp IRQ */
76 STAT_ADD(pvoice->interrupt_stat_volume);
77 pvoice->handler_volume(gus, pvoice);
78 }
79 } else {
80 STAT_ADD(gus->gf1.interrupt_stat_voice_lost);
81 snd_gf1_i_ctrl_stop(gus, SNDRV_GF1_VB_ADDRESS_CONTROL);
82 snd_gf1_i_ctrl_stop(gus, SNDRV_GF1_VB_VOLUME_CONTROL);
83 }
84 }
85 }
86 if (status & 0x04) {
87 STAT_ADD(gus->gf1.interrupt_stat_timer1);
88 gus->gf1.interrupt_handler_timer1(gus);
89 }
90 if (status & 0x08) {
91 STAT_ADD(gus->gf1.interrupt_stat_timer2);
92 gus->gf1.interrupt_handler_timer2(gus);
93 }
94 if (status & 0x80) {
95 if (snd_gf1_i_look8(gus, SNDRV_GF1_GB_DRAM_DMA_CONTROL) & 0x40) {
96 STAT_ADD(gus->gf1.interrupt_stat_dma_write);
97 gus->gf1.interrupt_handler_dma_write(gus);
98 }
99 if (snd_gf1_i_look8(gus, SNDRV_GF1_GB_REC_DMA_CONTROL) & 0x40) {
100 STAT_ADD(gus->gf1.interrupt_stat_dma_read);
101 gus->gf1.interrupt_handler_dma_read(gus);
102 }
103 }
104 if (--loop > 0)
105 goto __again;
106 return IRQ_NONE;
107}
108
109#ifdef CONFIG_SND_DEBUG
110static void snd_gus_irq_info_read(snd_info_entry_t *entry,
111 snd_info_buffer_t * buffer)
112{
113 snd_gus_card_t *gus;
114 snd_gus_voice_t *pvoice;
115 int idx;
116
117 gus = entry->private_data;
118 snd_iprintf(buffer, "midi out = %u\n", gus->gf1.interrupt_stat_midi_out);
119 snd_iprintf(buffer, "midi in = %u\n", gus->gf1.interrupt_stat_midi_in);
120 snd_iprintf(buffer, "timer1 = %u\n", gus->gf1.interrupt_stat_timer1);
121 snd_iprintf(buffer, "timer2 = %u\n", gus->gf1.interrupt_stat_timer2);
122 snd_iprintf(buffer, "dma write = %u\n", gus->gf1.interrupt_stat_dma_write);
123 snd_iprintf(buffer, "dma read = %u\n", gus->gf1.interrupt_stat_dma_read);
124 snd_iprintf(buffer, "voice lost = %u\n", gus->gf1.interrupt_stat_voice_lost);
125 for (idx = 0; idx < 32; idx++) {
126 pvoice = &gus->gf1.voices[idx];
127 snd_iprintf(buffer, "voice %i: wave = %u, volume = %u\n",
128 idx,
129 pvoice->interrupt_stat_wave,
130 pvoice->interrupt_stat_volume);
131 }
132}
133
134void snd_gus_irq_profile_init(snd_gus_card_t *gus)
135{
136 snd_info_entry_t *entry;
137
138 if (! snd_card_proc_new(gus->card, "gusirq", &entry))
139 snd_info_set_text_ops(entry, gus, 1024, snd_gus_irq_info_read);
140}
141
142#endif
diff --git a/sound/isa/gus/gus_main.c b/sound/isa/gus/gus_main.c
new file mode 100644
index 000000000000..73f81c14f768
--- /dev/null
+++ b/sound/isa/gus/gus_main.c
@@ -0,0 +1,514 @@
1/*
2 * Routines for Gravis UltraSound soundcards
3 * Copyright (c) by Jaroslav Kysela <perex@suse.cz>
4 *
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 *
20 */
21
22#include <sound/driver.h>
23#include <linux/init.h>
24#include <linux/interrupt.h>
25#include <linux/delay.h>
26#include <linux/slab.h>
27#include <linux/ioport.h>
28#include <sound/core.h>
29#include <sound/gus.h>
30#include <sound/control.h>
31
32#include <asm/dma.h>
33
34MODULE_AUTHOR("Jaroslav Kysela <perex@suse.cz>");
35MODULE_DESCRIPTION("Routines for Gravis UltraSound soundcards");
36MODULE_LICENSE("GPL");
37
38static int snd_gus_init_dma_irq(snd_gus_card_t * gus, int latches);
39
40int snd_gus_use_inc(snd_gus_card_t * gus)
41{
42 if (!try_module_get(gus->card->module))
43 return 0;
44 return 1;
45}
46
47void snd_gus_use_dec(snd_gus_card_t * gus)
48{
49 module_put(gus->card->module);
50}
51
52static int snd_gus_joystick_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
53{
54 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
55 uinfo->count = 1;
56 uinfo->value.integer.min = 0;
57 uinfo->value.integer.max = 31;
58 return 0;
59}
60
61static int snd_gus_joystick_get(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
62{
63 snd_gus_card_t *gus = snd_kcontrol_chip(kcontrol);
64
65 ucontrol->value.integer.value[0] = gus->joystick_dac & 31;
66 return 0;
67}
68
69static int snd_gus_joystick_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
70{
71 snd_gus_card_t *gus = snd_kcontrol_chip(kcontrol);
72 unsigned long flags;
73 int change;
74 unsigned char nval;
75
76 nval = ucontrol->value.integer.value[0] & 31;
77 spin_lock_irqsave(&gus->reg_lock, flags);
78 change = gus->joystick_dac != nval;
79 gus->joystick_dac = nval;
80 snd_gf1_write8(gus, SNDRV_GF1_GB_JOYSTICK_DAC_LEVEL, gus->joystick_dac);
81 spin_unlock_irqrestore(&gus->reg_lock, flags);
82 return change;
83}
84
85static snd_kcontrol_new_t snd_gus_joystick_control = {
86 .iface = SNDRV_CTL_ELEM_IFACE_CARD,
87 .name = "Joystick Speed",
88 .info = snd_gus_joystick_info,
89 .get = snd_gus_joystick_get,
90 .put = snd_gus_joystick_put
91};
92
93static void snd_gus_init_control(snd_gus_card_t *gus)
94{
95 if (!gus->ace_flag)
96 snd_ctl_add(gus->card, snd_ctl_new1(&snd_gus_joystick_control, gus));
97}
98
99/*
100 *
101 */
102
103static int snd_gus_free(snd_gus_card_t *gus)
104{
105 if (gus->gf1.res_port2 == NULL)
106 goto __hw_end;
107#if defined(CONFIG_SND_SEQUENCER) || (defined(MODULE) && defined(CONFIG_SND_SEQUENCER_MODULE))
108 if (gus->seq_dev) {
109 snd_device_free(gus->card, gus->seq_dev);
110 gus->seq_dev = NULL;
111 }
112#endif
113 snd_gf1_stop(gus);
114 snd_gus_init_dma_irq(gus, 0);
115 __hw_end:
116 if (gus->gf1.res_port1) {
117 release_resource(gus->gf1.res_port1);
118 kfree_nocheck(gus->gf1.res_port1);
119 }
120 if (gus->gf1.res_port2) {
121 release_resource(gus->gf1.res_port2);
122 kfree_nocheck(gus->gf1.res_port2);
123 }
124 if (gus->gf1.irq >= 0)
125 free_irq(gus->gf1.irq, (void *) gus);
126 if (gus->gf1.dma1 >= 0) {
127 disable_dma(gus->gf1.dma1);
128 free_dma(gus->gf1.dma1);
129 }
130 if (!gus->equal_dma && gus->gf1.dma2 >= 0) {
131 disable_dma(gus->gf1.dma2);
132 free_dma(gus->gf1.dma2);
133 }
134 kfree(gus);
135 return 0;
136}
137
138static int snd_gus_dev_free(snd_device_t *device)
139{
140 snd_gus_card_t *gus = device->device_data;
141 return snd_gus_free(gus);
142}
143
144int snd_gus_create(snd_card_t * card,
145 unsigned long port,
146 int irq, int dma1, int dma2,
147 int timer_dev,
148 int voices,
149 int pcm_channels,
150 int effect,
151 snd_gus_card_t **rgus)
152{
153 snd_gus_card_t *gus;
154 int err;
155 static snd_device_ops_t ops = {
156 .dev_free = snd_gus_dev_free,
157 };
158
159 *rgus = NULL;
160 gus = kcalloc(1, sizeof(*gus), GFP_KERNEL);
161 if (gus == NULL)
162 return -ENOMEM;
163 gus->gf1.irq = -1;
164 gus->gf1.dma1 = -1;
165 gus->gf1.dma2 = -1;
166 gus->card = card;
167 gus->gf1.port = port;
168 /* fill register variables for speedup */
169 gus->gf1.reg_page = GUSP(gus, GF1PAGE);
170 gus->gf1.reg_regsel = GUSP(gus, GF1REGSEL);
171 gus->gf1.reg_data8 = GUSP(gus, GF1DATAHIGH);
172 gus->gf1.reg_data16 = GUSP(gus, GF1DATALOW);
173 gus->gf1.reg_irqstat = GUSP(gus, IRQSTAT);
174 gus->gf1.reg_dram = GUSP(gus, DRAM);
175 gus->gf1.reg_timerctrl = GUSP(gus, TIMERCNTRL);
176 gus->gf1.reg_timerdata = GUSP(gus, TIMERDATA);
177 /* allocate resources */
178 if ((gus->gf1.res_port1 = request_region(port, 16, "GUS GF1 (Adlib/SB)")) == NULL) {
179 snd_printk(KERN_ERR "gus: can't grab SB port 0x%lx\n", port);
180 snd_gus_free(gus);
181 return -EBUSY;
182 }
183 if ((gus->gf1.res_port2 = request_region(port + 0x100, 12, "GUS GF1 (Synth)")) == NULL) {
184 snd_printk(KERN_ERR "gus: can't grab synth port 0x%lx\n", port + 0x100);
185 snd_gus_free(gus);
186 return -EBUSY;
187 }
188 if (irq >= 0 && request_irq(irq, snd_gus_interrupt, SA_INTERRUPT, "GUS GF1", (void *) gus)) {
189 snd_printk(KERN_ERR "gus: can't grab irq %d\n", irq);
190 snd_gus_free(gus);
191 return -EBUSY;
192 }
193 gus->gf1.irq = irq;
194 if (request_dma(dma1, "GUS - 1")) {
195 snd_printk(KERN_ERR "gus: can't grab DMA1 %d\n", dma1);
196 snd_gus_free(gus);
197 return -EBUSY;
198 }
199 gus->gf1.dma1 = dma1;
200 if (dma2 >= 0 && dma1 != dma2) {
201 if (request_dma(dma2, "GUS - 2")) {
202 snd_printk(KERN_ERR "gus: can't grab DMA2 %d\n", dma2);
203 snd_gus_free(gus);
204 return -EBUSY;
205 }
206 gus->gf1.dma2 = dma2;
207 } else {
208 gus->gf1.dma2 = gus->gf1.dma1;
209 gus->equal_dma = 1;
210 }
211 gus->timer_dev = timer_dev;
212 if (voices < 14)
213 voices = 14;
214 if (voices > 32)
215 voices = 32;
216 if (pcm_channels < 0)
217 pcm_channels = 0;
218 if (pcm_channels > 8)
219 pcm_channels = 8;
220 pcm_channels++;
221 pcm_channels &= ~1;
222 gus->gf1.effect = effect ? 1 : 0;
223 gus->gf1.active_voices = voices;
224 gus->gf1.pcm_channels = pcm_channels;
225 gus->gf1.volume_ramp = 25;
226 gus->gf1.smooth_pan = 1;
227 spin_lock_init(&gus->reg_lock);
228 spin_lock_init(&gus->voice_alloc);
229 spin_lock_init(&gus->active_voice_lock);
230 spin_lock_init(&gus->event_lock);
231 spin_lock_init(&gus->dma_lock);
232 spin_lock_init(&gus->pcm_volume_level_lock);
233 spin_lock_init(&gus->uart_cmd_lock);
234 init_MUTEX(&gus->dma_mutex);
235 if ((err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, gus, &ops)) < 0) {
236 snd_gus_free(gus);
237 return err;
238 }
239 *rgus = gus;
240 return 0;
241}
242
243/*
244 * Memory detection routine for plain GF1 soundcards
245 */
246
247static int snd_gus_detect_memory(snd_gus_card_t * gus)
248{
249 int l, idx, local;
250 unsigned char d;
251
252 snd_gf1_poke(gus, 0L, 0xaa);
253 snd_gf1_poke(gus, 1L, 0x55);
254 if (snd_gf1_peek(gus, 0L) != 0xaa || snd_gf1_peek(gus, 1L) != 0x55) {
255 snd_printk("plain GF1 card at 0x%lx without onboard DRAM?\n", gus->gf1.port);
256 return -ENOMEM;
257 }
258 for (idx = 1, d = 0xab; idx < 4; idx++, d++) {
259 local = idx << 18;
260 snd_gf1_poke(gus, local, d);
261 snd_gf1_poke(gus, local + 1, d + 1);
262 if (snd_gf1_peek(gus, local) != d ||
263 snd_gf1_peek(gus, local + 1) != d + 1 ||
264 snd_gf1_peek(gus, 0L) != 0xaa)
265 break;
266 }
267#if 1
268 gus->gf1.memory = idx << 18;
269#else
270 gus->gf1.memory = 256 * 1024;
271#endif
272 for (l = 0, local = gus->gf1.memory; l < 4; l++, local -= 256 * 1024) {
273 gus->gf1.mem_alloc.banks_8[l].address =
274 gus->gf1.mem_alloc.banks_8[l].size = 0;
275 gus->gf1.mem_alloc.banks_16[l].address = l << 18;
276 gus->gf1.mem_alloc.banks_16[l].size = local > 0 ? 256 * 1024 : 0;
277 }
278 gus->gf1.mem_alloc.banks_8[0].size = gus->gf1.memory;
279 return 0; /* some memory were detected */
280}
281
282static int snd_gus_init_dma_irq(snd_gus_card_t * gus, int latches)
283{
284 snd_card_t *card;
285 unsigned long flags;
286 int irq, dma1, dma2;
287 static unsigned char irqs[16] =
288 {0, 0, 1, 3, 0, 2, 0, 4, 0, 1, 0, 5, 6, 0, 0, 7};
289 static unsigned char dmas[8] =
290 {6, 1, 0, 2, 0, 3, 4, 5};
291
292 snd_assert(gus != NULL, return -EINVAL);
293 card = gus->card;
294 snd_assert(card != NULL, return -EINVAL);
295
296 gus->mix_cntrl_reg &= 0xf8;
297 gus->mix_cntrl_reg |= 0x01; /* disable MIC, LINE IN, enable LINE OUT */
298 if (gus->codec_flag || gus->ess_flag) {
299 gus->mix_cntrl_reg &= ~1; /* enable LINE IN */
300 gus->mix_cntrl_reg |= 4; /* enable MIC */
301 }
302 dma1 = gus->gf1.dma1;
303 dma1 = dma1 < 0 ? -dma1 : dma1;
304 dma1 = dmas[dma1 & 7];
305 dma2 = gus->gf1.dma2;
306 dma2 = dma2 < 0 ? -dma2 : dma2;
307 dma2 = dmas[dma2 & 7];
308#if 0
309 printk("dma1 = %i, dma2 = %i\n", gus->gf1.dma1, gus->gf1.dma2);
310#endif
311 dma1 |= gus->equal_dma ? 0x40 : (dma2 << 3);
312
313 if ((dma1 & 7) == 0 || (dma2 & 7) == 0) {
314 snd_printk("Error! DMA isn't defined.\n");
315 return -EINVAL;
316 }
317 irq = gus->gf1.irq;
318 irq = irq < 0 ? -irq : irq;
319 irq = irqs[irq & 0x0f];
320 if (irq == 0) {
321 snd_printk("Error! IRQ isn't defined.\n");
322 return -EINVAL;
323 }
324 irq |= 0x40;
325#if 0
326 card->mixer.mix_ctrl_reg |= 0x10;
327#endif
328
329 spin_lock_irqsave(&gus->reg_lock, flags);
330 outb(5, GUSP(gus, REGCNTRLS));
331 outb(gus->mix_cntrl_reg, GUSP(gus, MIXCNTRLREG));
332 outb(0x00, GUSP(gus, IRQDMACNTRLREG));
333 outb(0, GUSP(gus, REGCNTRLS));
334 spin_unlock_irqrestore(&gus->reg_lock, flags);
335
336 udelay(100);
337
338 spin_lock_irqsave(&gus->reg_lock, flags);
339 outb(0x00 | gus->mix_cntrl_reg, GUSP(gus, MIXCNTRLREG));
340 outb(dma1, GUSP(gus, IRQDMACNTRLREG));
341 if (latches) {
342 outb(0x40 | gus->mix_cntrl_reg, GUSP(gus, MIXCNTRLREG));
343 outb(irq, GUSP(gus, IRQDMACNTRLREG));
344 }
345 spin_unlock_irqrestore(&gus->reg_lock, flags);
346
347 udelay(100);
348
349 spin_lock_irqsave(&gus->reg_lock, flags);
350 outb(0x00 | gus->mix_cntrl_reg, GUSP(gus, MIXCNTRLREG));
351 outb(dma1, GUSP(gus, IRQDMACNTRLREG));
352 if (latches) {
353 outb(0x40 | gus->mix_cntrl_reg, GUSP(gus, MIXCNTRLREG));
354 outb(irq, GUSP(gus, IRQDMACNTRLREG));
355 }
356 spin_unlock_irqrestore(&gus->reg_lock, flags);
357
358 snd_gf1_delay(gus);
359
360 if (latches)
361 gus->mix_cntrl_reg |= 0x08; /* enable latches */
362 else
363 gus->mix_cntrl_reg &= ~0x08; /* disable latches */
364 spin_lock_irqsave(&gus->reg_lock, flags);
365 outb(gus->mix_cntrl_reg, GUSP(gus, MIXCNTRLREG));
366 outb(0, GUSP(gus, GF1PAGE));
367 spin_unlock_irqrestore(&gus->reg_lock, flags);
368
369 return 0;
370}
371
372static int snd_gus_check_version(snd_gus_card_t * gus)
373{
374 unsigned long flags;
375 unsigned char val, rev;
376 snd_card_t *card;
377
378 card = gus->card;
379 spin_lock_irqsave(&gus->reg_lock, flags);
380 outb(0x20, GUSP(gus, REGCNTRLS));
381 val = inb(GUSP(gus, REGCNTRLS));
382 rev = inb(GUSP(gus, BOARDVERSION));
383 spin_unlock_irqrestore(&gus->reg_lock, flags);
384 snd_printdd("GF1 [0x%lx] init - val = 0x%x, rev = 0x%x\n", gus->gf1.port, val, rev);
385 strcpy(card->driver, "GUS");
386 strcpy(card->longname, "Gravis UltraSound Classic (2.4)");
387 if ((val != 255 && (val & 0x06)) || (rev >= 5 && rev != 255)) {
388 if (rev >= 5 && rev <= 9) {
389 gus->ics_flag = 1;
390 if (rev == 5)
391 gus->ics_flipped = 1;
392 card->longname[27] = '3';
393 card->longname[29] = rev == 5 ? '5' : '7';
394 }
395 if (rev >= 10 && rev != 255) {
396 if (rev >= 10 && rev <= 11) {
397 strcpy(card->driver, "GUS MAX");
398 strcpy(card->longname, "Gravis UltraSound MAX");
399 gus->max_flag = 1;
400 } else if (rev == 0x30) {
401 strcpy(card->driver, "GUS ACE");
402 strcpy(card->longname, "Gravis UltraSound Ace");
403 gus->ace_flag = 1;
404 } else if (rev == 0x50) {
405 strcpy(card->driver, "GUS Extreme");
406 strcpy(card->longname, "Gravis UltraSound Extreme");
407 gus->ess_flag = 1;
408 } else {
409 snd_printk("unknown GF1 revision number at 0x%lx - 0x%x (0x%x)\n", gus->gf1.port, rev, val);
410 snd_printk(" please - report to <perex@suse.cz>\n");
411 }
412 }
413 }
414 strcpy(card->shortname, card->longname);
415 gus->uart_enable = 1; /* standard GUSes doesn't have midi uart trouble */
416 snd_gus_init_control(gus);
417 return 0;
418}
419
420static void snd_gus_seq_dev_free(snd_seq_device_t *seq_dev)
421{
422 snd_gus_card_t *gus = seq_dev->private_data;
423 gus->seq_dev = NULL;
424}
425
426int snd_gus_initialize(snd_gus_card_t *gus)
427{
428 int err;
429
430 if (!gus->interwave) {
431 if ((err = snd_gus_check_version(gus)) < 0) {
432 snd_printk("version check failed\n");
433 return err;
434 }
435 if ((err = snd_gus_detect_memory(gus)) < 0)
436 return err;
437 }
438 if ((err = snd_gus_init_dma_irq(gus, 1)) < 0)
439 return err;
440#if defined(CONFIG_SND_SEQUENCER) || (defined(MODULE) && defined(CONFIG_SND_SEQUENCER_MODULE))
441 if (snd_seq_device_new(gus->card, 1, SNDRV_SEQ_DEV_ID_GUS,
442 sizeof(snd_gus_card_t*), &gus->seq_dev) >= 0) {
443 strcpy(gus->seq_dev->name, "GUS");
444 *(snd_gus_card_t**)SNDRV_SEQ_DEVICE_ARGPTR(gus->seq_dev) = gus;
445 gus->seq_dev->private_data = gus;
446 gus->seq_dev->private_free = snd_gus_seq_dev_free;
447 }
448#endif
449 snd_gf1_start(gus);
450 gus->initialized = 1;
451 return 0;
452}
453
454 /* gus_io.c */
455EXPORT_SYMBOL(snd_gf1_delay);
456EXPORT_SYMBOL(snd_gf1_write8);
457EXPORT_SYMBOL(snd_gf1_look8);
458EXPORT_SYMBOL(snd_gf1_write16);
459EXPORT_SYMBOL(snd_gf1_look16);
460EXPORT_SYMBOL(snd_gf1_i_write8);
461EXPORT_SYMBOL(snd_gf1_i_look8);
462EXPORT_SYMBOL(snd_gf1_i_write16);
463EXPORT_SYMBOL(snd_gf1_i_look16);
464EXPORT_SYMBOL(snd_gf1_dram_addr);
465EXPORT_SYMBOL(snd_gf1_write_addr);
466EXPORT_SYMBOL(snd_gf1_poke);
467EXPORT_SYMBOL(snd_gf1_peek);
468 /* gus_reset.c */
469EXPORT_SYMBOL(snd_gf1_alloc_voice);
470EXPORT_SYMBOL(snd_gf1_free_voice);
471EXPORT_SYMBOL(snd_gf1_ctrl_stop);
472EXPORT_SYMBOL(snd_gf1_stop_voice);
473EXPORT_SYMBOL(snd_gf1_start);
474EXPORT_SYMBOL(snd_gf1_stop);
475 /* gus_mixer.c */
476EXPORT_SYMBOL(snd_gf1_new_mixer);
477 /* gus_pcm.c */
478EXPORT_SYMBOL(snd_gf1_pcm_new);
479 /* gus.c */
480EXPORT_SYMBOL(snd_gus_use_inc);
481EXPORT_SYMBOL(snd_gus_use_dec);
482EXPORT_SYMBOL(snd_gus_create);
483EXPORT_SYMBOL(snd_gus_initialize);
484 /* gus_irq.c */
485EXPORT_SYMBOL(snd_gus_interrupt);
486 /* gus_uart.c */
487EXPORT_SYMBOL(snd_gf1_rawmidi_new);
488 /* gus_dram.c */
489EXPORT_SYMBOL(snd_gus_dram_write);
490EXPORT_SYMBOL(snd_gus_dram_read);
491 /* gus_volume.c */
492EXPORT_SYMBOL(snd_gf1_lvol_to_gvol_raw);
493EXPORT_SYMBOL(snd_gf1_translate_freq);
494 /* gus_mem.c */
495EXPORT_SYMBOL(snd_gf1_mem_alloc);
496EXPORT_SYMBOL(snd_gf1_mem_xfree);
497EXPORT_SYMBOL(snd_gf1_mem_free);
498EXPORT_SYMBOL(snd_gf1_mem_lock);
499
500/*
501 * INIT part
502 */
503
504static int __init alsa_gus_init(void)
505{
506 return 0;
507}
508
509static void __exit alsa_gus_exit(void)
510{
511}
512
513module_init(alsa_gus_init)
514module_exit(alsa_gus_exit)
diff --git a/sound/isa/gus/gus_mem.c b/sound/isa/gus/gus_mem.c
new file mode 100644
index 000000000000..bfc2b91001d5
--- /dev/null
+++ b/sound/isa/gus/gus_mem.c
@@ -0,0 +1,353 @@
1/*
2 * Copyright (c) by Jaroslav Kysela <perex@suse.cz>
3 * GUS's memory allocation routines / bottom layer
4 *
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 *
20 */
21
22#include <sound/driver.h>
23#include <linux/slab.h>
24#include <sound/core.h>
25#include <sound/gus.h>
26#include <sound/info.h>
27
28#ifdef CONFIG_SND_DEBUG
29static void snd_gf1_mem_info_read(snd_info_entry_t *entry,
30 snd_info_buffer_t * buffer);
31#endif
32
33void snd_gf1_mem_lock(snd_gf1_mem_t * alloc, int xup)
34{
35 if (!xup) {
36 down(&alloc->memory_mutex);
37 } else {
38 up(&alloc->memory_mutex);
39 }
40}
41
42snd_gf1_mem_block_t *snd_gf1_mem_xalloc(snd_gf1_mem_t * alloc,
43 snd_gf1_mem_block_t * block)
44{
45 snd_gf1_mem_block_t *pblock, *nblock;
46
47 nblock = (snd_gf1_mem_block_t *) kmalloc(sizeof(snd_gf1_mem_block_t), GFP_KERNEL);
48 if (nblock == NULL)
49 return NULL;
50 *nblock = *block;
51 pblock = alloc->first;
52 while (pblock) {
53 if (pblock->ptr > nblock->ptr) {
54 nblock->prev = pblock->prev;
55 nblock->next = pblock;
56 pblock->prev = nblock;
57 if (pblock == alloc->first)
58 alloc->first = nblock;
59 else
60 nblock->prev->next = nblock;
61 up(&alloc->memory_mutex);
62 return NULL;
63 }
64 pblock = pblock->next;
65 }
66 nblock->next = NULL;
67 if (alloc->last == NULL) {
68 nblock->prev = NULL;
69 alloc->first = alloc->last = nblock;
70 } else {
71 nblock->prev = alloc->last;
72 alloc->last->next = nblock;
73 alloc->last = nblock;
74 }
75 return nblock;
76}
77
78int snd_gf1_mem_xfree(snd_gf1_mem_t * alloc, snd_gf1_mem_block_t * block)
79{
80 if (block->share) { /* ok.. shared block */
81 block->share--;
82 up(&alloc->memory_mutex);
83 return 0;
84 }
85 if (alloc->first == block) {
86 alloc->first = block->next;
87 if (block->next)
88 block->next->prev = NULL;
89 } else {
90 block->prev->next = block->next;
91 if (block->next)
92 block->next->prev = block->prev;
93 }
94 if (alloc->last == block) {
95 alloc->last = block->prev;
96 if (block->prev)
97 block->prev->next = NULL;
98 } else {
99 block->next->prev = block->prev;
100 if (block->prev)
101 block->prev->next = block->next;
102 }
103 kfree(block->name);
104 kfree(block);
105 return 0;
106}
107
108snd_gf1_mem_block_t *snd_gf1_mem_look(snd_gf1_mem_t * alloc,
109 unsigned int address)
110{
111 snd_gf1_mem_block_t *block;
112
113 for (block = alloc->first; block; block = block->next) {
114 if (block->ptr == address) {
115 return block;
116 }
117 }
118 return NULL;
119}
120
121snd_gf1_mem_block_t *snd_gf1_mem_share(snd_gf1_mem_t * alloc,
122 unsigned int *share_id)
123{
124 snd_gf1_mem_block_t *block;
125
126 if (!share_id[0] && !share_id[1] &&
127 !share_id[2] && !share_id[3])
128 return NULL;
129 for (block = alloc->first; block; block = block->next)
130 if (!memcmp(share_id, block->share_id, sizeof(share_id)))
131 return block;
132 return NULL;
133}
134
135static int snd_gf1_mem_find(snd_gf1_mem_t * alloc,
136 snd_gf1_mem_block_t * block,
137 unsigned int size, int w_16, int align)
138{
139 snd_gf1_bank_info_t *info = w_16 ? alloc->banks_16 : alloc->banks_8;
140 unsigned int idx, boundary;
141 int size1;
142 snd_gf1_mem_block_t *pblock;
143 unsigned int ptr1, ptr2;
144
145 align--;
146 if (w_16 && align < 1)
147 align = 1;
148 block->flags = w_16 ? SNDRV_GF1_MEM_BLOCK_16BIT : 0;
149 block->owner = SNDRV_GF1_MEM_OWNER_DRIVER;
150 block->share = 0;
151 block->share_id[0] = block->share_id[1] =
152 block->share_id[2] = block->share_id[3] = 0;
153 block->name = NULL;
154 block->prev = block->next = NULL;
155 for (pblock = alloc->first, idx = 0; pblock; pblock = pblock->next) {
156 while (pblock->ptr >= (boundary = info[idx].address + info[idx].size))
157 idx++;
158 while (pblock->ptr + pblock->size >= (boundary = info[idx].address + info[idx].size))
159 idx++;
160 ptr2 = boundary;
161 if (pblock->next) {
162 if (pblock->ptr + pblock->size == pblock->next->ptr)
163 continue;
164 if (pblock->next->ptr < boundary)
165 ptr2 = pblock->next->ptr;
166 }
167 ptr1 = (pblock->ptr + pblock->size + align) & ~align;
168 if (ptr1 >= ptr2)
169 continue;
170 size1 = ptr2 - ptr1;
171 if ((int)size <= size1) {
172 block->ptr = ptr1;
173 block->size = size;
174 return 0;
175 }
176 }
177 while (++idx < 4) {
178 if (size <= info[idx].size) {
179 /* I assume that bank address is already aligned.. */
180 block->ptr = info[idx].address;
181 block->size = size;
182 return 0;
183 }
184 }
185 return -ENOMEM;
186}
187
188snd_gf1_mem_block_t *snd_gf1_mem_alloc(snd_gf1_mem_t * alloc, int owner,
189 char *name, int size, int w_16, int align,
190 unsigned int *share_id)
191{
192 snd_gf1_mem_block_t block, *nblock;
193
194 snd_gf1_mem_lock(alloc, 0);
195 if (share_id != NULL) {
196 nblock = snd_gf1_mem_share(alloc, share_id);
197 if (nblock != NULL) {
198 if (size != (int)nblock->size) {
199 /* TODO: remove in the future */
200 snd_printk("snd_gf1_mem_alloc - share: sizes differ\n");
201 goto __std;
202 }
203 nblock->share++;
204 snd_gf1_mem_lock(alloc, 1);
205 return NULL;
206 }
207 }
208 __std:
209 if (snd_gf1_mem_find(alloc, &block, size, w_16, align) < 0) {
210 snd_gf1_mem_lock(alloc, 1);
211 return NULL;
212 }
213 if (share_id != NULL)
214 memcpy(&block.share_id, share_id, sizeof(block.share_id));
215 block.owner = owner;
216 block.name = snd_kmalloc_strdup(name, GFP_KERNEL);
217 nblock = snd_gf1_mem_xalloc(alloc, &block);
218 snd_gf1_mem_lock(alloc, 1);
219 return nblock;
220}
221
222int snd_gf1_mem_free(snd_gf1_mem_t * alloc, unsigned int address)
223{
224 int result;
225 snd_gf1_mem_block_t *block;
226
227 snd_gf1_mem_lock(alloc, 0);
228 if ((block = snd_gf1_mem_look(alloc, address)) != NULL) {
229 result = snd_gf1_mem_xfree(alloc, block);
230 snd_gf1_mem_lock(alloc, 1);
231 return result;
232 }
233 snd_gf1_mem_lock(alloc, 1);
234 return -EINVAL;
235}
236
237int snd_gf1_mem_init(snd_gus_card_t * gus)
238{
239 snd_gf1_mem_t *alloc;
240 snd_gf1_mem_block_t block;
241#ifdef CONFIG_SND_DEBUG
242 snd_info_entry_t *entry;
243#endif
244
245 alloc = &gus->gf1.mem_alloc;
246 init_MUTEX(&alloc->memory_mutex);
247 alloc->first = alloc->last = NULL;
248 if (!gus->gf1.memory)
249 return 0;
250
251 memset(&block, 0, sizeof(block));
252 block.owner = SNDRV_GF1_MEM_OWNER_DRIVER;
253 if (gus->gf1.enh_mode) {
254 block.ptr = 0;
255 block.size = 1024;
256 block.name = snd_kmalloc_strdup("InterWave LFOs", GFP_KERNEL);
257 if (snd_gf1_mem_xalloc(alloc, &block) == NULL)
258 return -ENOMEM;
259 }
260 block.ptr = gus->gf1.default_voice_address;
261 block.size = 4;
262 block.name = snd_kmalloc_strdup("Voice default (NULL's)", GFP_KERNEL);
263 if (snd_gf1_mem_xalloc(alloc, &block) == NULL)
264 return -ENOMEM;
265#ifdef CONFIG_SND_DEBUG
266 if (! snd_card_proc_new(gus->card, "gusmem", &entry)) {
267 snd_info_set_text_ops(entry, gus, 1024, snd_gf1_mem_info_read);
268 entry->c.text.read_size = 256 * 1024;
269 }
270#endif
271 return 0;
272}
273
274int snd_gf1_mem_done(snd_gus_card_t * gus)
275{
276 snd_gf1_mem_t *alloc;
277 snd_gf1_mem_block_t *block, *nblock;
278
279 alloc = &gus->gf1.mem_alloc;
280 block = alloc->first;
281 while (block) {
282 nblock = block->next;
283 snd_gf1_mem_xfree(alloc, block);
284 block = nblock;
285 }
286 return 0;
287}
288
289#ifdef CONFIG_SND_DEBUG
290static void snd_gf1_mem_info_read(snd_info_entry_t *entry,
291 snd_info_buffer_t * buffer)
292{
293 snd_gus_card_t *gus;
294 snd_gf1_mem_t *alloc;
295 snd_gf1_mem_block_t *block;
296 unsigned int total, used;
297 int i;
298
299 gus = entry->private_data;
300 alloc = &gus->gf1.mem_alloc;
301 down(&alloc->memory_mutex);
302 snd_iprintf(buffer, "8-bit banks : \n ");
303 for (i = 0; i < 4; i++)
304 snd_iprintf(buffer, "0x%06x (%04ik)%s", alloc->banks_8[i].address, alloc->banks_8[i].size >> 10, i + 1 < 4 ? "," : "");
305 snd_iprintf(buffer, "\n"
306 "16-bit banks : \n ");
307 for (i = total = 0; i < 4; i++) {
308 snd_iprintf(buffer, "0x%06x (%04ik)%s", alloc->banks_16[i].address, alloc->banks_16[i].size >> 10, i + 1 < 4 ? "," : "");
309 total += alloc->banks_16[i].size;
310 }
311 snd_iprintf(buffer, "\n");
312 used = 0;
313 for (block = alloc->first, i = 0; block; block = block->next, i++) {
314 used += block->size;
315 snd_iprintf(buffer, "Block %i at 0x%lx onboard 0x%x size %i (0x%x):\n", i, (long) block, block->ptr, block->size, block->size);
316 if (block->share ||
317 block->share_id[0] || block->share_id[1] ||
318 block->share_id[2] || block->share_id[3])
319 snd_iprintf(buffer, " Share : %i [id0 0x%x] [id1 0x%x] [id2 0x%x] [id3 0x%x]\n",
320 block->share,
321 block->share_id[0], block->share_id[1],
322 block->share_id[2], block->share_id[3]);
323 snd_iprintf(buffer, " Flags :%s\n",
324 block->flags & SNDRV_GF1_MEM_BLOCK_16BIT ? " 16-bit" : "");
325 snd_iprintf(buffer, " Owner : ");
326 switch (block->owner) {
327 case SNDRV_GF1_MEM_OWNER_DRIVER:
328 snd_iprintf(buffer, "driver - %s\n", block->name);
329 break;
330 case SNDRV_GF1_MEM_OWNER_WAVE_SIMPLE:
331 snd_iprintf(buffer, "SIMPLE wave\n");
332 break;
333 case SNDRV_GF1_MEM_OWNER_WAVE_GF1:
334 snd_iprintf(buffer, "GF1 wave\n");
335 break;
336 case SNDRV_GF1_MEM_OWNER_WAVE_IWFFFF:
337 snd_iprintf(buffer, "IWFFFF wave\n");
338 break;
339 default:
340 snd_iprintf(buffer, "unknown\n");
341 }
342 }
343 snd_iprintf(buffer, " Total: memory = %i, used = %i, free = %i\n",
344 total, used, total - used);
345 up(&alloc->memory_mutex);
346#if 0
347 ultra_iprintf(buffer, " Verify: free = %i, max 8-bit block = %i, max 16-bit block = %i\n",
348 ultra_memory_free_size(card, &card->gf1.mem_alloc),
349 ultra_memory_free_block(card, &card->gf1.mem_alloc, 0),
350 ultra_memory_free_block(card, &card->gf1.mem_alloc, 1));
351#endif
352}
353#endif
diff --git a/sound/isa/gus/gus_mem_proc.c b/sound/isa/gus/gus_mem_proc.c
new file mode 100644
index 000000000000..886763f12132
--- /dev/null
+++ b/sound/isa/gus/gus_mem_proc.c
@@ -0,0 +1,135 @@
1/*
2 * Copyright (c) by Jaroslav Kysela <perex@suse.cz>
3 * GUS's memory access via proc filesystem
4 *
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 *
20 */
21
22#include <sound/driver.h>
23#include <linux/slab.h>
24#include <sound/core.h>
25#include <sound/gus.h>
26#include <sound/info.h>
27
28typedef struct gus_proc_private {
29 int rom; /* data are in ROM */
30 unsigned int address;
31 unsigned int size;
32 snd_gus_card_t * gus;
33} gus_proc_private_t;
34
35static long snd_gf1_mem_proc_dump(snd_info_entry_t *entry, void *file_private_data,
36 struct file *file, char __user *buf,
37 unsigned long count, unsigned long pos)
38{
39 long size;
40 gus_proc_private_t *priv = entry->private_data;
41 snd_gus_card_t *gus = priv->gus;
42 int err;
43
44 size = count;
45 if (pos + size > priv->size)
46 size = (long)priv->size - pos;
47 if (size > 0) {
48 if ((err = snd_gus_dram_read(gus, buf, pos, size, priv->rom)) < 0)
49 return err;
50 return size;
51 }
52 return 0;
53}
54
55static long long snd_gf1_mem_proc_llseek(snd_info_entry_t *entry,
56 void *private_file_data,
57 struct file *file,
58 long long offset,
59 int orig)
60{
61 gus_proc_private_t *priv = entry->private_data;
62
63 switch (orig) {
64 case 0: /* SEEK_SET */
65 file->f_pos = offset;
66 break;
67 case 1: /* SEEK_CUR */
68 file->f_pos += offset;
69 break;
70 case 2: /* SEEK_END, offset is negative */
71 file->f_pos = priv->size + offset;
72 break;
73 default:
74 return -EINVAL;
75 }
76 if (file->f_pos > priv->size)
77 file->f_pos = priv->size;
78 return file->f_pos;
79}
80
81static void snd_gf1_mem_proc_free(snd_info_entry_t *entry)
82{
83 gus_proc_private_t *priv = entry->private_data;
84 kfree(priv);
85}
86
87static struct snd_info_entry_ops snd_gf1_mem_proc_ops = {
88 .read = snd_gf1_mem_proc_dump,
89 .llseek = snd_gf1_mem_proc_llseek,
90};
91
92int snd_gf1_mem_proc_init(snd_gus_card_t * gus)
93{
94 int idx;
95 char name[16];
96 gus_proc_private_t *priv;
97 snd_info_entry_t *entry;
98
99 for (idx = 0; idx < 4; idx++) {
100 if (gus->gf1.mem_alloc.banks_8[idx].size > 0) {
101 priv = kcalloc(1, sizeof(*priv), GFP_KERNEL);
102 if (priv == NULL)
103 return -ENOMEM;
104 priv->gus = gus;
105 sprintf(name, "gus-ram-%i", idx);
106 if (! snd_card_proc_new(gus->card, name, &entry)) {
107 entry->content = SNDRV_INFO_CONTENT_DATA;
108 entry->private_data = priv;
109 entry->private_free = snd_gf1_mem_proc_free;
110 entry->c.ops = &snd_gf1_mem_proc_ops;
111 priv->address = gus->gf1.mem_alloc.banks_8[idx].address;
112 priv->size = entry->size = gus->gf1.mem_alloc.banks_8[idx].size;
113 }
114 }
115 }
116 for (idx = 0; idx < 4; idx++) {
117 if (gus->gf1.rom_present & (1 << idx)) {
118 priv = kcalloc(1, sizeof(*priv), GFP_KERNEL);
119 if (priv == NULL)
120 return -ENOMEM;
121 priv->rom = 1;
122 priv->gus = gus;
123 sprintf(name, "gus-rom-%i", idx);
124 if (! snd_card_proc_new(gus->card, name, &entry)) {
125 entry->content = SNDRV_INFO_CONTENT_DATA;
126 entry->private_data = priv;
127 entry->private_free = snd_gf1_mem_proc_free;
128 entry->c.ops = &snd_gf1_mem_proc_ops;
129 priv->address = idx * 4096 * 1024;
130 priv->size = entry->size = gus->gf1.rom_memory;
131 }
132 }
133 }
134 return 0;
135}
diff --git a/sound/isa/gus/gus_mixer.c b/sound/isa/gus/gus_mixer.c
new file mode 100644
index 000000000000..a051094d510e
--- /dev/null
+++ b/sound/isa/gus/gus_mixer.c
@@ -0,0 +1,199 @@
1/*
2 * Copyright (c) by Jaroslav Kysela <perex@suse.cz>
3 * Routines for control of ICS 2101 chip and "mixer" in GF1 chip
4 *
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 *
20 */
21
22#include <sound/driver.h>
23#include <linux/time.h>
24#include <linux/wait.h>
25#include <sound/core.h>
26#include <sound/control.h>
27#include <sound/gus.h>
28
29/*
30 *
31 */
32
33#define GF1_SINGLE(xname, xindex, shift, invert) \
34{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xindex, \
35 .info = snd_gf1_info_single, \
36 .get = snd_gf1_get_single, .put = snd_gf1_put_single, \
37 .private_value = shift | (invert << 8) }
38
39static int snd_gf1_info_single(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
40{
41 uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
42 uinfo->count = 1;
43 uinfo->value.integer.min = 0;
44 uinfo->value.integer.max = 1;
45 return 0;
46}
47
48static int snd_gf1_get_single(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
49{
50 snd_gus_card_t *gus = snd_kcontrol_chip(kcontrol);
51 int shift = kcontrol->private_value & 0xff;
52 int invert = (kcontrol->private_value >> 8) & 1;
53
54 ucontrol->value.integer.value[0] = (gus->mix_cntrl_reg >> shift) & 1;
55 if (invert)
56 ucontrol->value.integer.value[0] ^= 1;
57 return 0;
58}
59
60static int snd_gf1_put_single(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
61{
62 snd_gus_card_t *gus = snd_kcontrol_chip(kcontrol);
63 unsigned long flags;
64 int shift = kcontrol->private_value & 0xff;
65 int invert = (kcontrol->private_value >> 8) & 1;
66 int change;
67 unsigned char oval, nval;
68
69 nval = ucontrol->value.integer.value[0] & 1;
70 if (invert)
71 nval ^= 1;
72 nval <<= shift;
73 spin_lock_irqsave(&gus->reg_lock, flags);
74 oval = gus->mix_cntrl_reg;
75 nval = (oval & ~(1 << shift)) | nval;
76 change = nval != oval;
77 outb(gus->mix_cntrl_reg = nval, GUSP(gus, MIXCNTRLREG));
78 outb(gus->gf1.active_voice = 0, GUSP(gus, GF1PAGE));
79 spin_unlock_irqrestore(&gus->reg_lock, flags);
80 return change;
81}
82
83#define ICS_DOUBLE(xname, xindex, addr) \
84{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xindex, \
85 .info = snd_ics_info_double, \
86 .get = snd_ics_get_double, .put = snd_ics_put_double, \
87 .private_value = addr }
88
89static int snd_ics_info_double(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
90{
91 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
92 uinfo->count = 2;
93 uinfo->value.integer.min = 0;
94 uinfo->value.integer.max = 127;
95 return 0;
96}
97
98static int snd_ics_get_double(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
99{
100 snd_gus_card_t *gus = snd_kcontrol_chip(kcontrol);
101 unsigned long flags;
102 int addr = kcontrol->private_value & 0xff;
103 unsigned char left, right;
104
105 spin_lock_irqsave(&gus->reg_lock, flags);
106 left = gus->gf1.ics_regs[addr][0];
107 right = gus->gf1.ics_regs[addr][1];
108 spin_unlock_irqrestore(&gus->reg_lock, flags);
109 ucontrol->value.integer.value[0] = left & 127;
110 ucontrol->value.integer.value[1] = right & 127;
111 return 0;
112}
113
114static int snd_ics_put_double(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
115{
116 snd_gus_card_t *gus = snd_kcontrol_chip(kcontrol);
117 unsigned long flags;
118 int addr = kcontrol->private_value & 0xff;
119 int change;
120 unsigned char val1, val2, oval1, oval2, tmp;
121
122 val1 = ucontrol->value.integer.value[0] & 127;
123 val2 = ucontrol->value.integer.value[1] & 127;
124 spin_lock_irqsave(&gus->reg_lock, flags);
125 oval1 = gus->gf1.ics_regs[addr][0];
126 oval2 = gus->gf1.ics_regs[addr][1];
127 change = val1 != oval1 || val2 != oval2;
128 gus->gf1.ics_regs[addr][0] = val1;
129 gus->gf1.ics_regs[addr][1] = val2;
130 if (gus->ics_flag && gus->ics_flipped &&
131 (addr == SNDRV_ICS_GF1_DEV || addr == SNDRV_ICS_MASTER_DEV)) {
132 tmp = val1;
133 val1 = val2;
134 val2 = tmp;
135 }
136 addr <<= 3;
137 outb(addr | 0, GUSP(gus, MIXCNTRLPORT));
138 outb(1, GUSP(gus, MIXDATAPORT));
139 outb(addr | 2, GUSP(gus, MIXCNTRLPORT));
140 outb((unsigned char) val1, GUSP(gus, MIXDATAPORT));
141 outb(addr | 1, GUSP(gus, MIXCNTRLPORT));
142 outb(2, GUSP(gus, MIXDATAPORT));
143 outb(addr | 3, GUSP(gus, MIXCNTRLPORT));
144 outb((unsigned char) val2, GUSP(gus, MIXDATAPORT));
145 spin_unlock_irqrestore(&gus->reg_lock, flags);
146 return change;
147}
148
149static snd_kcontrol_new_t snd_gf1_controls[] = {
150GF1_SINGLE("Master Playback Switch", 0, 1, 1),
151GF1_SINGLE("Line Switch", 0, 0, 1),
152GF1_SINGLE("Mic Switch", 0, 2, 0)
153};
154
155static snd_kcontrol_new_t snd_ics_controls[] = {
156GF1_SINGLE("Master Playback Switch", 0, 1, 1),
157ICS_DOUBLE("Master Playback Volume", 0, SNDRV_ICS_MASTER_DEV),
158ICS_DOUBLE("Synth Playback Volume", 0, SNDRV_ICS_GF1_DEV),
159GF1_SINGLE("Line Switch", 0, 0, 1),
160ICS_DOUBLE("Line Playback Volume", 0, SNDRV_ICS_LINE_DEV),
161GF1_SINGLE("Mic Switch", 0, 2, 0),
162ICS_DOUBLE("Mic Playback Volume", 0, SNDRV_ICS_MIC_DEV),
163ICS_DOUBLE("CD Playback Volume", 0, SNDRV_ICS_CD_DEV)
164};
165
166int snd_gf1_new_mixer(snd_gus_card_t * gus)
167{
168 snd_card_t *card;
169 unsigned int idx, max;
170 int err;
171
172 snd_assert(gus != NULL, return -EINVAL);
173 card = gus->card;
174 snd_assert(card != NULL, return -EINVAL);
175
176 if (gus->ics_flag)
177 snd_component_add(card, "ICS2101");
178 if (card->mixername[0] == '\0') {
179 strcpy(card->mixername, gus->ics_flag ? "GF1,ICS2101" : "GF1");
180 } else {
181 if (gus->ics_flag)
182 strcat(card->mixername, ",ICS2101");
183 strcat(card->mixername, ",GF1");
184 }
185
186 if (!gus->ics_flag) {
187 max = gus->ess_flag ? 1 : ARRAY_SIZE(snd_gf1_controls);
188 for (idx = 0; idx < max; idx++) {
189 if ((err = snd_ctl_add(card, snd_ctl_new1(&snd_gf1_controls[idx], gus))) < 0)
190 return err;
191 }
192 } else {
193 for (idx = 0; idx < ARRAY_SIZE(snd_ics_controls); idx++) {
194 if ((err = snd_ctl_add(card, snd_ctl_new1(&snd_ics_controls[idx], gus))) < 0)
195 return err;
196 }
197 }
198 return 0;
199}
diff --git a/sound/isa/gus/gus_pcm.c b/sound/isa/gus/gus_pcm.c
new file mode 100644
index 000000000000..8995ad9c516d
--- /dev/null
+++ b/sound/isa/gus/gus_pcm.c
@@ -0,0 +1,903 @@
1/*
2 * Copyright (c) by Jaroslav Kysela <perex@suse.cz>
3 * Routines for control of GF1 chip (PCM things)
4 *
5 * InterWave chips supports interleaved DMA, but this feature isn't used in
6 * this code.
7 *
8 * This code emulates autoinit DMA transfer for playback, recording by GF1
9 * chip doesn't support autoinit DMA.
10 *
11 *
12 * This program is free software; you can redistribute it and/or modify
13 * it under the terms of the GNU General Public License as published by
14 * the Free Software Foundation; either version 2 of the License, or
15 * (at your option) any later version.
16 *
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software
24 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
25 *
26 */
27
28#include <sound/driver.h>
29#include <asm/dma.h>
30#include <linux/slab.h>
31#include <sound/core.h>
32#include <sound/control.h>
33#include <sound/gus.h>
34#include <sound/pcm_params.h>
35#include "gus_tables.h"
36
37/* maximum rate */
38
39#define SNDRV_GF1_PCM_RATE 48000
40
41#define SNDRV_GF1_PCM_PFLG_NONE 0
42#define SNDRV_GF1_PCM_PFLG_ACTIVE (1<<0)
43#define SNDRV_GF1_PCM_PFLG_NEUTRAL (2<<0)
44
45typedef struct {
46 snd_gus_card_t * gus;
47 snd_pcm_substream_t * substream;
48 spinlock_t lock;
49 unsigned int voices;
50 snd_gus_voice_t *pvoices[2];
51 unsigned int memory;
52 unsigned short flags;
53 unsigned char voice_ctrl, ramp_ctrl;
54 unsigned int bpos;
55 unsigned int blocks;
56 unsigned int block_size;
57 unsigned int dma_size;
58 wait_queue_head_t sleep;
59 atomic_t dma_count;
60 int final_volume;
61} gus_pcm_private_t;
62
63static int snd_gf1_pcm_use_dma = 1;
64
65static void snd_gf1_pcm_block_change_ack(snd_gus_card_t * gus, void *private_data)
66{
67 gus_pcm_private_t *pcmp = private_data;
68
69 if (pcmp) {
70 atomic_dec(&pcmp->dma_count);
71 wake_up(&pcmp->sleep);
72 }
73}
74
75static int snd_gf1_pcm_block_change(snd_pcm_substream_t * substream,
76 unsigned int offset,
77 unsigned int addr,
78 unsigned int count)
79{
80 snd_gf1_dma_block_t block;
81 snd_pcm_runtime_t *runtime = substream->runtime;
82 gus_pcm_private_t *pcmp = runtime->private_data;
83
84 count += offset & 31;
85 offset &= ~31;
86 // snd_printk("block change - offset = 0x%x, count = 0x%x\n", offset, count);
87 memset(&block, 0, sizeof(block));
88 block.cmd = SNDRV_GF1_DMA_IRQ;
89 if (snd_pcm_format_unsigned(runtime->format))
90 block.cmd |= SNDRV_GF1_DMA_UNSIGNED;
91 if (snd_pcm_format_width(runtime->format) == 16)
92 block.cmd |= SNDRV_GF1_DMA_16BIT;
93 block.addr = addr & ~31;
94 block.buffer = runtime->dma_area + offset;
95 block.buf_addr = runtime->dma_addr + offset;
96 block.count = count;
97 block.private_data = pcmp;
98 block.ack = snd_gf1_pcm_block_change_ack;
99 if (!snd_gf1_dma_transfer_block(pcmp->gus, &block, 0, 0))
100 atomic_inc(&pcmp->dma_count);
101 return 0;
102}
103
104static void snd_gf1_pcm_trigger_up(snd_pcm_substream_t * substream)
105{
106 snd_pcm_runtime_t *runtime = substream->runtime;
107 gus_pcm_private_t *pcmp = runtime->private_data;
108 snd_gus_card_t * gus = pcmp->gus;
109 unsigned long flags;
110 unsigned char voice_ctrl, ramp_ctrl;
111 unsigned short rate;
112 unsigned int curr, begin, end;
113 unsigned short vol;
114 unsigned char pan;
115 unsigned int voice;
116
117 if (substream == NULL)
118 return;
119 spin_lock_irqsave(&pcmp->lock, flags);
120 if (pcmp->flags & SNDRV_GF1_PCM_PFLG_ACTIVE) {
121 spin_unlock_irqrestore(&pcmp->lock, flags);
122 return;
123 }
124 pcmp->flags |= SNDRV_GF1_PCM_PFLG_ACTIVE;
125 pcmp->final_volume = 0;
126 spin_unlock_irqrestore(&pcmp->lock, flags);
127 rate = snd_gf1_translate_freq(gus, runtime->rate << 4);
128 /* enable WAVE IRQ */
129 voice_ctrl = snd_pcm_format_width(runtime->format) == 16 ? 0x24 : 0x20;
130 /* enable RAMP IRQ + rollover */
131 ramp_ctrl = 0x24;
132 if (pcmp->blocks == 1) {
133 voice_ctrl |= 0x08; /* loop enable */
134 ramp_ctrl &= ~0x04; /* disable rollover */
135 }
136 for (voice = 0; voice < pcmp->voices; voice++) {
137 begin = pcmp->memory + voice * (pcmp->dma_size / runtime->channels);
138 curr = begin + (pcmp->bpos * pcmp->block_size) / runtime->channels;
139 end = curr + (pcmp->block_size / runtime->channels);
140 end -= snd_pcm_format_width(runtime->format) == 16 ? 2 : 1;
141 // snd_printk("init: curr=0x%x, begin=0x%x, end=0x%x, ctrl=0x%x, ramp=0x%x, rate=0x%x\n", curr, begin, end, voice_ctrl, ramp_ctrl, rate);
142 pan = runtime->channels == 2 ? (!voice ? 1 : 14) : 8;
143 vol = !voice ? gus->gf1.pcm_volume_level_left : gus->gf1.pcm_volume_level_right;
144 spin_lock_irqsave(&gus->reg_lock, flags);
145 snd_gf1_select_voice(gus, pcmp->pvoices[voice]->number);
146 snd_gf1_write8(gus, SNDRV_GF1_VB_PAN, pan);
147 snd_gf1_write16(gus, SNDRV_GF1_VW_FREQUENCY, rate);
148 snd_gf1_write_addr(gus, SNDRV_GF1_VA_START, begin << 4, voice_ctrl & 4);
149 snd_gf1_write_addr(gus, SNDRV_GF1_VA_END, end << 4, voice_ctrl & 4);
150 snd_gf1_write_addr(gus, SNDRV_GF1_VA_CURRENT, curr << 4, voice_ctrl & 4);
151 snd_gf1_write16(gus, SNDRV_GF1_VW_VOLUME, SNDRV_GF1_MIN_VOLUME << 4);
152 snd_gf1_write8(gus, SNDRV_GF1_VB_VOLUME_RATE, 0x2f);
153 snd_gf1_write8(gus, SNDRV_GF1_VB_VOLUME_START, SNDRV_GF1_MIN_OFFSET);
154 snd_gf1_write8(gus, SNDRV_GF1_VB_VOLUME_END, vol >> 8);
155 snd_gf1_write8(gus, SNDRV_GF1_VB_VOLUME_CONTROL, ramp_ctrl);
156 if (!gus->gf1.enh_mode) {
157 snd_gf1_delay(gus);
158 snd_gf1_write8(gus, SNDRV_GF1_VB_VOLUME_CONTROL, ramp_ctrl);
159 }
160 spin_unlock_irqrestore(&gus->reg_lock, flags);
161 }
162 spin_lock_irqsave(&gus->reg_lock, flags);
163 for (voice = 0; voice < pcmp->voices; voice++) {
164 snd_gf1_select_voice(gus, pcmp->pvoices[voice]->number);
165 if (gus->gf1.enh_mode)
166 snd_gf1_write8(gus, SNDRV_GF1_VB_MODE, 0x00); /* deactivate voice */
167 snd_gf1_write8(gus, SNDRV_GF1_VB_ADDRESS_CONTROL, voice_ctrl);
168 voice_ctrl &= ~0x20;
169 }
170 voice_ctrl |= 0x20;
171 if (!gus->gf1.enh_mode) {
172 snd_gf1_delay(gus);
173 for (voice = 0; voice < pcmp->voices; voice++) {
174 snd_gf1_select_voice(gus, pcmp->pvoices[voice]->number);
175 snd_gf1_write8(gus, SNDRV_GF1_VB_ADDRESS_CONTROL, voice_ctrl);
176 voice_ctrl &= ~0x20; /* disable IRQ for next voice */
177 }
178 }
179 spin_unlock_irqrestore(&gus->reg_lock, flags);
180}
181
182static void snd_gf1_pcm_interrupt_wave(snd_gus_card_t * gus, snd_gus_voice_t *pvoice)
183{
184 gus_pcm_private_t * pcmp;
185 snd_pcm_runtime_t * runtime;
186 unsigned char voice_ctrl, ramp_ctrl;
187 unsigned int idx;
188 unsigned int end, step;
189
190 if (!pvoice->private_data) {
191 snd_printd("snd_gf1_pcm: unknown wave irq?\n");
192 snd_gf1_smart_stop_voice(gus, pvoice->number);
193 return;
194 }
195 pcmp = pvoice->private_data;
196 if (pcmp == NULL) {
197 snd_printd("snd_gf1_pcm: unknown wave irq?\n");
198 snd_gf1_smart_stop_voice(gus, pvoice->number);
199 return;
200 }
201 gus = pcmp->gus;
202 runtime = pcmp->substream->runtime;
203
204 spin_lock(&gus->reg_lock);
205 snd_gf1_select_voice(gus, pvoice->number);
206 voice_ctrl = snd_gf1_read8(gus, SNDRV_GF1_VB_ADDRESS_CONTROL) & ~0x8b;
207 ramp_ctrl = (snd_gf1_read8(gus, SNDRV_GF1_VB_VOLUME_CONTROL) & ~0xa4) | 0x03;
208#if 0
209 snd_gf1_select_voice(gus, pvoice->number);
210 printk("position = 0x%x\n", (snd_gf1_read_addr(gus, SNDRV_GF1_VA_CURRENT, voice_ctrl & 4) >> 4));
211 snd_gf1_select_voice(gus, pcmp->pvoices[1]->number);
212 printk("position = 0x%x\n", (snd_gf1_read_addr(gus, SNDRV_GF1_VA_CURRENT, voice_ctrl & 4) >> 4));
213 snd_gf1_select_voice(gus, pvoice->number);
214#endif
215 pcmp->bpos++;
216 pcmp->bpos %= pcmp->blocks;
217 if (pcmp->bpos + 1 >= pcmp->blocks) { /* last block? */
218 voice_ctrl |= 0x08; /* enable loop */
219 } else {
220 ramp_ctrl |= 0x04; /* enable rollover */
221 }
222 end = pcmp->memory + (((pcmp->bpos + 1) * pcmp->block_size) / runtime->channels);
223 end -= voice_ctrl & 4 ? 2 : 1;
224 step = pcmp->dma_size / runtime->channels;
225 voice_ctrl |= 0x20;
226 if (!pcmp->final_volume) {
227 ramp_ctrl |= 0x20;
228 ramp_ctrl &= ~0x03;
229 }
230 for (idx = 0; idx < pcmp->voices; idx++, end += step) {
231 snd_gf1_select_voice(gus, pcmp->pvoices[idx]->number);
232 snd_gf1_write_addr(gus, SNDRV_GF1_VA_END, end << 4, voice_ctrl & 4);
233 snd_gf1_write8(gus, SNDRV_GF1_VB_ADDRESS_CONTROL, voice_ctrl);
234 snd_gf1_write8(gus, SNDRV_GF1_VB_VOLUME_CONTROL, ramp_ctrl);
235 voice_ctrl &= ~0x20;
236 }
237 if (!gus->gf1.enh_mode) {
238 snd_gf1_delay(gus);
239 voice_ctrl |= 0x20;
240 for (idx = 0; idx < pcmp->voices; idx++) {
241 snd_gf1_select_voice(gus, pcmp->pvoices[idx]->number);
242 snd_gf1_write8(gus, SNDRV_GF1_VB_ADDRESS_CONTROL, voice_ctrl);
243 snd_gf1_write8(gus, SNDRV_GF1_VB_VOLUME_CONTROL, ramp_ctrl);
244 voice_ctrl &= ~0x20;
245 }
246 }
247 spin_unlock(&gus->reg_lock);
248
249 snd_pcm_period_elapsed(pcmp->substream);
250#if 0
251 if ((runtime->flags & SNDRV_PCM_FLG_MMAP) &&
252 *runtime->state == SNDRV_PCM_STATE_RUNNING) {
253 end = pcmp->bpos * pcmp->block_size;
254 if (runtime->channels > 1) {
255 snd_gf1_pcm_block_change(pcmp->substream, end, pcmp->memory + (end / 2), pcmp->block_size / 2);
256 snd_gf1_pcm_block_change(pcmp->substream, end + (pcmp->block_size / 2), pcmp->memory + (pcmp->dma_size / 2) + (end / 2), pcmp->block_size / 2);
257 } else {
258 snd_gf1_pcm_block_change(pcmp->substream, end, pcmp->memory + end, pcmp->block_size);
259 }
260 }
261#endif
262}
263
264static void snd_gf1_pcm_interrupt_volume(snd_gus_card_t * gus, snd_gus_voice_t * pvoice)
265{
266 unsigned short vol;
267 int cvoice;
268 gus_pcm_private_t *pcmp = pvoice->private_data;
269
270 /* stop ramp, but leave rollover bit untouched */
271 spin_lock(&gus->reg_lock);
272 snd_gf1_select_voice(gus, pvoice->number);
273 snd_gf1_ctrl_stop(gus, SNDRV_GF1_VB_VOLUME_CONTROL);
274 spin_unlock(&gus->reg_lock);
275 if (pcmp == NULL)
276 return;
277 /* are we active? */
278 if (!(pcmp->flags & SNDRV_GF1_PCM_PFLG_ACTIVE))
279 return;
280 /* load real volume - better precision */
281 cvoice = pcmp->pvoices[0] == pvoice ? 0 : 1;
282 if (pcmp->substream == NULL)
283 return;
284 vol = !cvoice ? gus->gf1.pcm_volume_level_left : gus->gf1.pcm_volume_level_right;
285 spin_lock(&gus->reg_lock);
286 snd_gf1_select_voice(gus, pvoice->number);
287 snd_gf1_write16(gus, SNDRV_GF1_VW_VOLUME, vol);
288 pcmp->final_volume = 1;
289 spin_unlock(&gus->reg_lock);
290}
291
292static void snd_gf1_pcm_volume_change(snd_gus_card_t * gus)
293{
294}
295
296static int snd_gf1_pcm_poke_block(snd_gus_card_t *gus, unsigned char *buf,
297 unsigned int pos, unsigned int count,
298 int w16, int invert)
299{
300 unsigned int len;
301 unsigned long flags;
302
303 // printk("poke block; buf = 0x%x, pos = %i, count = %i, port = 0x%x\n", (int)buf, pos, count, gus->gf1.port);
304 while (count > 0) {
305 len = count;
306 if (len > 512) /* limit, to allow IRQ */
307 len = 512;
308 count -= len;
309 if (gus->interwave) {
310 spin_lock_irqsave(&gus->reg_lock, flags);
311 snd_gf1_write8(gus, SNDRV_GF1_GB_MEMORY_CONTROL, 0x01 | (invert ? 0x08 : 0x00));
312 snd_gf1_dram_addr(gus, pos);
313 if (w16) {
314 outb(SNDRV_GF1_GW_DRAM_IO16, GUSP(gus, GF1REGSEL));
315 outsw(GUSP(gus, GF1DATALOW), buf, len >> 1);
316 } else {
317 outsb(GUSP(gus, DRAM), buf, len);
318 }
319 spin_unlock_irqrestore(&gus->reg_lock, flags);
320 buf += 512;
321 pos += 512;
322 } else {
323 invert = invert ? 0x80 : 0x00;
324 if (w16) {
325 len >>= 1;
326 while (len--) {
327 snd_gf1_poke(gus, pos++, *buf++);
328 snd_gf1_poke(gus, pos++, *buf++ ^ invert);
329 }
330 } else {
331 while (len--)
332 snd_gf1_poke(gus, pos++, *buf++ ^ invert);
333 }
334 }
335 if (count > 0 && !in_interrupt()) {
336 set_current_state(TASK_INTERRUPTIBLE);
337 schedule_timeout(1);
338 if (signal_pending(current))
339 return -EAGAIN;
340 }
341 }
342 return 0;
343}
344
345static int snd_gf1_pcm_playback_copy(snd_pcm_substream_t *substream,
346 int voice,
347 snd_pcm_uframes_t pos,
348 void __user *src,
349 snd_pcm_uframes_t count)
350{
351 snd_pcm_runtime_t *runtime = substream->runtime;
352 gus_pcm_private_t *pcmp = runtime->private_data;
353 unsigned int bpos, len;
354
355 bpos = samples_to_bytes(runtime, pos) + (voice * (pcmp->dma_size / 2));
356 len = samples_to_bytes(runtime, count);
357 snd_assert(bpos <= pcmp->dma_size, return -EIO);
358 snd_assert(bpos + len <= pcmp->dma_size, return -EIO);
359 if (copy_from_user(runtime->dma_area + bpos, src, len))
360 return -EFAULT;
361 if (snd_gf1_pcm_use_dma && len > 32) {
362 return snd_gf1_pcm_block_change(substream, bpos, pcmp->memory + bpos, len);
363 } else {
364 snd_gus_card_t *gus = pcmp->gus;
365 int err, w16, invert;
366
367 w16 = (snd_pcm_format_width(runtime->format) == 16);
368 invert = snd_pcm_format_unsigned(runtime->format);
369 if ((err = snd_gf1_pcm_poke_block(gus, runtime->dma_area + bpos, pcmp->memory + bpos, len, w16, invert)) < 0)
370 return err;
371 }
372 return 0;
373}
374
375static int snd_gf1_pcm_playback_silence(snd_pcm_substream_t *substream,
376 int voice,
377 snd_pcm_uframes_t pos,
378 snd_pcm_uframes_t count)
379{
380 snd_pcm_runtime_t *runtime = substream->runtime;
381 gus_pcm_private_t *pcmp = runtime->private_data;
382 unsigned int bpos, len;
383
384 bpos = samples_to_bytes(runtime, pos) + (voice * (pcmp->dma_size / 2));
385 len = samples_to_bytes(runtime, count);
386 snd_assert(bpos <= pcmp->dma_size, return -EIO);
387 snd_assert(bpos + len <= pcmp->dma_size, return -EIO);
388 snd_pcm_format_set_silence(runtime->format, runtime->dma_area + bpos, count);
389 if (snd_gf1_pcm_use_dma && len > 32) {
390 return snd_gf1_pcm_block_change(substream, bpos, pcmp->memory + bpos, len);
391 } else {
392 snd_gus_card_t *gus = pcmp->gus;
393 int err, w16, invert;
394
395 w16 = (snd_pcm_format_width(runtime->format) == 16);
396 invert = snd_pcm_format_unsigned(runtime->format);
397 if ((err = snd_gf1_pcm_poke_block(gus, runtime->dma_area + bpos, pcmp->memory + bpos, len, w16, invert)) < 0)
398 return err;
399 }
400 return 0;
401}
402
403static int snd_gf1_pcm_playback_hw_params(snd_pcm_substream_t * substream,
404 snd_pcm_hw_params_t * hw_params)
405{
406 snd_gus_card_t *gus = snd_pcm_substream_chip(substream);
407 snd_pcm_runtime_t *runtime = substream->runtime;
408 gus_pcm_private_t *pcmp = runtime->private_data;
409 int err;
410
411 if ((err = snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(hw_params))) < 0)
412 return err;
413 if (err > 0) { /* change */
414 snd_gf1_mem_block_t *block;
415 if (pcmp->memory > 0) {
416 snd_gf1_mem_free(&gus->gf1.mem_alloc, pcmp->memory);
417 pcmp->memory = 0;
418 }
419 if ((block = snd_gf1_mem_alloc(&gus->gf1.mem_alloc,
420 SNDRV_GF1_MEM_OWNER_DRIVER,
421 "GF1 PCM",
422 runtime->dma_bytes, 1, 32,
423 NULL)) == NULL)
424 return -ENOMEM;
425 pcmp->memory = block->ptr;
426 }
427 pcmp->voices = params_channels(hw_params);
428 if (pcmp->pvoices[0] == NULL) {
429 if ((pcmp->pvoices[0] = snd_gf1_alloc_voice(pcmp->gus, SNDRV_GF1_VOICE_TYPE_PCM, 0, 0)) == NULL)
430 return -ENOMEM;
431 pcmp->pvoices[0]->handler_wave = snd_gf1_pcm_interrupt_wave;
432 pcmp->pvoices[0]->handler_volume = snd_gf1_pcm_interrupt_volume;
433 pcmp->pvoices[0]->volume_change = snd_gf1_pcm_volume_change;
434 pcmp->pvoices[0]->private_data = pcmp;
435 }
436 if (pcmp->voices > 1 && pcmp->pvoices[1] == NULL) {
437 if ((pcmp->pvoices[1] = snd_gf1_alloc_voice(pcmp->gus, SNDRV_GF1_VOICE_TYPE_PCM, 0, 0)) == NULL)
438 return -ENOMEM;
439 pcmp->pvoices[1]->handler_wave = snd_gf1_pcm_interrupt_wave;
440 pcmp->pvoices[1]->handler_volume = snd_gf1_pcm_interrupt_volume;
441 pcmp->pvoices[1]->volume_change = snd_gf1_pcm_volume_change;
442 pcmp->pvoices[1]->private_data = pcmp;
443 } else if (pcmp->voices == 1) {
444 if (pcmp->pvoices[1]) {
445 snd_gf1_free_voice(pcmp->gus, pcmp->pvoices[1]);
446 pcmp->pvoices[1] = NULL;
447 }
448 }
449 return 0;
450}
451
452static int snd_gf1_pcm_playback_hw_free(snd_pcm_substream_t * substream)
453{
454 snd_pcm_runtime_t *runtime = substream->runtime;
455 gus_pcm_private_t *pcmp = runtime->private_data;
456
457 snd_pcm_lib_free_pages(substream);
458 if (pcmp->pvoices[0]) {
459 snd_gf1_free_voice(pcmp->gus, pcmp->pvoices[0]);
460 pcmp->pvoices[0] = NULL;
461 }
462 if (pcmp->pvoices[1]) {
463 snd_gf1_free_voice(pcmp->gus, pcmp->pvoices[1]);
464 pcmp->pvoices[1] = NULL;
465 }
466 if (pcmp->memory > 0) {
467 snd_gf1_mem_free(&pcmp->gus->gf1.mem_alloc, pcmp->memory);
468 pcmp->memory = 0;
469 }
470 return 0;
471}
472
473static int snd_gf1_pcm_playback_prepare(snd_pcm_substream_t * substream)
474{
475 snd_pcm_runtime_t *runtime = substream->runtime;
476 gus_pcm_private_t *pcmp = runtime->private_data;
477
478 pcmp->bpos = 0;
479 pcmp->dma_size = snd_pcm_lib_buffer_bytes(substream);
480 pcmp->block_size = snd_pcm_lib_period_bytes(substream);
481 pcmp->blocks = pcmp->dma_size / pcmp->block_size;
482 return 0;
483}
484
485static int snd_gf1_pcm_playback_trigger(snd_pcm_substream_t * substream,
486 int cmd)
487{
488 snd_gus_card_t *gus = snd_pcm_substream_chip(substream);
489 snd_pcm_runtime_t *runtime = substream->runtime;
490 gus_pcm_private_t *pcmp = runtime->private_data;
491 int voice;
492
493 if (cmd == SNDRV_PCM_TRIGGER_START) {
494 snd_gf1_pcm_trigger_up(substream);
495 } else if (cmd == SNDRV_PCM_TRIGGER_STOP) {
496 spin_lock(&pcmp->lock);
497 pcmp->flags &= ~SNDRV_GF1_PCM_PFLG_ACTIVE;
498 spin_unlock(&pcmp->lock);
499 voice = pcmp->pvoices[0]->number;
500 snd_gf1_stop_voices(gus, voice, voice);
501 if (pcmp->pvoices[1]) {
502 voice = pcmp->pvoices[1]->number;
503 snd_gf1_stop_voices(gus, voice, voice);
504 }
505 } else {
506 return -EINVAL;
507 }
508 return 0;
509}
510
511static snd_pcm_uframes_t snd_gf1_pcm_playback_pointer(snd_pcm_substream_t * substream)
512{
513 snd_gus_card_t *gus = snd_pcm_substream_chip(substream);
514 snd_pcm_runtime_t *runtime = substream->runtime;
515 gus_pcm_private_t *pcmp = runtime->private_data;
516 unsigned int pos;
517 unsigned char voice_ctrl;
518
519 pos = 0;
520 spin_lock(&gus->reg_lock);
521 if (pcmp->flags & SNDRV_GF1_PCM_PFLG_ACTIVE) {
522 snd_gf1_select_voice(gus, pcmp->pvoices[0]->number);
523 voice_ctrl = snd_gf1_read8(gus, SNDRV_GF1_VB_ADDRESS_CONTROL);
524 pos = (snd_gf1_read_addr(gus, SNDRV_GF1_VA_CURRENT, voice_ctrl & 4) >> 4) - pcmp->memory;
525 if (substream->runtime->channels > 1)
526 pos <<= 1;
527 pos = bytes_to_frames(runtime, pos);
528 }
529 spin_unlock(&gus->reg_lock);
530 return pos;
531}
532
533static ratnum_t clock = {
534 .num = 9878400/16,
535 .den_min = 2,
536 .den_max = 257,
537 .den_step = 1,
538};
539
540static snd_pcm_hw_constraint_ratnums_t hw_constraints_clocks = {
541 .nrats = 1,
542 .rats = &clock,
543};
544
545static int snd_gf1_pcm_capture_hw_params(snd_pcm_substream_t * substream,
546 snd_pcm_hw_params_t * hw_params)
547{
548 snd_gus_card_t *gus = snd_pcm_substream_chip(substream);
549
550 gus->c_dma_size = params_buffer_bytes(hw_params);
551 gus->c_period_size = params_period_bytes(hw_params);
552 gus->c_pos = 0;
553 gus->gf1.pcm_rcntrl_reg = 0x21; /* IRQ at end, enable & start */
554 if (params_channels(hw_params) > 1)
555 gus->gf1.pcm_rcntrl_reg |= 2;
556 if (gus->gf1.dma2 > 3)
557 gus->gf1.pcm_rcntrl_reg |= 4;
558 if (snd_pcm_format_unsigned(params_format(hw_params)))
559 gus->gf1.pcm_rcntrl_reg |= 0x80;
560 return snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(hw_params));
561}
562
563static int snd_gf1_pcm_capture_hw_free(snd_pcm_substream_t * substream)
564{
565 return snd_pcm_lib_free_pages(substream);
566}
567
568static int snd_gf1_pcm_capture_prepare(snd_pcm_substream_t * substream)
569{
570 snd_gus_card_t *gus = snd_pcm_substream_chip(substream);
571 snd_pcm_runtime_t *runtime = substream->runtime;
572
573 snd_gf1_i_write8(gus, SNDRV_GF1_GB_RECORD_RATE, runtime->rate_den - 2);
574 snd_gf1_i_write8(gus, SNDRV_GF1_GB_REC_DMA_CONTROL, 0); /* disable sampling */
575 snd_gf1_i_look8(gus, SNDRV_GF1_GB_REC_DMA_CONTROL); /* Sampling Control Register */
576 snd_dma_program(gus->gf1.dma2, runtime->dma_addr, gus->c_period_size, DMA_MODE_READ);
577 return 0;
578}
579
580static int snd_gf1_pcm_capture_trigger(snd_pcm_substream_t * substream,
581 int cmd)
582{
583 snd_gus_card_t *gus = snd_pcm_substream_chip(substream);
584 int val;
585
586 if (cmd == SNDRV_PCM_TRIGGER_START) {
587 val = gus->gf1.pcm_rcntrl_reg;
588 } else if (cmd == SNDRV_PCM_TRIGGER_STOP) {
589 val = 0;
590 } else {
591 return -EINVAL;
592 }
593
594 spin_lock(&gus->reg_lock);
595 snd_gf1_write8(gus, SNDRV_GF1_GB_REC_DMA_CONTROL, val);
596 snd_gf1_look8(gus, SNDRV_GF1_GB_REC_DMA_CONTROL);
597 spin_unlock(&gus->reg_lock);
598 return 0;
599}
600
601static snd_pcm_uframes_t snd_gf1_pcm_capture_pointer(snd_pcm_substream_t * substream)
602{
603 snd_gus_card_t *gus = snd_pcm_substream_chip(substream);
604 int pos = snd_dma_pointer(gus->gf1.dma2, gus->c_period_size);
605 pos = bytes_to_frames(substream->runtime, (gus->c_pos + pos) % gus->c_dma_size);
606 return pos;
607}
608
609static void snd_gf1_pcm_interrupt_dma_read(snd_gus_card_t * gus)
610{
611 snd_gf1_i_write8(gus, SNDRV_GF1_GB_REC_DMA_CONTROL, 0); /* disable sampling */
612 snd_gf1_i_look8(gus, SNDRV_GF1_GB_REC_DMA_CONTROL); /* Sampling Control Register */
613 if (gus->pcm_cap_substream != NULL) {
614 snd_gf1_pcm_capture_prepare(gus->pcm_cap_substream);
615 snd_gf1_pcm_capture_trigger(gus->pcm_cap_substream, SNDRV_PCM_TRIGGER_START);
616 gus->c_pos += gus->c_period_size;
617 snd_pcm_period_elapsed(gus->pcm_cap_substream);
618 }
619}
620
621static snd_pcm_hardware_t snd_gf1_pcm_playback =
622{
623 .info = SNDRV_PCM_INFO_NONINTERLEAVED,
624 .formats = (SNDRV_PCM_FMTBIT_S8 | SNDRV_PCM_FMTBIT_U8 |
625 SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_U16_LE),
626 .rates = SNDRV_PCM_RATE_CONTINUOUS | SNDRV_PCM_RATE_8000_48000,
627 .rate_min = 5510,
628 .rate_max = 48000,
629 .channels_min = 1,
630 .channels_max = 2,
631 .buffer_bytes_max = (128*1024),
632 .period_bytes_min = 64,
633 .period_bytes_max = (128*1024),
634 .periods_min = 1,
635 .periods_max = 1024,
636 .fifo_size = 0,
637};
638
639static snd_pcm_hardware_t snd_gf1_pcm_capture =
640{
641 .info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED |
642 SNDRV_PCM_INFO_MMAP_VALID),
643 .formats = SNDRV_PCM_FMTBIT_S8 | SNDRV_PCM_FMTBIT_U8,
644 .rates = SNDRV_PCM_RATE_CONTINUOUS | SNDRV_PCM_RATE_8000_44100,
645 .rate_min = 5510,
646 .rate_max = 44100,
647 .channels_min = 1,
648 .channels_max = 2,
649 .buffer_bytes_max = (128*1024),
650 .period_bytes_min = 64,
651 .period_bytes_max = (128*1024),
652 .periods_min = 1,
653 .periods_max = 1024,
654 .fifo_size = 0,
655};
656
657static void snd_gf1_pcm_playback_free(snd_pcm_runtime_t *runtime)
658{
659 gus_pcm_private_t * pcmp = runtime->private_data;
660 kfree(pcmp);
661}
662
663static int snd_gf1_pcm_playback_open(snd_pcm_substream_t *substream)
664{
665 gus_pcm_private_t *pcmp;
666 snd_gus_card_t *gus = snd_pcm_substream_chip(substream);
667 snd_pcm_runtime_t *runtime = substream->runtime;
668 int err;
669
670 pcmp = kcalloc(1, sizeof(*pcmp), GFP_KERNEL);
671 if (pcmp == NULL)
672 return -ENOMEM;
673 pcmp->gus = gus;
674 spin_lock_init(&pcmp->lock);
675 init_waitqueue_head(&pcmp->sleep);
676 atomic_set(&pcmp->dma_count, 0);
677
678 runtime->private_data = pcmp;
679 runtime->private_free = snd_gf1_pcm_playback_free;
680
681#if 0
682 printk("playback.buffer = 0x%lx, gf1.pcm_buffer = 0x%lx\n", (long) pcm->playback.buffer, (long) gus->gf1.pcm_buffer);
683#endif
684 if ((err = snd_gf1_dma_init(gus)) < 0)
685 return err;
686 pcmp->flags = SNDRV_GF1_PCM_PFLG_NONE;
687 pcmp->substream = substream;
688 runtime->hw = snd_gf1_pcm_playback;
689 snd_pcm_limit_isa_dma_size(gus->gf1.dma1, &runtime->hw.buffer_bytes_max);
690 snd_pcm_limit_isa_dma_size(gus->gf1.dma1, &runtime->hw.period_bytes_max);
691 snd_pcm_hw_constraint_step(runtime, 0, SNDRV_PCM_HW_PARAM_PERIOD_BYTES, 64);
692 return 0;
693}
694
695static int snd_gf1_pcm_playback_close(snd_pcm_substream_t * substream)
696{
697 snd_gus_card_t *gus = snd_pcm_substream_chip(substream);
698 snd_pcm_runtime_t *runtime = substream->runtime;
699 gus_pcm_private_t *pcmp = runtime->private_data;
700
701 if (!wait_event_timeout(pcmp->sleep, (atomic_read(&pcmp->dma_count) <= 0), 2*HZ))
702 snd_printk("gf1 pcm - serious DMA problem\n");
703
704 snd_gf1_dma_done(gus);
705 return 0;
706}
707
708static int snd_gf1_pcm_capture_open(snd_pcm_substream_t * substream)
709{
710 snd_pcm_runtime_t *runtime = substream->runtime;
711 snd_gus_card_t *gus = snd_pcm_substream_chip(substream);
712
713 gus->gf1.interrupt_handler_dma_read = snd_gf1_pcm_interrupt_dma_read;
714 gus->pcm_cap_substream = substream;
715 substream->runtime->hw = snd_gf1_pcm_capture;
716 snd_pcm_limit_isa_dma_size(gus->gf1.dma2, &runtime->hw.buffer_bytes_max);
717 snd_pcm_limit_isa_dma_size(gus->gf1.dma2, &runtime->hw.period_bytes_max);
718 snd_pcm_hw_constraint_ratnums(runtime, 0, SNDRV_PCM_HW_PARAM_RATE,
719 &hw_constraints_clocks);
720 return 0;
721}
722
723static int snd_gf1_pcm_capture_close(snd_pcm_substream_t * substream)
724{
725 snd_gus_card_t *gus = snd_pcm_substream_chip(substream);
726
727 gus->pcm_cap_substream = NULL;
728 snd_gf1_set_default_handlers(gus, SNDRV_GF1_HANDLER_DMA_READ);
729 return 0;
730}
731
732static void snd_gf1_pcm_free(snd_pcm_t *pcm)
733{
734 snd_gus_card_t *gus = pcm->private_data;
735 gus->pcm = NULL;
736 snd_pcm_lib_preallocate_free_for_all(pcm);
737}
738
739static int snd_gf1_pcm_volume_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
740{
741 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
742 uinfo->count = 2;
743 uinfo->value.integer.min = 0;
744 uinfo->value.integer.max = 127;
745 return 0;
746}
747
748static int snd_gf1_pcm_volume_get(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
749{
750 snd_gus_card_t *gus = snd_kcontrol_chip(kcontrol);
751 unsigned long flags;
752
753 spin_lock_irqsave(&gus->pcm_volume_level_lock, flags);
754 ucontrol->value.integer.value[0] = gus->gf1.pcm_volume_level_left1;
755 ucontrol->value.integer.value[1] = gus->gf1.pcm_volume_level_right1;
756 spin_unlock_irqrestore(&gus->pcm_volume_level_lock, flags);
757 return 0;
758}
759
760static int snd_gf1_pcm_volume_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
761{
762 snd_gus_card_t *gus = snd_kcontrol_chip(kcontrol);
763 unsigned long flags;
764 int change;
765 unsigned int idx;
766 unsigned short val1, val2, vol;
767 gus_pcm_private_t *pcmp;
768 snd_gus_voice_t *pvoice;
769
770 val1 = ucontrol->value.integer.value[0] & 127;
771 val2 = ucontrol->value.integer.value[1] & 127;
772 spin_lock_irqsave(&gus->pcm_volume_level_lock, flags);
773 change = val1 != gus->gf1.pcm_volume_level_left1 ||
774 val2 != gus->gf1.pcm_volume_level_right1;
775 gus->gf1.pcm_volume_level_left1 = val1;
776 gus->gf1.pcm_volume_level_right1 = val2;
777 gus->gf1.pcm_volume_level_left = snd_gf1_lvol_to_gvol_raw(val1 << 9) << 4;
778 gus->gf1.pcm_volume_level_right = snd_gf1_lvol_to_gvol_raw(val2 << 9) << 4;
779 spin_unlock_irqrestore(&gus->pcm_volume_level_lock, flags);
780 /* are we active? */
781 spin_lock_irqsave(&gus->voice_alloc, flags);
782 for (idx = 0; idx < 32; idx++) {
783 pvoice = &gus->gf1.voices[idx];
784 if (!pvoice->pcm)
785 continue;
786 pcmp = pvoice->private_data;
787 if (!(pcmp->flags & SNDRV_GF1_PCM_PFLG_ACTIVE))
788 continue;
789 /* load real volume - better precision */
790 spin_lock_irqsave(&gus->reg_lock, flags);
791 snd_gf1_select_voice(gus, pvoice->number);
792 snd_gf1_ctrl_stop(gus, SNDRV_GF1_VB_VOLUME_CONTROL);
793 vol = pvoice == pcmp->pvoices[0] ? gus->gf1.pcm_volume_level_left : gus->gf1.pcm_volume_level_right;
794 snd_gf1_write16(gus, SNDRV_GF1_VW_VOLUME, vol);
795 pcmp->final_volume = 1;
796 spin_unlock_irqrestore(&gus->reg_lock, flags);
797 }
798 spin_unlock_irqrestore(&gus->voice_alloc, flags);
799 return change;
800}
801
802static snd_kcontrol_new_t snd_gf1_pcm_volume_control =
803{
804 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
805 .name = "PCM Playback Volume",
806 .info = snd_gf1_pcm_volume_info,
807 .get = snd_gf1_pcm_volume_get,
808 .put = snd_gf1_pcm_volume_put
809};
810
811static snd_kcontrol_new_t snd_gf1_pcm_volume_control1 =
812{
813 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
814 .name = "GPCM Playback Volume",
815 .info = snd_gf1_pcm_volume_info,
816 .get = snd_gf1_pcm_volume_get,
817 .put = snd_gf1_pcm_volume_put
818};
819
820static snd_pcm_ops_t snd_gf1_pcm_playback_ops = {
821 .open = snd_gf1_pcm_playback_open,
822 .close = snd_gf1_pcm_playback_close,
823 .ioctl = snd_pcm_lib_ioctl,
824 .hw_params = snd_gf1_pcm_playback_hw_params,
825 .hw_free = snd_gf1_pcm_playback_hw_free,
826 .prepare = snd_gf1_pcm_playback_prepare,
827 .trigger = snd_gf1_pcm_playback_trigger,
828 .pointer = snd_gf1_pcm_playback_pointer,
829 .copy = snd_gf1_pcm_playback_copy,
830 .silence = snd_gf1_pcm_playback_silence,
831};
832
833static snd_pcm_ops_t snd_gf1_pcm_capture_ops = {
834 .open = snd_gf1_pcm_capture_open,
835 .close = snd_gf1_pcm_capture_close,
836 .ioctl = snd_pcm_lib_ioctl,
837 .hw_params = snd_gf1_pcm_capture_hw_params,
838 .hw_free = snd_gf1_pcm_capture_hw_free,
839 .prepare = snd_gf1_pcm_capture_prepare,
840 .trigger = snd_gf1_pcm_capture_trigger,
841 .pointer = snd_gf1_pcm_capture_pointer,
842};
843
844int snd_gf1_pcm_new(snd_gus_card_t * gus, int pcm_dev, int control_index, snd_pcm_t ** rpcm)
845{
846 snd_card_t *card;
847 snd_kcontrol_t *kctl;
848 snd_pcm_t *pcm;
849 snd_pcm_substream_t *substream;
850 int capture, err;
851
852 if (rpcm)
853 *rpcm = NULL;
854 card = gus->card;
855 capture = !gus->interwave && !gus->ess_flag && !gus->ace_flag ? 1 : 0;
856 err = snd_pcm_new(card,
857 gus->interwave ? "AMD InterWave" : "GF1",
858 pcm_dev,
859 gus->gf1.pcm_channels / 2,
860 capture,
861 &pcm);
862 if (err < 0)
863 return err;
864 pcm->private_data = gus;
865 pcm->private_free = snd_gf1_pcm_free;
866 /* playback setup */
867 snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_gf1_pcm_playback_ops);
868
869 for (substream = pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream; substream; substream = substream->next)
870 snd_pcm_lib_preallocate_pages(substream, SNDRV_DMA_TYPE_DEV,
871 snd_dma_isa_data(),
872 64*1024, gus->gf1.dma1 > 3 ? 128*1024 : 64*1024);
873
874 pcm->info_flags = 0;
875 pcm->dev_subclass = SNDRV_PCM_SUBCLASS_GENERIC_MIX;
876 if (capture) {
877 snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_gf1_pcm_capture_ops);
878 if (gus->gf1.dma2 == gus->gf1.dma1)
879 pcm->info_flags |= SNDRV_PCM_INFO_HALF_DUPLEX;
880 snd_pcm_lib_preallocate_pages(pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream,
881 SNDRV_DMA_TYPE_DEV, snd_dma_isa_data(),
882 64*1024, gus->gf1.dma2 > 3 ? 128*1024 : 64*1024);
883 }
884 strcpy(pcm->name, pcm->id);
885 if (gus->interwave) {
886 sprintf(pcm->name + strlen(pcm->name), " rev %c", gus->revision + 'A');
887 }
888 strcat(pcm->name, " (synth)");
889 gus->pcm = pcm;
890
891 if (gus->codec_flag)
892 kctl = snd_ctl_new1(&snd_gf1_pcm_volume_control1, gus);
893 else
894 kctl = snd_ctl_new1(&snd_gf1_pcm_volume_control, gus);
895 if ((err = snd_ctl_add(card, kctl)) < 0)
896 return err;
897 kctl->id.index = control_index;
898
899 if (rpcm)
900 *rpcm = pcm;
901 return 0;
902}
903
diff --git a/sound/isa/gus/gus_reset.c b/sound/isa/gus/gus_reset.c
new file mode 100644
index 000000000000..b4e66f6a10ae
--- /dev/null
+++ b/sound/isa/gus/gus_reset.c
@@ -0,0 +1,413 @@
1/*
2 * Copyright (c) by Jaroslav Kysela <perex@suse.cz>
3 *
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 *
19 */
20
21#include <sound/driver.h>
22#include <linux/delay.h>
23#include <linux/interrupt.h>
24#include <linux/time.h>
25#include <sound/core.h>
26#include <sound/gus.h>
27
28extern void snd_gf1_timers_init(snd_gus_card_t * gus);
29extern void snd_gf1_timers_done(snd_gus_card_t * gus);
30extern int snd_gf1_synth_init(snd_gus_card_t * gus);
31extern void snd_gf1_synth_done(snd_gus_card_t * gus);
32
33/*
34 * ok.. default interrupt handlers...
35 */
36
37static void snd_gf1_default_interrupt_handler_midi_out(snd_gus_card_t * gus)
38{
39 snd_gf1_uart_cmd(gus, gus->gf1.uart_cmd &= ~0x20);
40}
41
42static void snd_gf1_default_interrupt_handler_midi_in(snd_gus_card_t * gus)
43{
44 snd_gf1_uart_cmd(gus, gus->gf1.uart_cmd &= ~0x80);
45}
46
47static void snd_gf1_default_interrupt_handler_timer1(snd_gus_card_t * gus)
48{
49 snd_gf1_i_write8(gus, SNDRV_GF1_GB_SOUND_BLASTER_CONTROL, gus->gf1.timer_enabled &= ~4);
50}
51
52static void snd_gf1_default_interrupt_handler_timer2(snd_gus_card_t * gus)
53{
54 snd_gf1_i_write8(gus, SNDRV_GF1_GB_SOUND_BLASTER_CONTROL, gus->gf1.timer_enabled &= ~8);
55}
56
57static void snd_gf1_default_interrupt_handler_wave_and_volume(snd_gus_card_t * gus, snd_gus_voice_t * voice)
58{
59 snd_gf1_i_ctrl_stop(gus, 0x00);
60 snd_gf1_i_ctrl_stop(gus, 0x0d);
61}
62
63static void snd_gf1_default_interrupt_handler_dma_write(snd_gus_card_t * gus)
64{
65 snd_gf1_i_write8(gus, 0x41, 0x00);
66}
67
68static void snd_gf1_default_interrupt_handler_dma_read(snd_gus_card_t * gus)
69{
70 snd_gf1_i_write8(gus, 0x49, 0x00);
71}
72
73void snd_gf1_set_default_handlers(snd_gus_card_t * gus, unsigned int what)
74{
75 if (what & SNDRV_GF1_HANDLER_MIDI_OUT)
76 gus->gf1.interrupt_handler_midi_out = snd_gf1_default_interrupt_handler_midi_out;
77 if (what & SNDRV_GF1_HANDLER_MIDI_IN)
78 gus->gf1.interrupt_handler_midi_in = snd_gf1_default_interrupt_handler_midi_in;
79 if (what & SNDRV_GF1_HANDLER_TIMER1)
80 gus->gf1.interrupt_handler_timer1 = snd_gf1_default_interrupt_handler_timer1;
81 if (what & SNDRV_GF1_HANDLER_TIMER2)
82 gus->gf1.interrupt_handler_timer2 = snd_gf1_default_interrupt_handler_timer2;
83 if (what & SNDRV_GF1_HANDLER_VOICE) {
84 snd_gus_voice_t *voice;
85
86 voice = &gus->gf1.voices[what & 0xffff];
87 voice->handler_wave =
88 voice->handler_volume = snd_gf1_default_interrupt_handler_wave_and_volume;
89 voice->handler_effect = NULL;
90 voice->volume_change = NULL;
91 }
92 if (what & SNDRV_GF1_HANDLER_DMA_WRITE)
93 gus->gf1.interrupt_handler_dma_write = snd_gf1_default_interrupt_handler_dma_write;
94 if (what & SNDRV_GF1_HANDLER_DMA_READ)
95 gus->gf1.interrupt_handler_dma_read = snd_gf1_default_interrupt_handler_dma_read;
96}
97
98/*
99
100 */
101
102static void snd_gf1_clear_regs(snd_gus_card_t * gus)
103{
104 unsigned long flags;
105
106 spin_lock_irqsave(&gus->reg_lock, flags);
107 inb(GUSP(gus, IRQSTAT));
108 snd_gf1_write8(gus, 0x41, 0); /* DRAM DMA Control Register */
109 snd_gf1_write8(gus, 0x45, 0); /* Timer Control */
110 snd_gf1_write8(gus, 0x49, 0); /* Sampling Control Register */
111 spin_unlock_irqrestore(&gus->reg_lock, flags);
112}
113
114static void snd_gf1_look_regs(snd_gus_card_t * gus)
115{
116 unsigned long flags;
117
118 spin_lock_irqsave(&gus->reg_lock, flags);
119 snd_gf1_look8(gus, 0x41); /* DRAM DMA Control Register */
120 snd_gf1_look8(gus, 0x49); /* Sampling Control Register */
121 inb(GUSP(gus, IRQSTAT));
122 snd_gf1_read8(gus, 0x0f); /* IRQ Source Register */
123 spin_unlock_irqrestore(&gus->reg_lock, flags);
124}
125
126/*
127 * put selected GF1 voices to initial stage...
128 */
129
130void snd_gf1_smart_stop_voice(snd_gus_card_t * gus, unsigned short voice)
131{
132 unsigned long flags;
133
134 spin_lock_irqsave(&gus->reg_lock, flags);
135 snd_gf1_select_voice(gus, voice);
136#if 0
137 printk(" -%i- smart stop voice - volume = 0x%x\n", voice, snd_gf1_i_read16(gus, SNDRV_GF1_VW_VOLUME));
138#endif
139 snd_gf1_ctrl_stop(gus, SNDRV_GF1_VB_ADDRESS_CONTROL);
140 snd_gf1_ctrl_stop(gus, SNDRV_GF1_VB_VOLUME_CONTROL);
141 spin_unlock_irqrestore(&gus->reg_lock, flags);
142}
143
144void snd_gf1_stop_voice(snd_gus_card_t * gus, unsigned short voice)
145{
146 unsigned long flags;
147
148 spin_lock_irqsave(&gus->reg_lock, flags);
149 snd_gf1_select_voice(gus, voice);
150#if 0
151 printk(" -%i- stop voice - volume = 0x%x\n", voice, snd_gf1_i_read16(gus, SNDRV_GF1_VW_VOLUME));
152#endif
153 snd_gf1_ctrl_stop(gus, SNDRV_GF1_VB_ADDRESS_CONTROL);
154 snd_gf1_ctrl_stop(gus, SNDRV_GF1_VB_VOLUME_CONTROL);
155 if (gus->gf1.enh_mode)
156 snd_gf1_write8(gus, SNDRV_GF1_VB_ACCUMULATOR, 0);
157 spin_unlock_irqrestore(&gus->reg_lock, flags);
158#if 0
159 snd_gf1_lfo_shutdown(gus, voice, ULTRA_LFO_VIBRATO);
160 snd_gf1_lfo_shutdown(gus, voice, ULTRA_LFO_TREMOLO);
161#endif
162}
163
164void snd_gf1_clear_voices(snd_gus_card_t * gus, unsigned short v_min, unsigned short v_max)
165{
166 unsigned long flags;
167 unsigned int daddr;
168 unsigned short i, w_16;
169
170 daddr = gus->gf1.default_voice_address << 4;
171 for (i = v_min; i <= v_max; i++) {
172#if 0
173 if (gus->gf1.syn_voices)
174 gus->gf1.syn_voices[i].flags = ~VFLG_DYNAMIC;
175#endif
176 spin_lock_irqsave(&gus->reg_lock, flags);
177 snd_gf1_select_voice(gus, i);
178 snd_gf1_ctrl_stop(gus, SNDRV_GF1_VB_ADDRESS_CONTROL); /* Voice Control Register = voice stop */
179 snd_gf1_ctrl_stop(gus, SNDRV_GF1_VB_VOLUME_CONTROL); /* Volume Ramp Control Register = ramp off */
180 if (gus->gf1.enh_mode)
181 snd_gf1_write8(gus, SNDRV_GF1_VB_MODE, gus->gf1.memory ? 0x02 : 0x82); /* Deactivate voice */
182 w_16 = snd_gf1_read8(gus, SNDRV_GF1_VB_ADDRESS_CONTROL) & 0x04;
183 snd_gf1_write16(gus, SNDRV_GF1_VW_FREQUENCY, 0x400);
184 snd_gf1_write_addr(gus, SNDRV_GF1_VA_START, daddr, w_16);
185 snd_gf1_write_addr(gus, SNDRV_GF1_VA_END, daddr, w_16);
186 snd_gf1_write8(gus, SNDRV_GF1_VB_VOLUME_START, 0);
187 snd_gf1_write8(gus, SNDRV_GF1_VB_VOLUME_END, 0);
188 snd_gf1_write8(gus, SNDRV_GF1_VB_VOLUME_RATE, 0);
189 snd_gf1_write16(gus, SNDRV_GF1_VW_VOLUME, 0);
190 snd_gf1_write_addr(gus, SNDRV_GF1_VA_CURRENT, daddr, w_16);
191 snd_gf1_write8(gus, SNDRV_GF1_VB_PAN, 7);
192 if (gus->gf1.enh_mode) {
193 snd_gf1_write8(gus, SNDRV_GF1_VB_ACCUMULATOR, 0);
194 snd_gf1_write16(gus, SNDRV_GF1_VW_EFFECT_VOLUME, 0);
195 snd_gf1_write16(gus, SNDRV_GF1_VW_EFFECT_VOLUME_FINAL, 0);
196 }
197 spin_unlock_irqrestore(&gus->reg_lock, flags);
198#if 0
199 snd_gf1_lfo_shutdown(gus, i, ULTRA_LFO_VIBRATO);
200 snd_gf1_lfo_shutdown(gus, i, ULTRA_LFO_TREMOLO);
201#endif
202 }
203}
204
205void snd_gf1_stop_voices(snd_gus_card_t * gus, unsigned short v_min, unsigned short v_max)
206{
207 unsigned long flags;
208 short i, ramp_ok;
209 unsigned short ramp_end;
210
211 if (!in_interrupt()) { /* this can't be done in interrupt */
212 for (i = v_min, ramp_ok = 0; i <= v_max; i++) {
213 spin_lock_irqsave(&gus->reg_lock, flags);
214 snd_gf1_select_voice(gus, i);
215 ramp_end = snd_gf1_read16(gus, 9) >> 8;
216 if (ramp_end > SNDRV_GF1_MIN_OFFSET) {
217 ramp_ok++;
218 snd_gf1_write8(gus, SNDRV_GF1_VB_VOLUME_RATE, 20); /* ramp rate */
219 snd_gf1_write8(gus, SNDRV_GF1_VB_VOLUME_START, SNDRV_GF1_MIN_OFFSET); /* ramp start */
220 snd_gf1_write8(gus, SNDRV_GF1_VB_VOLUME_END, ramp_end); /* ramp end */
221 snd_gf1_write8(gus, SNDRV_GF1_VB_VOLUME_CONTROL, 0x40); /* ramp down */
222 if (gus->gf1.enh_mode) {
223 snd_gf1_delay(gus);
224 snd_gf1_write8(gus, SNDRV_GF1_VB_VOLUME_CONTROL, 0x40);
225 }
226 }
227 spin_unlock_irqrestore(&gus->reg_lock, flags);
228 }
229 msleep_interruptible(50);
230 }
231 snd_gf1_clear_voices(gus, v_min, v_max);
232}
233
234static void snd_gf1_alloc_voice_use(snd_gus_card_t * gus,
235 snd_gus_voice_t * pvoice,
236 int type, int client, int port)
237{
238 pvoice->use = 1;
239 switch (type) {
240 case SNDRV_GF1_VOICE_TYPE_PCM:
241 gus->gf1.pcm_alloc_voices++;
242 pvoice->pcm = 1;
243 break;
244 case SNDRV_GF1_VOICE_TYPE_SYNTH:
245 pvoice->synth = 1;
246 pvoice->client = client;
247 pvoice->port = port;
248 break;
249 case SNDRV_GF1_VOICE_TYPE_MIDI:
250 pvoice->midi = 1;
251 pvoice->client = client;
252 pvoice->port = port;
253 break;
254 }
255}
256
257snd_gus_voice_t *snd_gf1_alloc_voice(snd_gus_card_t * gus, int type, int client, int port)
258{
259 snd_gus_voice_t *pvoice;
260 unsigned long flags;
261 int idx;
262
263 spin_lock_irqsave(&gus->voice_alloc, flags);
264 if (type == SNDRV_GF1_VOICE_TYPE_PCM) {
265 if (gus->gf1.pcm_alloc_voices >= gus->gf1.pcm_channels) {
266 spin_unlock_irqrestore(&gus->voice_alloc, flags);
267 return NULL;
268 }
269 }
270 for (idx = 0; idx < 32; idx++) {
271 pvoice = &gus->gf1.voices[idx];
272 if (!pvoice->use) {
273 snd_gf1_alloc_voice_use(gus, pvoice, type, client, port);
274 spin_unlock_irqrestore(&gus->voice_alloc, flags);
275 return pvoice;
276 }
277 }
278 for (idx = 0; idx < 32; idx++) {
279 pvoice = &gus->gf1.voices[idx];
280 if (pvoice->midi && !pvoice->client) {
281 snd_gf1_clear_voices(gus, pvoice->number, pvoice->number);
282 snd_gf1_alloc_voice_use(gus, pvoice, type, client, port);
283 spin_unlock_irqrestore(&gus->voice_alloc, flags);
284 return pvoice;
285 }
286 }
287 spin_unlock_irqrestore(&gus->voice_alloc, flags);
288 return NULL;
289}
290
291void snd_gf1_free_voice(snd_gus_card_t * gus, snd_gus_voice_t *voice)
292{
293 unsigned long flags;
294 void (*private_free)(snd_gus_voice_t *voice);
295 void *private_data;
296
297 if (voice == NULL || !voice->use)
298 return;
299 snd_gf1_set_default_handlers(gus, SNDRV_GF1_HANDLER_VOICE | voice->number);
300 snd_gf1_clear_voices(gus, voice->number, voice->number);
301 spin_lock_irqsave(&gus->voice_alloc, flags);
302 private_free = voice->private_free;
303 private_data = voice->private_data;
304 voice->private_free = NULL;
305 voice->private_data = NULL;
306 if (voice->pcm)
307 gus->gf1.pcm_alloc_voices--;
308 voice->use = voice->pcm = 0;
309 voice->sample_ops = NULL;
310 spin_unlock_irqrestore(&gus->voice_alloc, flags);
311 if (private_free)
312 private_free(voice);
313}
314
315/*
316 * call this function only by start of driver
317 */
318
319int snd_gf1_start(snd_gus_card_t * gus)
320{
321 unsigned long flags;
322 unsigned int i;
323
324 snd_gf1_i_write8(gus, SNDRV_GF1_GB_RESET, 0); /* reset GF1 */
325 udelay(160);
326 snd_gf1_i_write8(gus, SNDRV_GF1_GB_RESET, 1); /* disable IRQ & DAC */
327 udelay(160);
328 snd_gf1_i_write8(gus, SNDRV_GF1_GB_JOYSTICK_DAC_LEVEL, gus->joystick_dac);
329
330 snd_gf1_set_default_handlers(gus, SNDRV_GF1_HANDLER_ALL);
331 for (i = 0; i < 32; i++) {
332 gus->gf1.voices[i].number = i;
333 snd_gf1_set_default_handlers(gus, SNDRV_GF1_HANDLER_VOICE | i);
334 }
335
336 snd_gf1_uart_cmd(gus, 0x03); /* huh.. this cleanup took me some time... */
337
338 if (gus->gf1.enh_mode) { /* enhanced mode !!!! */
339 snd_gf1_i_write8(gus, SNDRV_GF1_GB_GLOBAL_MODE, snd_gf1_i_look8(gus, SNDRV_GF1_GB_GLOBAL_MODE) | 0x01);
340 snd_gf1_i_write8(gus, SNDRV_GF1_GB_MEMORY_CONTROL, 0x01);
341 }
342 snd_gf1_clear_regs(gus);
343 snd_gf1_select_active_voices(gus);
344 snd_gf1_delay(gus);
345 gus->gf1.default_voice_address = gus->gf1.memory > 0 ? 0 : 512 - 8;
346 /* initialize LFOs & clear LFOs memory */
347 if (gus->gf1.enh_mode && gus->gf1.memory) {
348 gus->gf1.hw_lfo = 1;
349 gus->gf1.default_voice_address += 1024;
350 } else {
351 gus->gf1.sw_lfo = 1;
352 }
353#if 0
354 snd_gf1_lfo_init(gus);
355#endif
356 if (gus->gf1.memory > 0)
357 for (i = 0; i < 4; i++)
358 snd_gf1_poke(gus, gus->gf1.default_voice_address + i, 0);
359 snd_gf1_clear_regs(gus);
360 snd_gf1_clear_voices(gus, 0, 31);
361 snd_gf1_look_regs(gus);
362 udelay(160);
363 snd_gf1_i_write8(gus, SNDRV_GF1_GB_RESET, 7); /* Reset Register = IRQ enable, DAC enable */
364 udelay(160);
365 snd_gf1_i_write8(gus, SNDRV_GF1_GB_RESET, 7); /* Reset Register = IRQ enable, DAC enable */
366 if (gus->gf1.enh_mode) { /* enhanced mode !!!! */
367 snd_gf1_i_write8(gus, SNDRV_GF1_GB_GLOBAL_MODE, snd_gf1_i_look8(gus, SNDRV_GF1_GB_GLOBAL_MODE) | 0x01);
368 snd_gf1_i_write8(gus, SNDRV_GF1_GB_MEMORY_CONTROL, 0x01);
369 }
370 while ((snd_gf1_i_read8(gus, SNDRV_GF1_GB_VOICES_IRQ) & 0xc0) != 0xc0);
371
372 spin_lock_irqsave(&gus->reg_lock, flags);
373 outb(gus->gf1.active_voice = 0, GUSP(gus, GF1PAGE));
374 outb(gus->mix_cntrl_reg, GUSP(gus, MIXCNTRLREG));
375 spin_unlock_irqrestore(&gus->reg_lock, flags);
376
377 snd_gf1_timers_init(gus);
378 snd_gf1_look_regs(gus);
379 snd_gf1_mem_init(gus);
380 snd_gf1_mem_proc_init(gus);
381#ifdef CONFIG_SND_DEBUG
382 snd_gus_irq_profile_init(gus);
383#endif
384
385#if 0
386 if (gus->pnp_flag) {
387 if (gus->chip.playback_fifo_size > 0)
388 snd_gf1_i_write16(gus, SNDRV_GF1_GW_FIFO_RECORD_BASE_ADDR, gus->chip.playback_fifo_block->ptr >> 8);
389 if (gus->chip.record_fifo_size > 0)
390 snd_gf1_i_write16(gus, SNDRV_GF1_GW_FIFO_PLAY_BASE_ADDR, gus->chip.record_fifo_block->ptr >> 8);
391 snd_gf1_i_write16(gus, SNDRV_GF1_GW_FIFO_SIZE, gus->chip.interwave_fifo_reg);
392 }
393#endif
394
395 return 0;
396}
397
398/*
399 * call this function only by shutdown of driver
400 */
401
402int snd_gf1_stop(snd_gus_card_t * gus)
403{
404 snd_gf1_i_write8(gus, SNDRV_GF1_GB_SOUND_BLASTER_CONTROL, 0); /* stop all timers */
405 snd_gf1_stop_voices(gus, 0, 31); /* stop all voices */
406 snd_gf1_i_write8(gus, SNDRV_GF1_GB_RESET, 1); /* disable IRQ & DAC */
407 snd_gf1_timers_done(gus);
408 snd_gf1_mem_done(gus);
409#if 0
410 snd_gf1_lfo_done(gus);
411#endif
412 return 0;
413}
diff --git a/sound/isa/gus/gus_sample.c b/sound/isa/gus/gus_sample.c
new file mode 100644
index 000000000000..4290e03acd51
--- /dev/null
+++ b/sound/isa/gus/gus_sample.c
@@ -0,0 +1,155 @@
1/*
2 * Routines for Gravis UltraSound soundcards - Sample support
3 * Copyright (c) by Jaroslav Kysela <perex@suse.cz>
4 *
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 *
20 */
21
22#include <sound/driver.h>
23#include <linux/time.h>
24#include <sound/core.h>
25#include <sound/gus.h>
26
27/*
28 *
29 */
30
31static void select_instrument(snd_gus_card_t * gus, snd_gus_voice_t * v)
32{
33 snd_seq_kinstr_t *instr;
34
35#if 0
36 printk("select instrument: cluster = %li, std = 0x%x, bank = %i, prg = %i\n",
37 v->instr.cluster,
38 v->instr.std,
39 v->instr.bank,
40 v->instr.prg);
41#endif
42 instr = snd_seq_instr_find(gus->gf1.ilist, &v->instr, 0, 1);
43 if (instr != NULL) {
44 if (instr->ops) {
45 if (!strcmp(instr->ops->instr_type, SNDRV_SEQ_INSTR_ID_SIMPLE))
46 snd_gf1_simple_init(v);
47 }
48 snd_seq_instr_free_use(gus->gf1.ilist, instr);
49 }
50}
51
52/*
53 *
54 */
55
56static void event_sample(snd_seq_event_t *ev, snd_gus_port_t *p, snd_gus_voice_t *v)
57{
58 if (v->sample_ops && v->sample_ops->sample_stop)
59 v->sample_ops->sample_stop(p->gus, v, SAMPLE_STOP_IMMEDIATELY);
60 v->instr.std = ev->data.sample.param.sample.std;
61 if (v->instr.std & 0xff000000) { /* private instrument */
62 v->instr.std &= 0x00ffffff;
63 v->instr.std |= (unsigned int)ev->source.client << 24;
64 }
65 v->instr.bank = ev->data.sample.param.sample.bank;
66 v->instr.prg = ev->data.sample.param.sample.prg;
67 select_instrument(p->gus, v);
68}
69
70static void event_cluster(snd_seq_event_t *ev, snd_gus_port_t *p, snd_gus_voice_t *v)
71{
72 if (v->sample_ops && v->sample_ops->sample_stop)
73 v->sample_ops->sample_stop(p->gus, v, SAMPLE_STOP_IMMEDIATELY);
74 v->instr.cluster = ev->data.sample.param.cluster.cluster;
75 select_instrument(p->gus, v);
76}
77
78static void event_start(snd_seq_event_t *ev, snd_gus_port_t *p, snd_gus_voice_t *v)
79{
80 if (v->sample_ops && v->sample_ops->sample_start)
81 v->sample_ops->sample_start(p->gus, v, ev->data.sample.param.position);
82}
83
84static void event_stop(snd_seq_event_t *ev, snd_gus_port_t *p, snd_gus_voice_t *v)
85{
86 if (v->sample_ops && v->sample_ops->sample_stop)
87 v->sample_ops->sample_stop(p->gus, v, ev->data.sample.param.stop_mode);
88}
89
90static void event_freq(snd_seq_event_t *ev, snd_gus_port_t *p, snd_gus_voice_t *v)
91{
92 if (v->sample_ops && v->sample_ops->sample_freq)
93 v->sample_ops->sample_freq(p->gus, v, ev->data.sample.param.frequency);
94}
95
96static void event_volume(snd_seq_event_t *ev, snd_gus_port_t *p, snd_gus_voice_t *v)
97{
98 if (v->sample_ops && v->sample_ops->sample_volume)
99 v->sample_ops->sample_volume(p->gus, v, &ev->data.sample.param.volume);
100}
101
102static void event_loop(snd_seq_event_t *ev, snd_gus_port_t *p, snd_gus_voice_t *v)
103{
104 if (v->sample_ops && v->sample_ops->sample_loop)
105 v->sample_ops->sample_loop(p->gus, v, &ev->data.sample.param.loop);
106}
107
108static void event_position(snd_seq_event_t *ev, snd_gus_port_t *p, snd_gus_voice_t *v)
109{
110 if (v->sample_ops && v->sample_ops->sample_pos)
111 v->sample_ops->sample_pos(p->gus, v, ev->data.sample.param.position);
112}
113
114static void event_private1(snd_seq_event_t *ev, snd_gus_port_t *p, snd_gus_voice_t *v)
115{
116 if (v->sample_ops && v->sample_ops->sample_private1)
117 v->sample_ops->sample_private1(p->gus, v, (unsigned char *)&ev->data.sample.param.raw8);
118}
119
120typedef void (gus_sample_event_handler_t)(snd_seq_event_t *ev, snd_gus_port_t *p, snd_gus_voice_t *v);
121
122static gus_sample_event_handler_t *gus_sample_event_handlers[9] = {
123 event_sample,
124 event_cluster,
125 event_start,
126 event_stop,
127 event_freq,
128 event_volume,
129 event_loop,
130 event_position,
131 event_private1
132};
133
134void snd_gus_sample_event(snd_seq_event_t *ev, snd_gus_port_t *p)
135{
136 int idx, voice;
137 snd_gus_card_t *gus = p->gus;
138 snd_gus_voice_t *v;
139 unsigned long flags;
140
141 idx = ev->type - SNDRV_SEQ_EVENT_SAMPLE;
142 if (idx < 0 || idx > 8)
143 return;
144 for (voice = 0; voice < 32; voice++) {
145 v = &gus->gf1.voices[voice];
146 if (v->use && v->client == ev->source.client &&
147 v->port == ev->source.port &&
148 v->index == ev->data.sample.channel) {
149 spin_lock_irqsave(&gus->event_lock, flags);
150 gus_sample_event_handlers[idx](ev, p, v);
151 spin_unlock_irqrestore(&gus->event_lock, flags);
152 return;
153 }
154 }
155}
diff --git a/sound/isa/gus/gus_simple.c b/sound/isa/gus/gus_simple.c
new file mode 100644
index 000000000000..c122e7be6ceb
--- /dev/null
+++ b/sound/isa/gus/gus_simple.c
@@ -0,0 +1,634 @@
1/*
2 * Routines for Gravis UltraSound soundcards - Simple instrument handlers
3 * Copyright (c) by Jaroslav Kysela <perex@suse.cz>
4 *
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 *
20 */
21
22#include <sound/driver.h>
23#include <linux/time.h>
24#include <sound/core.h>
25#include <sound/gus.h>
26#include "gus_tables.h"
27
28/*
29 *
30 */
31
32static void interrupt_wave(snd_gus_card_t *gus, snd_gus_voice_t *voice);
33static void interrupt_volume(snd_gus_card_t *gus, snd_gus_voice_t *voice);
34static void interrupt_effect(snd_gus_card_t *gus, snd_gus_voice_t *voice);
35
36static void sample_start(snd_gus_card_t *gus, snd_gus_voice_t *voice, snd_seq_position_t position);
37static void sample_stop(snd_gus_card_t *gus, snd_gus_voice_t *voice, snd_seq_stop_mode_t mode);
38static void sample_freq(snd_gus_card_t *gus, snd_gus_voice_t *voice, snd_seq_frequency_t freq);
39static void sample_volume(snd_gus_card_t *card, snd_gus_voice_t *voice, snd_seq_ev_volume_t *volume);
40static void sample_loop(snd_gus_card_t *card, snd_gus_voice_t *voice, snd_seq_ev_loop_t *loop);
41static void sample_pos(snd_gus_card_t *card, snd_gus_voice_t *voice, snd_seq_position_t position);
42static void sample_private1(snd_gus_card_t *card, snd_gus_voice_t *voice, unsigned char *data);
43
44static snd_gus_sample_ops_t sample_ops = {
45 sample_start,
46 sample_stop,
47 sample_freq,
48 sample_volume,
49 sample_loop,
50 sample_pos,
51 sample_private1
52};
53
54#if 0
55
56static void note_stop(snd_gus_card_t *gus, snd_gus_voice_t *voice, int wait);
57static void note_wait(snd_gus_card_t *gus, snd_gus_voice_t *voice);
58static void note_off(snd_gus_card_t *gus, snd_gus_voice_t *voice);
59static void note_volume(snd_gus_card_t *card, snd_gus_voice_t *voice);
60static void note_pitchbend(snd_gus_card_t *card, snd_gus_voice_t *voice);
61static void note_vibrato(snd_gus_card_t *card, snd_gus_voice_t *voice);
62static void note_tremolo(snd_gus_card_t *card, snd_gus_voice_t *voice);
63
64static struct snd_gus_note_handlers note_commands = {
65 note_stop,
66 note_wait,
67 note_off,
68 note_volume,
69 note_pitchbend,
70 note_vibrato,
71 note_tremolo
72};
73
74static void chn_trigger_down(snd_gus_card_t *card, ultra_channel_t *channel, ultra_instrument_t *instrument, unsigned char note, unsigned char velocity, unsigned char priority );
75static void chn_trigger_up( ultra_card_t *card, ultra_note_t *note );
76static void chn_control( ultra_card_t *card, ultra_channel_t *channel, unsigned short p1, unsigned short p2 );
77
78static struct ULTRA_STRU_INSTRUMENT_CHANNEL_COMMANDS channel_commands = {
79 chn_trigger_down,
80 chn_trigger_up,
81 chn_control
82};
83
84#endif
85
86static void do_volume_envelope(snd_gus_card_t *card, snd_gus_voice_t *voice);
87static void do_pan_envelope(snd_gus_card_t *card, snd_gus_voice_t *voice);
88
89/*
90 *
91 */
92
93static void interrupt_wave(snd_gus_card_t *gus, snd_gus_voice_t *voice)
94{
95 spin_lock(&gus->event_lock);
96 snd_gf1_stop_voice(gus, voice->number);
97 spin_lock(&gus->reg_lock);
98 snd_gf1_select_voice(gus, voice->number);
99 snd_gf1_write16(gus, SNDRV_GF1_VW_VOLUME, 0);
100 spin_unlock(&gus->reg_lock);
101 voice->flags &= ~SNDRV_GF1_VFLG_RUNNING;
102 spin_unlock(&gus->event_lock);
103}
104
105static void interrupt_volume(snd_gus_card_t *gus, snd_gus_voice_t *voice)
106{
107 spin_lock(&gus->event_lock);
108 if (voice->flags & SNDRV_GF1_VFLG_RUNNING)
109 do_volume_envelope(gus, voice);
110 else
111 snd_gf1_stop_voice(gus, voice->number);
112 spin_unlock(&gus->event_lock);
113}
114
115static void interrupt_effect(snd_gus_card_t *gus, snd_gus_voice_t *voice)
116{
117 spin_lock(&gus->event_lock);
118 if ((voice->flags & (SNDRV_GF1_VFLG_RUNNING|SNDRV_GF1_VFLG_EFFECT_TIMER1)) ==
119 (SNDRV_GF1_VFLG_RUNNING|SNDRV_GF1_VFLG_EFFECT_TIMER1))
120 do_pan_envelope(gus, voice);
121 spin_unlock(&gus->event_lock);
122}
123
124/*
125 *
126 */
127
128static void do_volume_envelope(snd_gus_card_t *gus, snd_gus_voice_t *voice)
129{
130 unsigned short next, rate, old_volume;
131 int program_next_ramp;
132 unsigned long flags;
133
134 if (!gus->gf1.volume_ramp) {
135 spin_lock_irqsave(&gus->reg_lock, flags);
136 snd_gf1_select_voice(gus, voice->number);
137 snd_gf1_ctrl_stop(gus, SNDRV_GF1_VB_VOLUME_CONTROL);
138 snd_gf1_write16(gus, SNDRV_GF1_VW_VOLUME, voice->gf1_volume);
139 printk("gf1_volume = 0x%x\n", voice->gf1_volume);
140 spin_unlock_irqrestore(&gus->reg_lock, flags);
141 return;
142 }
143 program_next_ramp = 0;
144 rate = next = 0;
145 while (1) {
146 program_next_ramp = 0;
147 rate = next = 0;
148 switch (voice->venv_state) {
149 case VENV_BEFORE:
150 voice->venv_state = VENV_ATTACK;
151 voice->venv_value_next = 0;
152 spin_lock_irqsave(&gus->reg_lock, flags);
153 snd_gf1_select_voice(gus, voice->number);
154 snd_gf1_ctrl_stop(gus, SNDRV_GF1_VB_VOLUME_CONTROL);
155 snd_gf1_write16(gus, SNDRV_GF1_VW_VOLUME, SNDRV_GF1_MIN_VOLUME);
156 spin_unlock_irqrestore(&gus->reg_lock, flags);
157 break;
158 case VENV_ATTACK:
159 voice->venv_state = VENV_SUSTAIN;
160 program_next_ramp++;
161 next = 255;
162 rate = gus->gf1.volume_ramp;
163 break;
164 case VENV_SUSTAIN:
165 voice->venv_state = VENV_RELEASE;
166 spin_lock_irqsave(&gus->reg_lock, flags);
167 snd_gf1_select_voice(gus, voice->number);
168 snd_gf1_ctrl_stop(gus, SNDRV_GF1_VB_VOLUME_CONTROL);
169 snd_gf1_write16(gus, SNDRV_GF1_VW_VOLUME, ((int)voice->gf1_volume * (int)voice->venv_value_next) / 255);
170 spin_unlock_irqrestore(&gus->reg_lock, flags);
171 return;
172 case VENV_RELEASE:
173 voice->venv_state = VENV_DONE;
174 program_next_ramp++;
175 next = 0;
176 rate = gus->gf1.volume_ramp;
177 break;
178 case VENV_DONE:
179 snd_gf1_stop_voice(gus, voice->number);
180 voice->flags &= ~SNDRV_GF1_VFLG_RUNNING;
181 return;
182 case VENV_VOLUME:
183 program_next_ramp++;
184 next = voice->venv_value_next;
185 rate = gus->gf1.volume_ramp;
186 voice->venv_state = voice->venv_state_prev;
187 break;
188 }
189 voice->venv_value_next = next;
190 if (!program_next_ramp)
191 continue;
192 spin_lock_irqsave(&gus->reg_lock, flags);
193 snd_gf1_select_voice(gus, voice->number);
194 snd_gf1_ctrl_stop(gus, SNDRV_GF1_VB_VOLUME_CONTROL);
195 old_volume = snd_gf1_read16(gus, SNDRV_GF1_VW_VOLUME) >> 8;
196 if (!rate) {
197 spin_unlock_irqrestore(&gus->reg_lock, flags);
198 continue;
199 }
200 next = (((int)voice->gf1_volume * (int)next) / 255) >> 8;
201 if (old_volume < SNDRV_GF1_MIN_OFFSET)
202 old_volume = SNDRV_GF1_MIN_OFFSET;
203 if (next < SNDRV_GF1_MIN_OFFSET)
204 next = SNDRV_GF1_MIN_OFFSET;
205 if (next > SNDRV_GF1_MAX_OFFSET)
206 next = SNDRV_GF1_MAX_OFFSET;
207 if (old_volume == next) {
208 spin_unlock_irqrestore(&gus->reg_lock, flags);
209 continue;
210 }
211 voice->volume_control &= ~0xc3;
212 voice->volume_control |= 0x20;
213 if (old_volume > next) {
214 snd_gf1_write8(gus, SNDRV_GF1_VB_VOLUME_START, next);
215 snd_gf1_write8(gus, SNDRV_GF1_VB_VOLUME_END, old_volume);
216 voice->volume_control |= 0x40;
217 } else {
218 snd_gf1_write8(gus, SNDRV_GF1_VB_VOLUME_START, old_volume);
219 snd_gf1_write8(gus, SNDRV_GF1_VB_VOLUME_END, next);
220 }
221 snd_gf1_write8(gus, SNDRV_GF1_VB_VOLUME_RATE, rate);
222 snd_gf1_write8(gus, SNDRV_GF1_VB_VOLUME_CONTROL, voice->volume_control);
223 if (!gus->gf1.enh_mode) {
224 snd_gf1_delay(gus);
225 snd_gf1_write8(gus, SNDRV_GF1_VB_VOLUME_CONTROL, voice->volume_control);
226 }
227 spin_unlock_irqrestore(&gus->reg_lock, flags);
228 return;
229 }
230}
231
232static void do_pan_envelope(snd_gus_card_t *gus, snd_gus_voice_t *voice)
233{
234 unsigned long flags;
235 unsigned char old_pan;
236
237#if 0
238 snd_gf1_select_voice(gus, voice->number);
239 printk(" -%i- do_pan_envelope - flags = 0x%x (0x%x -> 0x%x)\n",
240 voice->number,
241 voice->flags,
242 voice->gf1_pan,
243 snd_gf1_i_read8(gus, SNDRV_GF1_VB_PAN) & 0x0f);
244#endif
245 if (gus->gf1.enh_mode) {
246 voice->flags &= ~(SNDRV_GF1_VFLG_EFFECT_TIMER1|SNDRV_GF1_VFLG_PAN);
247 return;
248 }
249 if (!gus->gf1.smooth_pan) {
250 spin_lock_irqsave(&gus->reg_lock, flags);
251 snd_gf1_select_voice(gus, voice->number);
252 snd_gf1_write8(gus, SNDRV_GF1_VB_PAN, voice->gf1_pan);
253 spin_unlock_irqrestore(&gus->reg_lock, flags);
254 return;
255 }
256 if (!(voice->flags & SNDRV_GF1_VFLG_PAN)) /* before */
257 voice->flags |= SNDRV_GF1_VFLG_EFFECT_TIMER1|SNDRV_GF1_VFLG_PAN;
258 spin_lock_irqsave(&gus->reg_lock, flags);
259 snd_gf1_select_voice(gus, voice->number);
260 old_pan = snd_gf1_read8(gus, SNDRV_GF1_VB_PAN) & 0x0f;
261 if (old_pan > voice->gf1_pan )
262 old_pan--;
263 if (old_pan < voice->gf1_pan)
264 old_pan++;
265 snd_gf1_write8(gus, SNDRV_GF1_VB_PAN, old_pan);
266 spin_unlock_irqrestore(&gus->reg_lock, flags);
267 if (old_pan == voice->gf1_pan) /* the goal was reached */
268 voice->flags &= ~(SNDRV_GF1_VFLG_EFFECT_TIMER1|SNDRV_GF1_VFLG_PAN);
269#if 0
270 snd_gf1_select_voice(gus, voice->number);
271 printk(" -%i- (1) do_pan_envelope - flags = 0x%x (0x%x -> 0x%x)\n",
272 voice->number,
273 voice->flags,
274 voice->gf1_pan,
275 snd_gf1_i_read8(gus, GF1_VB_PAN) & 0x0f);
276#endif
277}
278
279static void set_enhanced_pan(snd_gus_card_t *gus, snd_gus_voice_t *voice, unsigned short pan)
280{
281 unsigned long flags;
282 unsigned short vlo, vro;
283
284 vlo = SNDRV_GF1_ATTEN((SNDRV_GF1_ATTEN_TABLE_SIZE-1) - pan);
285 vro = SNDRV_GF1_ATTEN(pan);
286 if (pan != SNDRV_GF1_ATTEN_TABLE_SIZE - 1 && pan != 0) {
287 vlo >>= 1;
288 vro >>= 1;
289 }
290 vlo <<= 4;
291 vro <<= 4;
292#if 0
293 printk("vlo = 0x%x (0x%x), vro = 0x%x (0x%x)\n",
294 vlo, snd_gf1_i_read16(gus, GF1_VW_OFFSET_LEFT),
295 vro, snd_gf1_i_read16(gus, GF1_VW_OFFSET_RIGHT));
296#endif
297 spin_lock_irqsave(&gus->reg_lock, flags);
298 snd_gf1_select_voice(gus, voice->number);
299 snd_gf1_write16(gus, SNDRV_GF1_VW_OFFSET_LEFT_FINAL, vlo);
300 snd_gf1_write16(gus, SNDRV_GF1_VW_OFFSET_RIGHT_FINAL, vro);
301 spin_unlock_irqrestore(&gus->reg_lock, flags);
302 voice->vlo = vlo;
303 voice->vro = vro;
304}
305
306/*
307 *
308 */
309
310static void sample_start(snd_gus_card_t *gus, snd_gus_voice_t *voice, snd_seq_position_t position)
311{
312 unsigned long flags;
313 unsigned int begin, addr, addr_end, addr_start;
314 int w_16;
315 simple_instrument_t *simple;
316 snd_seq_kinstr_t *instr;
317
318 instr = snd_seq_instr_find(gus->gf1.ilist, &voice->instr, 0, 1);
319 if (instr == NULL)
320 return;
321 voice->instr = instr->instr; /* copy ID to speedup aliases */
322 simple = KINSTR_DATA(instr);
323 begin = simple->address.memory << 4;
324 w_16 = simple->format & SIMPLE_WAVE_16BIT ? 0x04 : 0;
325 addr_start = simple->loop_start;
326 if (simple->format & SIMPLE_WAVE_LOOP) {
327 addr_end = simple->loop_end;
328 } else {
329 addr_end = (simple->size << 4) - (w_16 ? 40 : 24);
330 }
331 if (simple->format & SIMPLE_WAVE_BACKWARD) {
332 addr = simple->loop_end;
333 if (position < simple->loop_end)
334 addr -= position;
335 } else {
336 addr = position;
337 }
338 voice->control = 0x00;
339 voice->mode = 0x20; /* enable offset registers */
340 if (simple->format & SIMPLE_WAVE_16BIT)
341 voice->control |= 0x04;
342 if (simple->format & SIMPLE_WAVE_BACKWARD)
343 voice->control |= 0x40;
344 if (simple->format & SIMPLE_WAVE_LOOP) {
345 voice->control |= 0x08;
346 } else {
347 voice->control |= 0x20;
348 }
349 if (simple->format & SIMPLE_WAVE_BIDIR)
350 voice->control |= 0x10;
351 if (simple->format & SIMPLE_WAVE_ULAW)
352 voice->mode |= 0x40;
353 if (w_16) {
354 addr = ((addr << 1) & ~0x1f) | (addr & 0x0f);
355 addr_start = ((addr_start << 1) & ~0x1f) | (addr_start & 0x0f);
356 addr_end = ((addr_end << 1) & ~0x1f) | (addr_end & 0x0f);
357 }
358 addr += begin;
359 addr_start += begin;
360 addr_end += begin;
361 snd_gf1_stop_voice(gus, voice->number);
362 spin_lock_irqsave(&gus->reg_lock, flags);
363 snd_gf1_select_voice(gus, voice->number);
364 snd_gf1_write16(gus, SNDRV_GF1_VW_FREQUENCY, voice->fc_register + voice->fc_lfo);
365 voice->venv_state = VENV_BEFORE;
366 voice->volume_control = 0x03;
367 snd_gf1_write_addr(gus, SNDRV_GF1_VA_START, addr_start, w_16);
368 snd_gf1_write_addr(gus, SNDRV_GF1_VA_END, addr_end, w_16);
369 snd_gf1_write_addr(gus, SNDRV_GF1_VA_CURRENT, addr, w_16);
370 if (!gus->gf1.enh_mode) {
371 snd_gf1_write8(gus, SNDRV_GF1_VB_PAN, voice->gf1_pan);
372 } else {
373 snd_gf1_write16(gus, SNDRV_GF1_VW_OFFSET_LEFT, voice->vlo);
374 snd_gf1_write16(gus, SNDRV_GF1_VW_OFFSET_LEFT_FINAL, voice->vlo);
375 snd_gf1_write16(gus, SNDRV_GF1_VW_OFFSET_RIGHT, voice->vro);
376 snd_gf1_write16(gus, SNDRV_GF1_VW_OFFSET_RIGHT_FINAL, voice->vro);
377 snd_gf1_write8(gus, SNDRV_GF1_VB_ACCUMULATOR, voice->effect_accumulator);
378 snd_gf1_write16(gus, SNDRV_GF1_VW_EFFECT_VOLUME, voice->gf1_effect_volume);
379 snd_gf1_write16(gus, SNDRV_GF1_VW_EFFECT_VOLUME_FINAL, voice->gf1_effect_volume);
380 }
381 spin_unlock_irqrestore(&gus->reg_lock, flags);
382 do_volume_envelope(gus, voice);
383 spin_lock_irqsave(&gus->reg_lock, flags);
384 snd_gf1_select_voice(gus, voice->number);
385 if (gus->gf1.enh_mode)
386 snd_gf1_write8(gus, SNDRV_GF1_VB_MODE, voice->mode);
387 snd_gf1_write8(gus, SNDRV_GF1_VB_ADDRESS_CONTROL, voice->control);
388 if (!gus->gf1.enh_mode) {
389 snd_gf1_delay(gus);
390 snd_gf1_write8(gus, SNDRV_GF1_VB_ADDRESS_CONTROL, voice->control );
391 }
392 spin_unlock_irqrestore(&gus->reg_lock, flags);
393#if 0
394 snd_gf1_print_voice_registers(gus);
395#endif
396 voice->flags |= SNDRV_GF1_VFLG_RUNNING;
397 snd_seq_instr_free_use(gus->gf1.ilist, instr);
398}
399
400static void sample_stop(snd_gus_card_t *gus, snd_gus_voice_t *voice, snd_seq_stop_mode_t mode)
401{
402 unsigned char control;
403 unsigned long flags;
404
405 if (!(voice->flags & SNDRV_GF1_VFLG_RUNNING))
406 return;
407 switch (mode) {
408 default:
409 if (gus->gf1.volume_ramp > 0) {
410 if (voice->venv_state < VENV_RELEASE) {
411 voice->venv_state = VENV_RELEASE;
412 do_volume_envelope(gus, voice);
413 }
414 }
415 if (mode != SAMPLE_STOP_VENVELOPE) {
416 snd_gf1_stop_voice(gus, voice->number);
417 spin_lock_irqsave(&gus->reg_lock, flags);
418 snd_gf1_select_voice(gus, voice->number);
419 snd_gf1_write16(gus, SNDRV_GF1_VW_VOLUME, SNDRV_GF1_MIN_VOLUME);
420 spin_unlock_irqrestore(&gus->reg_lock, flags);
421 voice->flags &= ~SNDRV_GF1_VFLG_RUNNING;
422 }
423 break;
424 case SAMPLE_STOP_LOOP: /* disable loop only */
425 spin_lock_irqsave(&gus->reg_lock, flags);
426 snd_gf1_select_voice(gus, voice->number);
427 control = snd_gf1_read8(gus, SNDRV_GF1_VB_ADDRESS_CONTROL);
428 control &= ~(0x83 | 0x04);
429 control |= 0x20;
430 snd_gf1_write8(gus, SNDRV_GF1_VB_ADDRESS_CONTROL, control);
431 spin_unlock_irqrestore(&gus->reg_lock, flags);
432 break;
433 }
434}
435
436static void sample_freq(snd_gus_card_t *gus, snd_gus_voice_t *voice, snd_seq_frequency_t freq)
437{
438 unsigned long flags;
439
440 spin_lock_irqsave(&gus->reg_lock, flags);
441 voice->fc_register = snd_gf1_translate_freq(gus, freq);
442 snd_gf1_select_voice(gus, voice->number);
443 snd_gf1_write16(gus, SNDRV_GF1_VW_FREQUENCY, voice->fc_register + voice->fc_lfo);
444 spin_unlock_irqrestore(&gus->reg_lock, flags);
445}
446
447static void sample_volume(snd_gus_card_t *gus, snd_gus_voice_t *voice, snd_seq_ev_volume_t *volume)
448{
449 if (volume->volume >= 0) {
450 volume->volume &= 0x3fff;
451 voice->gf1_volume = snd_gf1_lvol_to_gvol_raw(volume->volume << 2) << 4;
452 voice->venv_state_prev = VENV_SUSTAIN;
453 voice->venv_state = VENV_VOLUME;
454 do_volume_envelope(gus, voice);
455 }
456 if (volume->lr >= 0) {
457 volume->lr &= 0x3fff;
458 if (!gus->gf1.enh_mode) {
459 voice->gf1_pan = (volume->lr >> 10) & 15;
460 if (!gus->gf1.full_range_pan) {
461 if (voice->gf1_pan == 0)
462 voice->gf1_pan++;
463 if (voice->gf1_pan == 15)
464 voice->gf1_pan--;
465 }
466 voice->flags &= ~SNDRV_GF1_VFLG_PAN; /* before */
467 do_pan_envelope(gus, voice);
468 } else {
469 set_enhanced_pan(gus, voice, volume->lr >> 7);
470 }
471 }
472}
473
474static void sample_loop(snd_gus_card_t *gus, snd_gus_voice_t *voice, snd_seq_ev_loop_t *loop)
475{
476 unsigned long flags;
477 int w_16 = voice->control & 0x04;
478 unsigned int begin, addr_start, addr_end;
479 simple_instrument_t *simple;
480 snd_seq_kinstr_t *instr;
481
482#if 0
483 printk("voice_loop: start = 0x%x, end = 0x%x\n", loop->start, loop->end);
484#endif
485 instr = snd_seq_instr_find(gus->gf1.ilist, &voice->instr, 0, 1);
486 if (instr == NULL)
487 return;
488 voice->instr = instr->instr; /* copy ID to speedup aliases */
489 simple = KINSTR_DATA(instr);
490 begin = simple->address.memory;
491 addr_start = loop->start;
492 addr_end = loop->end;
493 addr_start = (((addr_start << 1) & ~0x1f) | (addr_start & 0x0f)) + begin;
494 addr_end = (((addr_end << 1) & ~0x1f) | (addr_end & 0x0f)) + begin;
495 spin_lock_irqsave(&gus->reg_lock, flags);
496 snd_gf1_select_voice(gus, voice->number);
497 snd_gf1_write_addr(gus, SNDRV_GF1_VA_START, addr_start, w_16);
498 snd_gf1_write_addr(gus, SNDRV_GF1_VA_END, addr_end, w_16);
499 spin_unlock_irqrestore(&gus->reg_lock, flags);
500 snd_seq_instr_free_use(gus->gf1.ilist, instr);
501}
502
503static void sample_pos(snd_gus_card_t *gus, snd_gus_voice_t *voice, snd_seq_position_t position)
504{
505 unsigned long flags;
506 int w_16 = voice->control & 0x04;
507 unsigned int begin, addr;
508 simple_instrument_t *simple;
509 snd_seq_kinstr_t *instr;
510
511#if 0
512 printk("voice_loop: start = 0x%x, end = 0x%x\n", loop->start, loop->end);
513#endif
514 instr = snd_seq_instr_find(gus->gf1.ilist, &voice->instr, 0, 1);
515 if (instr == NULL)
516 return;
517 voice->instr = instr->instr; /* copy ID to speedup aliases */
518 simple = KINSTR_DATA(instr);
519 begin = simple->address.memory;
520 addr = (((position << 1) & ~0x1f) | (position & 0x0f)) + begin;
521 spin_lock_irqsave(&gus->reg_lock, flags);
522 snd_gf1_select_voice(gus, voice->number);
523 snd_gf1_write_addr(gus, SNDRV_GF1_VA_CURRENT, addr, w_16);
524 spin_unlock_irqrestore(&gus->reg_lock, flags);
525 snd_seq_instr_free_use(gus->gf1.ilist, instr);
526}
527
528#if 0
529
530static unsigned char get_effects_mask( ultra_card_t *card, int value )
531{
532 if ( value > 7 ) return 0;
533 if ( card -> gf1.effects && card -> gf1.effects -> chip_type == ULTRA_EFFECT_CHIP_INTERWAVE )
534 return card -> gf1.effects -> chip.interwave.voice_output[ value ];
535 return 0;
536}
537
538#endif
539
540static void sample_private1(snd_gus_card_t *card, snd_gus_voice_t *voice, unsigned char *data)
541{
542#if 0
543 unsigned long flags;
544 unsigned char uc;
545
546 switch ( *data ) {
547 case ULTRA_PRIV1_IW_EFFECT:
548 uc = get_effects_mask( card, ultra_get_byte( data, 4 ) );
549 uc |= get_effects_mask( card, ultra_get_byte( data, 4 ) >> 4 );
550 uc |= get_effects_mask( card, ultra_get_byte( data, 5 ) );
551 uc |= get_effects_mask( card, ultra_get_byte( data, 5 ) >> 4 );
552 voice -> data.simple.effect_accumulator = uc;
553 voice -> data.simple.effect_volume = ultra_translate_voice_volume( card, ultra_get_word( data, 2 ) ) << 4;
554 if ( !card -> gf1.enh_mode ) return;
555 if ( voice -> flags & VFLG_WAIT_FOR_START ) return;
556 if ( voice -> flags & VFLG_RUNNING )
557 {
558 CLI( &flags );
559 gf1_select_voice( card, voice -> number );
560 ultra_write8( card, GF1_VB_ACCUMULATOR, voice -> data.simple.effect_accumulator );
561 ultra_write16( card, GF1_VW_EFFECT_VOLUME_FINAL, voice -> data.simple.effect_volume );
562 STI( &flags );
563 }
564 break;
565 case ULTRA_PRIV1_IW_LFO:
566 ultra_lfo_command( card, voice -> number, data );
567 }
568#endif
569}
570
571#if 0
572
573/*
574 *
575 */
576
577static void note_stop( ultra_card_t *card, ultra_voice_t *voice, int wait )
578{
579}
580
581static void note_wait( ultra_card_t *card, ultra_voice_t *voice )
582{
583}
584
585static void note_off( ultra_card_t *card, ultra_voice_t *voice )
586{
587}
588
589static void note_volume( ultra_card_t *card, ultra_voice_t *voice )
590{
591}
592
593static void note_pitchbend( ultra_card_t *card, ultra_voice_t *voice )
594{
595}
596
597static void note_vibrato( ultra_card_t *card, ultra_voice_t *voice )
598{
599}
600
601static void note_tremolo( ultra_card_t *card, ultra_voice_t *voice )
602{
603}
604
605/*
606 *
607 */
608
609static void chn_trigger_down( ultra_card_t *card, ultra_channel_t *channel, ultra_instrument_t *instrument, unsigned char note, unsigned char velocity, unsigned char priority )
610{
611}
612
613static void chn_trigger_up( ultra_card_t *card, ultra_note_t *note )
614{
615}
616
617static void chn_control( ultra_card_t *card, ultra_channel_t *channel, unsigned short p1, unsigned short p2 )
618{
619}
620
621/*
622 *
623 */
624
625#endif
626
627void snd_gf1_simple_init(snd_gus_voice_t *voice)
628{
629 voice->handler_wave = interrupt_wave;
630 voice->handler_volume = interrupt_volume;
631 voice->handler_effect = interrupt_effect;
632 voice->volume_change = NULL;
633 voice->sample_ops = &sample_ops;
634}
diff --git a/sound/isa/gus/gus_synth.c b/sound/isa/gus/gus_synth.c
new file mode 100644
index 000000000000..66552e6013a4
--- /dev/null
+++ b/sound/isa/gus/gus_synth.c
@@ -0,0 +1,329 @@
1/*
2 * Routines for Gravis UltraSound soundcards - Synthesizer
3 * Copyright (c) by Jaroslav Kysela <perex@suse.cz>
4 *
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 *
20 */
21
22#include <sound/driver.h>
23#include <linux/init.h>
24#include <linux/time.h>
25#include <sound/core.h>
26#include <sound/gus.h>
27#include <sound/seq_device.h>
28
29MODULE_AUTHOR("Jaroslav Kysela <perex@suse.cz>");
30MODULE_DESCRIPTION("Routines for Gravis UltraSound soundcards - Synthesizer");
31MODULE_LICENSE("GPL");
32
33/*
34 *
35 */
36
37static void snd_gus_synth_free_voices(snd_gus_card_t * gus, int client, int port)
38{
39 int idx;
40 snd_gus_voice_t * voice;
41
42 for (idx = 0; idx < 32; idx++) {
43 voice = &gus->gf1.voices[idx];
44 if (voice->use && voice->client == client && voice->port == port)
45 snd_gf1_free_voice(gus, voice);
46 }
47}
48
49static int snd_gus_synth_use(void *private_data, snd_seq_port_subscribe_t *info)
50{
51 snd_gus_port_t * port = (snd_gus_port_t *)private_data;
52 snd_gus_card_t * gus = port->gus;
53 snd_gus_voice_t * voice;
54 unsigned int idx;
55
56 if (info->voices > 32)
57 return -EINVAL;
58 down(&gus->register_mutex);
59 if (!snd_gus_use_inc(gus)) {
60 up(&gus->register_mutex);
61 return -EFAULT;
62 }
63 for (idx = 0; idx < info->voices; idx++) {
64 voice = snd_gf1_alloc_voice(gus, SNDRV_GF1_VOICE_TYPE_SYNTH, info->sender.client, info->sender.port);
65 if (voice == NULL) {
66 snd_gus_synth_free_voices(gus, info->sender.client, info->sender.port);
67 snd_gus_use_dec(gus);
68 up(&gus->register_mutex);
69 return -EBUSY;
70 }
71 voice->index = idx;
72 }
73 up(&gus->register_mutex);
74 return 0;
75}
76
77static int snd_gus_synth_unuse(void *private_data, snd_seq_port_subscribe_t *info)
78{
79 snd_gus_port_t * port = (snd_gus_port_t *)private_data;
80 snd_gus_card_t * gus = port->gus;
81
82 down(&gus->register_mutex);
83 snd_gus_synth_free_voices(gus, info->sender.client, info->sender.port);
84 snd_gus_use_dec(gus);
85 up(&gus->register_mutex);
86 return 0;
87}
88
89/*
90 *
91 */
92
93static void snd_gus_synth_free_private_instruments(snd_gus_port_t *p, int client)
94{
95 snd_seq_instr_header_t ifree;
96
97 memset(&ifree, 0, sizeof(ifree));
98 ifree.cmd = SNDRV_SEQ_INSTR_FREE_CMD_PRIVATE;
99 snd_seq_instr_list_free_cond(p->gus->gf1.ilist, &ifree, client, 0);
100}
101
102int snd_gus_synth_event_input(snd_seq_event_t *ev, int direct, void *private_data, int atomic, int hop)
103{
104 snd_gus_port_t * p = (snd_gus_port_t *) private_data;
105
106 snd_assert(p != NULL, return -EINVAL);
107 if (ev->type >= SNDRV_SEQ_EVENT_SAMPLE &&
108 ev->type <= SNDRV_SEQ_EVENT_SAMPLE_PRIVATE1) {
109 snd_gus_sample_event(ev, p);
110 return 0;
111 }
112 if (ev->source.client == SNDRV_SEQ_CLIENT_SYSTEM &&
113 ev->source.port == SNDRV_SEQ_PORT_SYSTEM_ANNOUNCE) {
114 if (ev->type == SNDRV_SEQ_EVENT_CLIENT_EXIT) {
115 snd_gus_synth_free_private_instruments(p, ev->data.addr.client);
116 return 0;
117 }
118 }
119 if (direct) {
120 if (ev->type >= SNDRV_SEQ_EVENT_INSTR_BEGIN) {
121 snd_seq_instr_event(&p->gus->gf1.iwffff_ops.kops,
122 p->gus->gf1.ilist,
123 ev,
124 p->gus->gf1.seq_client,
125 atomic, hop);
126 return 0;
127 }
128 }
129 return 0;
130}
131
132static void snd_gus_synth_instr_notify(void *private_data,
133 snd_seq_kinstr_t *instr,
134 int what)
135{
136 unsigned int idx;
137 snd_gus_card_t *gus = private_data;
138 snd_gus_voice_t *pvoice;
139 unsigned long flags;
140
141 spin_lock_irqsave(&gus->event_lock, flags);
142 for (idx = 0; idx < 32; idx++) {
143 pvoice = &gus->gf1.voices[idx];
144 if (pvoice->use && !memcmp(&pvoice->instr, &instr->instr, sizeof(pvoice->instr))) {
145 if (pvoice->sample_ops && pvoice->sample_ops->sample_stop) {
146 pvoice->sample_ops->sample_stop(gus, pvoice, SAMPLE_STOP_IMMEDIATELY);
147 } else {
148 snd_gf1_stop_voice(gus, pvoice->number);
149 pvoice->flags &= ~SNDRV_GF1_VFLG_RUNNING;
150 }
151 }
152 }
153 spin_unlock_irqrestore(&gus->event_lock, flags);
154}
155
156/*
157 *
158 */
159
160static void snd_gus_synth_free_port(void *private_data)
161{
162 snd_gus_port_t * p = (snd_gus_port_t *)private_data;
163
164 if (p)
165 snd_midi_channel_free_set(p->chset);
166}
167
168static int snd_gus_synth_create_port(snd_gus_card_t * gus, int idx)
169{
170 snd_gus_port_t * p;
171 snd_seq_port_callback_t callbacks;
172 char name[32];
173 int result;
174
175 p = &gus->gf1.seq_ports[idx];
176 p->chset = snd_midi_channel_alloc_set(16);
177 if (p->chset == NULL)
178 return -ENOMEM;
179 p->chset->private_data = p;
180 p->gus = gus;
181 p->client = gus->gf1.seq_client;
182
183 memset(&callbacks, 0, sizeof(callbacks));
184 callbacks.owner = THIS_MODULE;
185 callbacks.use = snd_gus_synth_use;
186 callbacks.unuse = snd_gus_synth_unuse;
187 callbacks.event_input = snd_gus_synth_event_input;
188 callbacks.private_free = snd_gus_synth_free_port;
189 callbacks.private_data = p;
190
191 sprintf(name, "%s port %i", gus->interwave ? "AMD InterWave" : "GF1", idx);
192 p->chset->port = snd_seq_event_port_attach(gus->gf1.seq_client,
193 &callbacks,
194 SNDRV_SEQ_PORT_CAP_WRITE | SNDRV_SEQ_PORT_CAP_SUBS_WRITE,
195 SNDRV_SEQ_PORT_TYPE_DIRECT_SAMPLE |
196 SNDRV_SEQ_PORT_TYPE_SYNTH,
197 16, 0,
198 name);
199 if (p->chset->port < 0) {
200 result = p->chset->port;
201 snd_gus_synth_free_port(p);
202 return result;
203 }
204 p->port = p->chset->port;
205 return 0;
206}
207
208/*
209 *
210 */
211
212static int snd_gus_synth_new_device(snd_seq_device_t *dev)
213{
214 snd_gus_card_t *gus;
215 int client, i;
216 snd_seq_client_callback_t callbacks;
217 snd_seq_client_info_t *cinfo;
218 snd_seq_port_subscribe_t sub;
219 snd_iwffff_ops_t *iwops;
220 snd_gf1_ops_t *gf1ops;
221 snd_simple_ops_t *simpleops;
222
223 gus = *(snd_gus_card_t**)SNDRV_SEQ_DEVICE_ARGPTR(dev);
224 if (gus == NULL)
225 return -EINVAL;
226
227 init_MUTEX(&gus->register_mutex);
228 gus->gf1.seq_client = -1;
229
230 cinfo = kmalloc(sizeof(*cinfo), GFP_KERNEL);
231 if (! cinfo)
232 return -ENOMEM;
233
234 /* allocate new client */
235 memset(&callbacks, 0, sizeof(callbacks));
236 callbacks.private_data = gus;
237 callbacks.allow_output = callbacks.allow_input = 1;
238 client = gus->gf1.seq_client =
239 snd_seq_create_kernel_client(gus->card, 1, &callbacks);
240 if (client < 0) {
241 kfree(cinfo);
242 return client;
243 }
244
245 /* change name of client */
246 memset(cinfo, 0, sizeof(*cinfo));
247 cinfo->client = client;
248 cinfo->type = KERNEL_CLIENT;
249 sprintf(cinfo->name, gus->interwave ? "AMD InterWave" : "GF1");
250 snd_seq_kernel_client_ctl(client, SNDRV_SEQ_IOCTL_SET_CLIENT_INFO, cinfo);
251 kfree(cinfo);
252
253 for (i = 0; i < 4; i++)
254 snd_gus_synth_create_port(gus, i);
255
256 gus->gf1.ilist = snd_seq_instr_list_new();
257 if (gus->gf1.ilist == NULL) {
258 snd_seq_delete_kernel_client(client);
259 gus->gf1.seq_client = -1;
260 return -ENOMEM;
261 }
262 gus->gf1.ilist->flags = SNDRV_SEQ_INSTR_FLG_DIRECT;
263
264 simpleops = &gus->gf1.simple_ops;
265 snd_seq_simple_init(simpleops, gus, NULL);
266 simpleops->put_sample = snd_gus_simple_put_sample;
267 simpleops->get_sample = snd_gus_simple_get_sample;
268 simpleops->remove_sample = snd_gus_simple_remove_sample;
269 simpleops->notify = snd_gus_synth_instr_notify;
270
271 gf1ops = &gus->gf1.gf1_ops;
272 snd_seq_gf1_init(gf1ops, gus, &simpleops->kops);
273 gf1ops->put_sample = snd_gus_gf1_put_sample;
274 gf1ops->get_sample = snd_gus_gf1_get_sample;
275 gf1ops->remove_sample = snd_gus_gf1_remove_sample;
276 gf1ops->notify = snd_gus_synth_instr_notify;
277
278 iwops = &gus->gf1.iwffff_ops;
279 snd_seq_iwffff_init(iwops, gus, &gf1ops->kops);
280 iwops->put_sample = snd_gus_iwffff_put_sample;
281 iwops->get_sample = snd_gus_iwffff_get_sample;
282 iwops->remove_sample = snd_gus_iwffff_remove_sample;
283 iwops->notify = snd_gus_synth_instr_notify;
284
285 memset(&sub, 0, sizeof(sub));
286 sub.sender.client = SNDRV_SEQ_CLIENT_SYSTEM;
287 sub.sender.port = SNDRV_SEQ_PORT_SYSTEM_ANNOUNCE;
288 sub.dest.client = client;
289 sub.dest.port = 0;
290 snd_seq_kernel_client_ctl(client, SNDRV_SEQ_IOCTL_SUBSCRIBE_PORT, &sub);
291
292 return 0;
293}
294
295static int snd_gus_synth_delete_device(snd_seq_device_t *dev)
296{
297 snd_gus_card_t *gus;
298
299 gus = *(snd_gus_card_t**)SNDRV_SEQ_DEVICE_ARGPTR(dev);
300 if (gus == NULL)
301 return -EINVAL;
302
303 if (gus->gf1.seq_client >= 0) {
304 snd_seq_delete_kernel_client(gus->gf1.seq_client);
305 gus->gf1.seq_client = -1;
306 }
307 if (gus->gf1.ilist)
308 snd_seq_instr_list_free(&gus->gf1.ilist);
309 return 0;
310}
311
312static int __init alsa_gus_synth_init(void)
313{
314 static snd_seq_dev_ops_t ops = {
315 snd_gus_synth_new_device,
316 snd_gus_synth_delete_device
317 };
318
319 return snd_seq_device_register_driver(SNDRV_SEQ_DEV_ID_GUS, &ops,
320 sizeof(snd_gus_card_t*));
321}
322
323static void __exit alsa_gus_synth_exit(void)
324{
325 snd_seq_device_unregister_driver(SNDRV_SEQ_DEV_ID_GUS);
326}
327
328module_init(alsa_gus_synth_init)
329module_exit(alsa_gus_synth_exit)
diff --git a/sound/isa/gus/gus_tables.h b/sound/isa/gus/gus_tables.h
new file mode 100644
index 000000000000..ed8e9d85ad31
--- /dev/null
+++ b/sound/isa/gus/gus_tables.h
@@ -0,0 +1,86 @@
1/*
2 * Copyright (c) by Jaroslav Kysela <perex@suse.cz>
3 *
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 *
19 */
20
21#define SNDRV_GF1_SCALE_TABLE_SIZE 128
22#define SNDRV_GF1_ATTEN_TABLE_SIZE 128
23
24#ifdef __GUS_TABLES_ALLOC__
25
26unsigned int snd_gf1_scale_table[SNDRV_GF1_SCALE_TABLE_SIZE] =
27{
28 8372, 8870, 9397, 9956, 10548, 11175,
29 11840, 12544, 13290, 14080, 14917, 15804,
30 16744, 17740, 18795, 19912, 21096, 22351,
31 23680, 25088, 26580, 28160, 29834, 31609,
32 33488, 35479, 37589, 39824, 42192, 44701,
33 47359, 50175, 53159, 56320, 59669, 63217,
34 66976, 70959, 75178, 79649, 84385, 89402,
35 94719, 100351, 106318, 112640, 119338, 126434,
36 133952, 141918, 150356, 159297, 168769, 178805,
37 189437, 200702, 212636, 225280, 238676, 252868,
38 267905, 283835, 300713, 318594, 337539, 357610,
39 378874, 401403, 425272, 450560, 477352, 505737,
40 535809, 567670, 601425, 637188, 675077, 715219,
41 757749, 802807, 850544, 901120, 954703, 1011473,
42 1071618, 1135340, 1202851, 1274376, 1350154, 1430439,
43 1515497, 1605613, 1701088, 1802240, 1909407, 2022946,
44 2143237, 2270680, 2405702, 2548752, 2700309, 2860878,
45 3030994, 3211227, 3402176, 3604480, 3818814, 4045892,
46 4286473, 4541360, 4811404, 5097505, 5400618, 5721755,
47 6061989, 6422453, 6804352, 7208960, 7637627, 8091784,
48 8572947, 9082720, 9622807, 10195009, 10801236, 11443511,
49 12123977, 12844906
50};
51
52unsigned short snd_gf1_atten_table[SNDRV_GF1_ATTEN_TABLE_SIZE] = {
53 4095 /* 0 */,1789 /* 1 */,1533 /* 2 */,1383 /* 3 */,1277 /* 4 */,
54 1195 /* 5 */,1127 /* 6 */,1070 /* 7 */,1021 /* 8 */,978 /* 9 */,
55 939 /* 10 */,903 /* 11 */,871 /* 12 */,842 /* 13 */,814 /* 14 */,
56 789 /* 15 */,765 /* 16 */,743 /* 17 */,722 /* 18 */,702 /* 19 */,
57 683 /* 20 */,665 /* 21 */,647 /* 22 */,631 /* 23 */,615 /* 24 */,
58 600 /* 25 */,586 /* 26 */,572 /* 27 */,558 /* 28 */,545 /* 29 */,
59 533 /* 30 */,521 /* 31 */,509 /* 32 */,498 /* 33 */,487 /* 34 */,
60 476 /* 35 */,466 /* 36 */,455 /* 37 */,446 /* 38 */,436 /* 39 */,
61 427 /* 40 */,418 /* 41 */,409 /* 42 */,400 /* 43 */,391 /* 44 */,
62 383 /* 45 */,375 /* 46 */,367 /* 47 */,359 /* 48 */,352 /* 49 */,
63 344 /* 50 */,337 /* 51 */,330 /* 52 */,323 /* 53 */,316 /* 54 */,
64 309 /* 55 */,302 /* 56 */,296 /* 57 */,289 /* 58 */,283 /* 59 */,
65 277 /* 60 */,271 /* 61 */,265 /* 62 */,259 /* 63 */,253 /* 64 */,
66 247 /* 65 */,242 /* 66 */,236 /* 67 */,231 /* 68 */,225 /* 69 */,
67 220 /* 70 */,215 /* 71 */,210 /* 72 */,205 /* 73 */,199 /* 74 */,
68 195 /* 75 */,190 /* 76 */,185 /* 77 */,180 /* 78 */,175 /* 79 */,
69 171 /* 80 */,166 /* 81 */,162 /* 82 */,157 /* 83 */,153 /* 84 */,
70 148 /* 85 */,144 /* 86 */,140 /* 87 */,135 /* 88 */,131 /* 89 */,
71 127 /* 90 */,123 /* 91 */,119 /* 92 */,115 /* 93 */,111 /* 94 */,
72 107 /* 95 */,103 /* 96 */,100 /* 97 */,96 /* 98 */,92 /* 99 */,
73 88 /* 100 */,85 /* 101 */,81 /* 102 */,77 /* 103 */,74 /* 104 */,
74 70 /* 105 */,67 /* 106 */,63 /* 107 */,60 /* 108 */,56 /* 109 */,
75 53 /* 110 */,50 /* 111 */,46 /* 112 */,43 /* 113 */,40 /* 114 */,
76 37 /* 115 */,33 /* 116 */,30 /* 117 */,27 /* 118 */,24 /* 119 */,
77 21 /* 120 */,18 /* 121 */,15 /* 122 */,12 /* 123 */,9 /* 124 */,
78 6 /* 125 */,3 /* 126 */,0 /* 127 */,
79};
80
81#else
82
83extern unsigned int snd_gf1_scale_table[SNDRV_GF1_SCALE_TABLE_SIZE];
84extern unsigned short snd_gf1_atten_table[SNDRV_GF1_ATTEN_TABLE_SIZE];
85
86#endif
diff --git a/sound/isa/gus/gus_timer.c b/sound/isa/gus/gus_timer.c
new file mode 100644
index 000000000000..9876603ff6c1
--- /dev/null
+++ b/sound/isa/gus/gus_timer.c
@@ -0,0 +1,204 @@
1/*
2 * Routines for Gravis UltraSound soundcards - Timers
3 * Copyright (c) by Jaroslav Kysela <perex@suse.cz>
4 *
5 * GUS have similar timers as AdLib (OPL2/OPL3 chips).
6 *
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21 *
22 */
23
24#include <sound/driver.h>
25#include <linux/time.h>
26#include <sound/core.h>
27#include <sound/gus.h>
28
29/*
30 * Timer 1 - 80us
31 */
32
33static int snd_gf1_timer1_start(snd_timer_t * timer)
34{
35 unsigned long flags;
36 unsigned char tmp;
37 unsigned int ticks;
38 snd_gus_card_t *gus;
39
40 gus = snd_timer_chip(timer);
41 spin_lock_irqsave(&gus->reg_lock, flags);
42 ticks = timer->sticks;
43 tmp = (gus->gf1.timer_enabled |= 4);
44 snd_gf1_write8(gus, SNDRV_GF1_GB_ADLIB_TIMER_1, 256 - ticks); /* timer 1 count */
45 snd_gf1_write8(gus, SNDRV_GF1_GB_SOUND_BLASTER_CONTROL, tmp); /* enable timer 1 IRQ */
46 snd_gf1_adlib_write(gus, 0x04, tmp >> 2); /* timer 2 start */
47 spin_unlock_irqrestore(&gus->reg_lock, flags);
48 return 0;
49}
50
51static int snd_gf1_timer1_stop(snd_timer_t * timer)
52{
53 unsigned long flags;
54 unsigned char tmp;
55 snd_gus_card_t *gus;
56
57 gus = snd_timer_chip(timer);
58 spin_lock_irqsave(&gus->reg_lock, flags);
59 tmp = (gus->gf1.timer_enabled &= ~4);
60 snd_gf1_write8(gus, SNDRV_GF1_GB_SOUND_BLASTER_CONTROL, tmp); /* disable timer #1 */
61 spin_unlock_irqrestore(&gus->reg_lock, flags);
62 return 0;
63}
64
65/*
66 * Timer 2 - 320us
67 */
68
69static int snd_gf1_timer2_start(snd_timer_t * timer)
70{
71 unsigned long flags;
72 unsigned char tmp;
73 unsigned int ticks;
74 snd_gus_card_t *gus;
75
76 gus = snd_timer_chip(timer);
77 spin_lock_irqsave(&gus->reg_lock, flags);
78 ticks = timer->sticks;
79 tmp = (gus->gf1.timer_enabled |= 8);
80 snd_gf1_write8(gus, SNDRV_GF1_GB_ADLIB_TIMER_2, 256 - ticks); /* timer 2 count */
81 snd_gf1_write8(gus, SNDRV_GF1_GB_SOUND_BLASTER_CONTROL, tmp); /* enable timer 2 IRQ */
82 snd_gf1_adlib_write(gus, 0x04, tmp >> 2); /* timer 2 start */
83 spin_unlock_irqrestore(&gus->reg_lock, flags);
84 return 0;
85}
86
87static int snd_gf1_timer2_stop(snd_timer_t * timer)
88{
89 unsigned long flags;
90 unsigned char tmp;
91 snd_gus_card_t *gus;
92
93 gus = snd_timer_chip(timer);
94 spin_lock_irqsave(&gus->reg_lock, flags);
95 tmp = (gus->gf1.timer_enabled &= ~8);
96 snd_gf1_write8(gus, SNDRV_GF1_GB_SOUND_BLASTER_CONTROL, tmp); /* disable timer #1 */
97 spin_unlock_irqrestore(&gus->reg_lock, flags);
98 return 0;
99}
100
101/*
102
103 */
104
105static void snd_gf1_interrupt_timer1(snd_gus_card_t * gus)
106{
107 snd_timer_t *timer = gus->gf1.timer1;
108
109 if (timer == NULL)
110 return;
111 snd_timer_interrupt(timer, timer->sticks);
112}
113
114static void snd_gf1_interrupt_timer2(snd_gus_card_t * gus)
115{
116 snd_timer_t *timer = gus->gf1.timer2;
117
118 if (timer == NULL)
119 return;
120 snd_timer_interrupt(timer, timer->sticks);
121}
122
123/*
124
125 */
126
127static struct _snd_timer_hardware snd_gf1_timer1 =
128{
129 .flags = SNDRV_TIMER_HW_STOP,
130 .resolution = 80000,
131 .ticks = 256,
132 .start = snd_gf1_timer1_start,
133 .stop = snd_gf1_timer1_stop,
134};
135
136static struct _snd_timer_hardware snd_gf1_timer2 =
137{
138 .flags = SNDRV_TIMER_HW_STOP,
139 .resolution = 320000,
140 .ticks = 256,
141 .start = snd_gf1_timer2_start,
142 .stop = snd_gf1_timer2_stop,
143};
144
145static void snd_gf1_timer1_free(snd_timer_t *timer)
146{
147 snd_gus_card_t *gus = timer->private_data;
148 gus->gf1.timer1 = NULL;
149}
150
151static void snd_gf1_timer2_free(snd_timer_t *timer)
152{
153 snd_gus_card_t *gus = timer->private_data;
154 gus->gf1.timer2 = NULL;
155}
156
157void snd_gf1_timers_init(snd_gus_card_t * gus)
158{
159 snd_timer_t *timer;
160 snd_timer_id_t tid;
161
162 if (gus->gf1.timer1 != NULL || gus->gf1.timer2 != NULL)
163 return;
164
165 gus->gf1.interrupt_handler_timer1 = snd_gf1_interrupt_timer1;
166 gus->gf1.interrupt_handler_timer2 = snd_gf1_interrupt_timer2;
167
168 tid.dev_class = SNDRV_TIMER_CLASS_CARD;
169 tid.dev_sclass = SNDRV_TIMER_SCLASS_NONE;
170 tid.card = gus->card->number;
171 tid.device = gus->timer_dev;
172 tid.subdevice = 0;
173
174 if (snd_timer_new(gus->card, "GF1 timer", &tid, &timer) >= 0) {
175 strcpy(timer->name, "GF1 timer #1");
176 timer->private_data = gus;
177 timer->private_free = snd_gf1_timer1_free;
178 timer->hw = snd_gf1_timer1;
179 }
180 gus->gf1.timer1 = timer;
181
182 tid.device++;
183
184 if (snd_timer_new(gus->card, "GF1 timer", &tid, &timer) >= 0) {
185 strcpy(timer->name, "GF1 timer #2");
186 timer->private_data = gus;
187 timer->private_free = snd_gf1_timer2_free;
188 timer->hw = snd_gf1_timer2;
189 }
190 gus->gf1.timer2 = timer;
191}
192
193void snd_gf1_timers_done(snd_gus_card_t * gus)
194{
195 snd_gf1_set_default_handlers(gus, SNDRV_GF1_HANDLER_TIMER1 | SNDRV_GF1_HANDLER_TIMER2);
196 if (gus->gf1.timer1) {
197 snd_device_free(gus->card, gus->gf1.timer1);
198 gus->gf1.timer1 = NULL;
199 }
200 if (gus->gf1.timer2) {
201 snd_device_free(gus->card, gus->gf1.timer2);
202 gus->gf1.timer2 = NULL;
203 }
204}
diff --git a/sound/isa/gus/gus_uart.c b/sound/isa/gus/gus_uart.c
new file mode 100644
index 000000000000..1bc2da8784e0
--- /dev/null
+++ b/sound/isa/gus/gus_uart.c
@@ -0,0 +1,257 @@
1/*
2 * Copyright (c) by Jaroslav Kysela <perex@suse.cz>
3 * Routines for the GF1 MIDI interface - like UART 6850
4 *
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 *
20 */
21
22#include <sound/driver.h>
23#include <linux/delay.h>
24#include <linux/interrupt.h>
25#include <linux/time.h>
26#include <sound/core.h>
27#include <sound/gus.h>
28
29static void snd_gf1_interrupt_midi_in(snd_gus_card_t * gus)
30{
31 int count;
32 unsigned char stat, data, byte;
33 unsigned long flags;
34
35 count = 10;
36 while (count) {
37 spin_lock_irqsave(&gus->uart_cmd_lock, flags);
38 stat = snd_gf1_uart_stat(gus);
39 if (!(stat & 0x01)) { /* data in Rx FIFO? */
40 spin_unlock_irqrestore(&gus->uart_cmd_lock, flags);
41 count--;
42 continue;
43 }
44 count = 100; /* arm counter to new value */
45 data = snd_gf1_uart_get(gus);
46 if (!(gus->gf1.uart_cmd & 0x80)) {
47 spin_unlock_irqrestore(&gus->uart_cmd_lock, flags);
48 continue;
49 }
50 if (stat & 0x10) { /* framing error */
51 gus->gf1.uart_framing++;
52 spin_unlock_irqrestore(&gus->uart_cmd_lock, flags);
53 continue;
54 }
55 byte = snd_gf1_uart_get(gus);
56 spin_unlock_irqrestore(&gus->uart_cmd_lock, flags);
57 snd_rawmidi_receive(gus->midi_substream_input, &byte, 1);
58 if (stat & 0x20) {
59 gus->gf1.uart_overrun++;
60 }
61 }
62}
63
64static void snd_gf1_interrupt_midi_out(snd_gus_card_t * gus)
65{
66 char byte;
67 unsigned long flags;
68
69 /* try unlock output */
70 if (snd_gf1_uart_stat(gus) & 0x01)
71 snd_gf1_interrupt_midi_in(gus);
72
73 spin_lock_irqsave(&gus->uart_cmd_lock, flags);
74 if (snd_gf1_uart_stat(gus) & 0x02) { /* Tx FIFO free? */
75 if (snd_rawmidi_transmit(gus->midi_substream_output, &byte, 1) != 1) { /* no other bytes or error */
76 snd_gf1_uart_cmd(gus, gus->gf1.uart_cmd & ~0x20); /* disable Tx interrupt */
77 } else {
78 snd_gf1_uart_put(gus, byte);
79 }
80 }
81 spin_unlock_irqrestore(&gus->uart_cmd_lock, flags);
82}
83
84static void snd_gf1_uart_reset(snd_gus_card_t * gus, int close)
85{
86 snd_gf1_uart_cmd(gus, 0x03); /* reset */
87 if (!close && gus->uart_enable) {
88 udelay(160);
89 snd_gf1_uart_cmd(gus, 0x00); /* normal operations */
90 }
91}
92
93static int snd_gf1_uart_output_open(snd_rawmidi_substream_t * substream)
94{
95 unsigned long flags;
96 snd_gus_card_t *gus;
97
98 gus = substream->rmidi->private_data;
99 spin_lock_irqsave(&gus->uart_cmd_lock, flags);
100 if (!(gus->gf1.uart_cmd & 0x80)) { /* input active? */
101 snd_gf1_uart_reset(gus, 0);
102 }
103 gus->gf1.interrupt_handler_midi_out = snd_gf1_interrupt_midi_out;
104 gus->midi_substream_output = substream;
105 spin_unlock_irqrestore(&gus->uart_cmd_lock, flags);
106#if 0
107 snd_printk("write init - cmd = 0x%x, stat = 0x%x\n", gus->gf1.uart_cmd, snd_gf1_uart_stat(gus));
108#endif
109 return 0;
110}
111
112static int snd_gf1_uart_input_open(snd_rawmidi_substream_t * substream)
113{
114 unsigned long flags;
115 snd_gus_card_t *gus;
116 int i;
117
118 gus = substream->rmidi->private_data;
119 spin_lock_irqsave(&gus->uart_cmd_lock, flags);
120 if (gus->gf1.interrupt_handler_midi_out != snd_gf1_interrupt_midi_out) {
121 snd_gf1_uart_reset(gus, 0);
122 }
123 gus->gf1.interrupt_handler_midi_in = snd_gf1_interrupt_midi_in;
124 gus->midi_substream_input = substream;
125 if (gus->uart_enable) {
126 for (i = 0; i < 1000 && (snd_gf1_uart_stat(gus) & 0x01); i++)
127 snd_gf1_uart_get(gus); /* clean Rx */
128 if (i >= 1000)
129 snd_printk("gus midi uart init read - cleanup error\n");
130 }
131 spin_unlock_irqrestore(&gus->uart_cmd_lock, flags);
132#if 0
133 snd_printk("read init - enable = %i, cmd = 0x%x, stat = 0x%x\n", gus->uart_enable, gus->gf1.uart_cmd, snd_gf1_uart_stat(gus));
134 snd_printk("[0x%x] reg (ctrl/status) = 0x%x, reg (data) = 0x%x (page = 0x%x)\n", gus->gf1.port + 0x100, inb(gus->gf1.port + 0x100), inb(gus->gf1.port + 0x101), inb(gus->gf1.port + 0x102));
135#endif
136 return 0;
137}
138
139static int snd_gf1_uart_output_close(snd_rawmidi_substream_t * substream)
140{
141 unsigned long flags;
142 snd_gus_card_t *gus;
143
144 gus = substream->rmidi->private_data;
145 spin_lock_irqsave(&gus->uart_cmd_lock, flags);
146 if (gus->gf1.interrupt_handler_midi_in != snd_gf1_interrupt_midi_in)
147 snd_gf1_uart_reset(gus, 1);
148 snd_gf1_set_default_handlers(gus, SNDRV_GF1_HANDLER_MIDI_OUT);
149 gus->midi_substream_output = NULL;
150 spin_unlock_irqrestore(&gus->uart_cmd_lock, flags);
151 return 0;
152}
153
154static int snd_gf1_uart_input_close(snd_rawmidi_substream_t * substream)
155{
156 unsigned long flags;
157 snd_gus_card_t *gus;
158
159 gus = substream->rmidi->private_data;
160 spin_lock_irqsave(&gus->uart_cmd_lock, flags);
161 if (gus->gf1.interrupt_handler_midi_out != snd_gf1_interrupt_midi_out)
162 snd_gf1_uart_reset(gus, 1);
163 snd_gf1_set_default_handlers(gus, SNDRV_GF1_HANDLER_MIDI_IN);
164 gus->midi_substream_input = NULL;
165 spin_unlock_irqrestore(&gus->uart_cmd_lock, flags);
166 return 0;
167}
168
169static void snd_gf1_uart_input_trigger(snd_rawmidi_substream_t * substream, int up)
170{
171 snd_gus_card_t *gus;
172 unsigned long flags;
173
174 gus = substream->rmidi->private_data;
175
176 spin_lock_irqsave(&gus->uart_cmd_lock, flags);
177 if (up) {
178 if ((gus->gf1.uart_cmd & 0x80) == 0)
179 snd_gf1_uart_cmd(gus, gus->gf1.uart_cmd | 0x80); /* enable Rx interrupts */
180 } else {
181 if (gus->gf1.uart_cmd & 0x80)
182 snd_gf1_uart_cmd(gus, gus->gf1.uart_cmd & ~0x80); /* disable Rx interrupts */
183 }
184 spin_unlock_irqrestore(&gus->uart_cmd_lock, flags);
185}
186
187static void snd_gf1_uart_output_trigger(snd_rawmidi_substream_t * substream, int up)
188{
189 unsigned long flags;
190 snd_gus_card_t *gus;
191 char byte;
192 int timeout;
193
194 gus = substream->rmidi->private_data;
195
196 spin_lock_irqsave(&gus->uart_cmd_lock, flags);
197 if (up) {
198 if ((gus->gf1.uart_cmd & 0x20) == 0) {
199 spin_unlock_irqrestore(&gus->uart_cmd_lock, flags);
200 /* wait for empty Rx - Tx is probably unlocked */
201 timeout = 10000;
202 while (timeout-- > 0 && snd_gf1_uart_stat(gus) & 0x01);
203 /* Tx FIFO free? */
204 spin_lock_irqsave(&gus->uart_cmd_lock, flags);
205 if (gus->gf1.uart_cmd & 0x20) {
206 spin_unlock_irqrestore(&gus->uart_cmd_lock, flags);
207 return;
208 }
209 if (snd_gf1_uart_stat(gus) & 0x02) {
210 if (snd_rawmidi_transmit(substream, &byte, 1) != 1) {
211 spin_unlock_irqrestore(&gus->uart_cmd_lock, flags);
212 return;
213 }
214 snd_gf1_uart_put(gus, byte);
215 }
216 snd_gf1_uart_cmd(gus, gus->gf1.uart_cmd | 0x20); /* enable Tx interrupt */
217 }
218 } else {
219 if (gus->gf1.uart_cmd & 0x20)
220 snd_gf1_uart_cmd(gus, gus->gf1.uart_cmd & ~0x20);
221 }
222 spin_unlock_irqrestore(&gus->uart_cmd_lock, flags);
223}
224
225static snd_rawmidi_ops_t snd_gf1_uart_output =
226{
227 .open = snd_gf1_uart_output_open,
228 .close = snd_gf1_uart_output_close,
229 .trigger = snd_gf1_uart_output_trigger,
230};
231
232static snd_rawmidi_ops_t snd_gf1_uart_input =
233{
234 .open = snd_gf1_uart_input_open,
235 .close = snd_gf1_uart_input_close,
236 .trigger = snd_gf1_uart_input_trigger,
237};
238
239int snd_gf1_rawmidi_new(snd_gus_card_t * gus, int device, snd_rawmidi_t ** rrawmidi)
240{
241 snd_rawmidi_t *rmidi;
242 int err;
243
244 if (rrawmidi)
245 *rrawmidi = NULL;
246 if ((err = snd_rawmidi_new(gus->card, "GF1", device, 1, 1, &rmidi)) < 0)
247 return err;
248 strcpy(rmidi->name, gus->interwave ? "AMD InterWave" : "GF1");
249 snd_rawmidi_set_ops(rmidi, SNDRV_RAWMIDI_STREAM_OUTPUT, &snd_gf1_uart_output);
250 snd_rawmidi_set_ops(rmidi, SNDRV_RAWMIDI_STREAM_INPUT, &snd_gf1_uart_input);
251 rmidi->info_flags |= SNDRV_RAWMIDI_INFO_OUTPUT | SNDRV_RAWMIDI_INFO_INPUT | SNDRV_RAWMIDI_INFO_DUPLEX;
252 rmidi->private_data = gus;
253 gus->midi_uart = rmidi;
254 if (rrawmidi)
255 *rrawmidi = rmidi;
256 return err;
257}
diff --git a/sound/isa/gus/gus_volume.c b/sound/isa/gus/gus_volume.c
new file mode 100644
index 000000000000..b72bcfb28617
--- /dev/null
+++ b/sound/isa/gus/gus_volume.c
@@ -0,0 +1,210 @@
1/*
2 * Copyright (c) by Jaroslav Kysela <perex@suse.cz>
3 *
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 *
19 */
20
21#include <sound/driver.h>
22#include <linux/time.h>
23#include <sound/core.h>
24#include <sound/gus.h>
25#define __GUS_TABLES_ALLOC__
26#include "gus_tables.h"
27
28EXPORT_SYMBOL(snd_gf1_atten_table); /* for snd-gus-synth module */
29
30unsigned short snd_gf1_lvol_to_gvol_raw(unsigned int vol)
31{
32 unsigned short e, m, tmp;
33
34 if (vol > 65535)
35 vol = 65535;
36 tmp = vol;
37 e = 7;
38 if (tmp < 128) {
39 while (e > 0 && tmp < (1 << e))
40 e--;
41 } else {
42 while (tmp > 255) {
43 tmp >>= 1;
44 e++;
45 }
46 }
47 m = vol - (1 << e);
48 if (m > 0) {
49 if (e > 8)
50 m >>= e - 8;
51 else if (e < 8)
52 m <<= 8 - e;
53 m &= 255;
54 }
55 return (e << 8) | m;
56}
57
58unsigned int snd_gf1_gvol_to_lvol_raw(unsigned short gf1_vol)
59{
60 unsigned int rvol;
61 unsigned short e, m;
62
63 if (!gf1_vol)
64 return 0;
65 e = gf1_vol >> 8;
66 m = (unsigned char) gf1_vol;
67 rvol = 1 << e;
68 if (e > 8)
69 return rvol | (m << (e - 8));
70 return rvol | (m >> (8 - e));
71}
72
73unsigned int snd_gf1_calc_ramp_rate(snd_gus_card_t * gus,
74 unsigned short start,
75 unsigned short end,
76 unsigned int us)
77{
78 static unsigned char vol_rates[19] =
79 {
80 23, 24, 26, 28, 29, 31, 32, 34,
81 36, 37, 39, 40, 42, 44, 45, 47,
82 49, 50, 52
83 };
84 unsigned short range, increment, value, i;
85
86 start >>= 4;
87 end >>= 4;
88 if (start < end)
89 us /= end - start;
90 else
91 us /= start - end;
92 range = 4;
93 value = gus->gf1.enh_mode ?
94 vol_rates[0] :
95 vol_rates[gus->gf1.active_voices - 14];
96 for (i = 0; i < 3; i++) {
97 if (us < value) {
98 range = i;
99 break;
100 } else
101 value <<= 3;
102 }
103 if (range == 4) {
104 range = 3;
105 increment = 1;
106 } else
107 increment = (value + (value >> 1)) / us;
108 return (range << 6) | (increment & 0x3f);
109}
110
111unsigned short snd_gf1_translate_freq(snd_gus_card_t * gus, unsigned int freq16)
112{
113 freq16 >>= 3;
114 if (freq16 < 50)
115 freq16 = 50;
116 if (freq16 & 0xf8000000) {
117 freq16 = ~0xf8000000;
118 snd_printk("snd_gf1_translate_freq: overflow - freq = 0x%x\n", freq16);
119 }
120 return ((freq16 << 9) + (gus->gf1.playback_freq >> 1)) / gus->gf1.playback_freq;
121}
122
123short snd_gf1_compute_vibrato(short cents, unsigned short fc_register)
124{
125 static short vibrato_table[] =
126 {
127 0, 0, 32, 592, 61, 1175, 93, 1808,
128 124, 2433, 152, 3007, 182, 3632, 213, 4290,
129 241, 4834, 255, 5200
130 };
131
132 long depth;
133 short *vi1, *vi2, pcents, v1;
134
135 pcents = cents < 0 ? -cents : cents;
136 for (vi1 = vibrato_table, vi2 = vi1 + 2; pcents > *vi2; vi1 = vi2, vi2 += 2);
137 v1 = *(vi1 + 1);
138 /* The FC table above is a list of pairs. The first number in the pair */
139 /* is the cents index from 0-255 cents, and the second number in the */
140 /* pair is the FC adjustment needed to change the pitch by the indexed */
141 /* number of cents. The table was created for an FC of 32768. */
142 /* The following expression does a linear interpolation against the */
143 /* approximated log curve in the table above, and then scales the number */
144 /* by the FC before the LFO. This calculation also adjusts the output */
145 /* value to produce the appropriate depth for the hardware. The depth */
146 /* is 2 * desired FC + 1. */
147 depth = (((int) (*(vi2 + 1) - *vi1) * (pcents - *vi1) / (*vi2 - *vi1)) + v1) * fc_register >> 14;
148 if (depth)
149 depth++;
150 if (depth > 255)
151 depth = 255;
152 return cents < 0 ? -(short) depth : (short) depth;
153}
154
155unsigned short snd_gf1_compute_pitchbend(unsigned short pitchbend, unsigned short sens)
156{
157 static long log_table[] = {1024, 1085, 1149, 1218, 1290, 1367, 1448, 1534, 1625, 1722, 1825, 1933};
158 int wheel, sensitivity;
159 unsigned int mantissa, f1, f2;
160 unsigned short semitones, f1_index, f2_index, f1_power, f2_power;
161 char bend_down = 0;
162 int bend;
163
164 if (!sens)
165 return 1024;
166 wheel = (int) pitchbend - 8192;
167 sensitivity = ((int) sens * wheel) / 128;
168 if (sensitivity < 0) {
169 bend_down = 1;
170 sensitivity = -sensitivity;
171 }
172 semitones = (unsigned int) (sensitivity >> 13);
173 mantissa = sensitivity % 8192;
174 f1_index = semitones % 12;
175 f2_index = (semitones + 1) % 12;
176 f1_power = semitones / 12;
177 f2_power = (semitones + 1) / 12;
178 f1 = log_table[f1_index] << f1_power;
179 f2 = log_table[f2_index] << f2_power;
180 bend = (int) ((((f2 - f1) * mantissa) >> 13) + f1);
181 if (bend_down)
182 bend = 1048576L / bend;
183 return bend;
184}
185
186unsigned short snd_gf1_compute_freq(unsigned int freq,
187 unsigned int rate,
188 unsigned short mix_rate)
189{
190 unsigned int fc;
191 int scale = 0;
192
193 while (freq >= 4194304L) {
194 scale++;
195 freq >>= 1;
196 }
197 fc = (freq << 10) / rate;
198 if (fc > 97391L) {
199 fc = 97391;
200 snd_printk("patch: (1) fc frequency overflow - %u\n", fc);
201 }
202 fc = (fc * 44100UL) / mix_rate;
203 while (scale--)
204 fc <<= 1;
205 if (fc > 65535L) {
206 fc = 65535;
207 snd_printk("patch: (2) fc frequency overflow - %u\n", fc);
208 }
209 return (unsigned short) fc;
210}
diff --git a/sound/isa/gus/gusclassic.c b/sound/isa/gus/gusclassic.c
new file mode 100644
index 000000000000..a99fa5040b46
--- /dev/null
+++ b/sound/isa/gus/gusclassic.c
@@ -0,0 +1,260 @@
1/*
2 * Driver for Gravis UltraSound Classic soundcard
3 * Copyright (c) by Jaroslav Kysela <perex@suse.cz>
4 *
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 *
20 */
21
22#include <sound/driver.h>
23#include <asm/dma.h>
24#include <linux/init.h>
25#include <linux/delay.h>
26#include <linux/time.h>
27#include <linux/moduleparam.h>
28#include <sound/core.h>
29#include <sound/gus.h>
30#define SNDRV_LEGACY_AUTO_PROBE
31#define SNDRV_LEGACY_FIND_FREE_IRQ
32#define SNDRV_LEGACY_FIND_FREE_DMA
33#include <sound/initval.h>
34
35MODULE_AUTHOR("Jaroslav Kysela <perex@suse.cz>");
36MODULE_DESCRIPTION("Gravis UltraSound Classic");
37MODULE_LICENSE("GPL");
38MODULE_SUPPORTED_DEVICE("{{Gravis,UltraSound Classic}}");
39
40static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-MAX */
41static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* ID for this card */
42static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE; /* Enable this card */
43static long port[SNDRV_CARDS] = SNDRV_DEFAULT_PORT; /* 0x220,0x230,0x240,0x250,0x260 */
44static int irq[SNDRV_CARDS] = SNDRV_DEFAULT_IRQ; /* 3,5,9,11,12,15 */
45static int dma1[SNDRV_CARDS] = SNDRV_DEFAULT_DMA; /* 1,3,5,6,7 */
46static int dma2[SNDRV_CARDS] = SNDRV_DEFAULT_DMA; /* 1,3,5,6,7 */
47static int joystick_dac[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 29};
48 /* 0 to 31, (0.59V-4.52V or 0.389V-2.98V) */
49static int channels[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 24};
50static int pcm_channels[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 2};
51
52module_param_array(index, int, NULL, 0444);
53MODULE_PARM_DESC(index, "Index value for GUS Classic soundcard.");
54module_param_array(id, charp, NULL, 0444);
55MODULE_PARM_DESC(id, "ID string for GUS Classic soundcard.");
56module_param_array(enable, bool, NULL, 0444);
57MODULE_PARM_DESC(enable, "Enable GUS Classic soundcard.");
58module_param_array(port, long, NULL, 0444);
59MODULE_PARM_DESC(port, "Port # for GUS Classic driver.");
60module_param_array(irq, int, NULL, 0444);
61MODULE_PARM_DESC(irq, "IRQ # for GUS Classic driver.");
62module_param_array(dma1, int, NULL, 0444);
63MODULE_PARM_DESC(dma1, "DMA1 # for GUS Classic driver.");
64module_param_array(dma2, int, NULL, 0444);
65MODULE_PARM_DESC(dma2, "DMA2 # for GUS Classic driver.");
66module_param_array(joystick_dac, int, NULL, 0444);
67MODULE_PARM_DESC(joystick_dac, "Joystick DAC level 0.59V-4.52V or 0.389V-2.98V for GUS Classic driver.");
68module_param_array(channels, int, NULL, 0444);
69MODULE_PARM_DESC(channels, "GF1 channels for GUS Classic driver.");
70module_param_array(pcm_channels, int, NULL, 0444);
71MODULE_PARM_DESC(pcm_channels, "Reserved PCM channels for GUS Classic driver.");
72
73static snd_card_t *snd_gusclassic_cards[SNDRV_CARDS] = SNDRV_DEFAULT_PTR;
74
75
76static int __init snd_gusclassic_detect(snd_gus_card_t * gus)
77{
78 snd_gf1_i_write8(gus, SNDRV_GF1_GB_RESET, 0); /* reset GF1 */
79#ifdef CONFIG_SND_DEBUG_DETECT
80 {
81 unsigned char d;
82
83 if (((d = snd_gf1_i_look8(gus, SNDRV_GF1_GB_RESET)) & 0x07) != 0) {
84 snd_printk("[0x%lx] check 1 failed - 0x%x\n", gus->gf1.port, d);
85 return -ENODEV;
86 }
87 }
88#else
89 if ((snd_gf1_i_look8(gus, SNDRV_GF1_GB_RESET) & 0x07) != 0)
90 return -ENODEV;
91#endif
92 udelay(160);
93 snd_gf1_i_write8(gus, SNDRV_GF1_GB_RESET, 1); /* release reset */
94 udelay(160);
95#ifdef CONFIG_SND_DEBUG_DETECT
96 {
97 unsigned char d;
98
99 if (((d = snd_gf1_i_look8(gus, SNDRV_GF1_GB_RESET)) & 0x07) != 1) {
100 snd_printk("[0x%lx] check 2 failed - 0x%x\n", gus->gf1.port, d);
101 return -ENODEV;
102 }
103 }
104#else
105 if ((snd_gf1_i_look8(gus, SNDRV_GF1_GB_RESET) & 0x07) != 1)
106 return -ENODEV;
107#endif
108
109 return 0;
110}
111
112static void __init snd_gusclassic_init(int dev, snd_gus_card_t * gus)
113{
114 gus->equal_irq = 0;
115 gus->codec_flag = 0;
116 gus->max_flag = 0;
117 gus->joystick_dac = joystick_dac[dev];
118}
119
120static int __init snd_gusclassic_probe(int dev)
121{
122 static int possible_irqs[] = {5, 11, 12, 9, 7, 15, 3, 4, -1};
123 static int possible_dmas[] = {5, 6, 7, 1, 3, -1};
124 int xirq, xdma1, xdma2;
125 snd_card_t *card;
126 struct snd_gusclassic *guscard;
127 snd_gus_card_t *gus = NULL;
128 int err;
129
130 card = snd_card_new(index[dev], id[dev], THIS_MODULE, 0);
131 if (card == NULL)
132 return -ENOMEM;
133 guscard = (struct snd_gusclassic *)card->private_data;
134 if (pcm_channels[dev] < 2)
135 pcm_channels[dev] = 2;
136
137 xirq = irq[dev];
138 if (xirq == SNDRV_AUTO_IRQ) {
139 if ((xirq = snd_legacy_find_free_irq(possible_irqs)) < 0) {
140 snd_card_free(card);
141 snd_printk("unable to find a free IRQ\n");
142 return -EBUSY;
143 }
144 }
145 xdma1 = dma1[dev];
146 if (xdma1 == SNDRV_AUTO_DMA) {
147 if ((xdma1 = snd_legacy_find_free_dma(possible_dmas)) < 0) {
148 snd_card_free(card);
149 snd_printk("unable to find a free DMA1\n");
150 return -EBUSY;
151 }
152 }
153 xdma2 = dma2[dev];
154 if (xdma2 == SNDRV_AUTO_DMA) {
155 if ((xdma2 = snd_legacy_find_free_dma(possible_dmas)) < 0) {
156 snd_card_free(card);
157 snd_printk("unable to find a free DMA2\n");
158 return -EBUSY;
159 }
160 }
161
162
163 if ((err = snd_gus_create(card,
164 port[dev],
165 xirq, xdma1, xdma2,
166 0, channels[dev], pcm_channels[dev],
167 0, &gus)) < 0) {
168 snd_card_free(card);
169 return err;
170 }
171 if ((err = snd_gusclassic_detect(gus)) < 0) {
172 snd_card_free(card);
173 return err;
174 }
175 snd_gusclassic_init(dev, gus);
176 if ((err = snd_gus_initialize(gus)) < 0) {
177 snd_card_free(card);
178 return err;
179 }
180 if (gus->max_flag || gus->ess_flag) {
181 snd_printdd("GUS Classic or ACE soundcard was not detected at 0x%lx\n", gus->gf1.port);
182 snd_card_free(card);
183 return -ENODEV;
184 }
185 if ((err = snd_gf1_new_mixer(gus)) < 0) {
186 snd_card_free(card);
187 return err;
188 }
189 if ((err = snd_gf1_pcm_new(gus, 0, 0, NULL)) < 0) {
190 snd_card_free(card);
191 return err;
192 }
193 if (!gus->ace_flag) {
194 if ((err = snd_gf1_rawmidi_new(gus, 0, NULL)) < 0) {
195 snd_card_free(card);
196 return err;
197 }
198 }
199 sprintf(card->longname + strlen(card->longname), " at 0x%lx, irq %d, dma %d", gus->gf1.port, xirq, xdma1);
200 if (dma2 >= 0)
201 sprintf(card->longname + strlen(card->longname), "&%d", xdma2);
202 if ((err = snd_card_register(card)) < 0) {
203 snd_card_free(card);
204 return err;
205 }
206 snd_gusclassic_cards[dev] = card;
207 return 0;
208}
209
210static int __init snd_gusclassic_legacy_auto_probe(unsigned long xport)
211{
212 static int dev;
213 int res;
214
215 for ( ; dev < SNDRV_CARDS; dev++) {
216 if (!enable[dev] || port[dev] != SNDRV_AUTO_PORT)
217 continue;
218 port[dev] = xport;
219 res = snd_gusclassic_probe(dev);
220 if (res < 0)
221 port[dev] = SNDRV_AUTO_PORT;
222 return res;
223 }
224 return -ENODEV;
225}
226
227static int __init alsa_card_gusclassic_init(void)
228{
229 static unsigned long possible_ports[] = {0x220, 0x230, 0x240, 0x250, 0x260, -1};
230 int dev, cards, i;
231
232 for (dev = cards = 0; dev < SNDRV_CARDS && enable[dev]; dev++) {
233 if (port[dev] == SNDRV_AUTO_PORT)
234 continue;
235 if (snd_gusclassic_probe(dev) >= 0)
236 cards++;
237 }
238 i = snd_legacy_auto_probe(possible_ports, snd_gusclassic_legacy_auto_probe);
239 if (i > 0)
240 cards += i;
241
242 if (!cards) {
243#ifdef MODULE
244 printk(KERN_ERR "GUS Classic soundcard not found or device busy\n");
245#endif
246 return -ENODEV;
247 }
248 return 0;
249}
250
251static void __exit alsa_card_gusclassic_exit(void)
252{
253 int idx;
254
255 for (idx = 0; idx < SNDRV_CARDS; idx++)
256 snd_card_free(snd_gusclassic_cards[idx]);
257}
258
259module_init(alsa_card_gusclassic_init)
260module_exit(alsa_card_gusclassic_exit)
diff --git a/sound/isa/gus/gusextreme.c b/sound/isa/gus/gusextreme.c
new file mode 100644
index 000000000000..bc6fecb18dcf
--- /dev/null
+++ b/sound/isa/gus/gusextreme.c
@@ -0,0 +1,374 @@
1/*
2 * Driver for Gravis UltraSound Extreme soundcards
3 * Copyright (c) by Jaroslav Kysela <perex@suse.cz>
4 *
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 *
20 */
21
22#include <sound/driver.h>
23#include <asm/dma.h>
24#include <linux/init.h>
25#include <linux/delay.h>
26#include <linux/time.h>
27#include <linux/moduleparam.h>
28#include <sound/core.h>
29#include <sound/gus.h>
30#include <sound/es1688.h>
31#include <sound/mpu401.h>
32#include <sound/opl3.h>
33#define SNDRV_LEGACY_AUTO_PROBE
34#define SNDRV_LEGACY_FIND_FREE_IRQ
35#define SNDRV_LEGACY_FIND_FREE_DMA
36#include <sound/initval.h>
37
38MODULE_AUTHOR("Jaroslav Kysela <perex@suse.cz>");
39MODULE_DESCRIPTION("Gravis UltraSound Extreme");
40MODULE_LICENSE("GPL");
41MODULE_SUPPORTED_DEVICE("{{Gravis,UltraSound Extreme}}");
42
43static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-MAX */
44static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* ID for this card */
45static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE; /* Enable this card */
46static long port[SNDRV_CARDS] = SNDRV_DEFAULT_PORT; /* 0x220,0x240,0x260 */
47static long gf1_port[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS) - 1] = -1}; /* 0x210,0x220,0x230,0x240,0x250,0x260,0x270 */
48static long mpu_port[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS) - 1] = -1}; /* 0x300,0x310,0x320 */
49static int irq[SNDRV_CARDS] = SNDRV_DEFAULT_IRQ; /* 5,7,9,10 */
50static int mpu_irq[SNDRV_CARDS] = SNDRV_DEFAULT_IRQ; /* 5,7,9,10 */
51static int gf1_irq[SNDRV_CARDS] = SNDRV_DEFAULT_IRQ; /* 2,3,5,9,11,12,15 */
52static int dma8[SNDRV_CARDS] = SNDRV_DEFAULT_DMA; /* 0,1,3 */
53static int dma1[SNDRV_CARDS] = SNDRV_DEFAULT_DMA;
54static int joystick_dac[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 29};
55 /* 0 to 31, (0.59V-4.52V or 0.389V-2.98V) */
56static int channels[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 24};
57static int pcm_channels[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 2};
58
59module_param_array(index, int, NULL, 0444);
60MODULE_PARM_DESC(index, "Index value for GUS Extreme soundcard.");
61module_param_array(id, charp, NULL, 0444);
62MODULE_PARM_DESC(id, "ID string for GUS Extreme soundcard.");
63module_param_array(enable, bool, NULL, 0444);
64MODULE_PARM_DESC(enable, "Enable GUS Extreme soundcard.");
65module_param_array(port, long, NULL, 0444);
66MODULE_PARM_DESC(port, "Port # for GUS Extreme driver.");
67module_param_array(gf1_port, long, NULL, 0444);
68MODULE_PARM_DESC(gf1_port, "GF1 port # for GUS Extreme driver (optional).");
69module_param_array(mpu_port, long, NULL, 0444);
70MODULE_PARM_DESC(mpu_port, "MPU-401 port # for GUS Extreme driver.");
71module_param_array(irq, int, NULL, 0444);
72MODULE_PARM_DESC(irq, "IRQ # for GUS Extreme driver.");
73module_param_array(mpu_irq, int, NULL, 0444);
74MODULE_PARM_DESC(mpu_irq, "MPU-401 IRQ # for GUS Extreme driver.");
75module_param_array(gf1_irq, int, NULL, 0444);
76MODULE_PARM_DESC(gf1_irq, "GF1 IRQ # for GUS Extreme driver.");
77module_param_array(dma8, int, NULL, 0444);
78MODULE_PARM_DESC(dma8, "8-bit DMA # for GUS Extreme driver.");
79module_param_array(dma1, int, NULL, 0444);
80MODULE_PARM_DESC(dma1, "GF1 DMA # for GUS Extreme driver.");
81module_param_array(joystick_dac, int, NULL, 0444);
82MODULE_PARM_DESC(joystick_dac, "Joystick DAC level 0.59V-4.52V or 0.389V-2.98V for GUS Extreme driver.");
83module_param_array(channels, int, NULL, 0444);
84MODULE_PARM_DESC(channels, "GF1 channels for GUS Extreme driver.");
85module_param_array(pcm_channels, int, NULL, 0444);
86MODULE_PARM_DESC(pcm_channels, "Reserved PCM channels for GUS Extreme driver.");
87
88static snd_card_t *snd_gusextreme_cards[SNDRV_CARDS] = SNDRV_DEFAULT_PTR;
89
90
91static int __init snd_gusextreme_detect(int dev,
92 snd_card_t * card,
93 snd_gus_card_t * gus,
94 es1688_t *es1688)
95{
96 unsigned long flags;
97
98 /*
99 * This is main stuff - enable access to GF1 chip...
100 * I'm not sure, if this will work for card which have
101 * ES1688 chip in another place than 0x220.
102 *
103 * I used reverse-engineering in DOSEMU. [--jk]
104 *
105 * ULTRINIT.EXE:
106 * 0x230 = 0,2,3
107 * 0x240 = 2,0,1
108 * 0x250 = 2,0,3
109 * 0x260 = 2,2,1
110 */
111
112 spin_lock_irqsave(&es1688->mixer_lock, flags);
113 snd_es1688_mixer_write(es1688, 0x40, 0x0b); /* don't change!!! */
114 spin_unlock_irqrestore(&es1688->mixer_lock, flags);
115 spin_lock_irqsave(&es1688->reg_lock, flags);
116 outb(gf1_port[dev] & 0x040 ? 2 : 0, ES1688P(es1688, INIT1));
117 outb(0, 0x201);
118 outb(gf1_port[dev] & 0x020 ? 2 : 0, ES1688P(es1688, INIT1));
119 outb(0, 0x201);
120 outb(gf1_port[dev] & 0x010 ? 3 : 1, ES1688P(es1688, INIT1));
121 spin_unlock_irqrestore(&es1688->reg_lock, flags);
122
123 udelay(100);
124
125 snd_gf1_i_write8(gus, SNDRV_GF1_GB_RESET, 0); /* reset GF1 */
126#ifdef CONFIG_SND_DEBUG_DETECT
127 {
128 unsigned char d;
129
130 if (((d = snd_gf1_i_look8(gus, SNDRV_GF1_GB_RESET)) & 0x07) != 0) {
131 snd_printk("[0x%lx] check 1 failed - 0x%x\n", gus->gf1.port, d);
132 return -EIO;
133 }
134 }
135#else
136 if ((snd_gf1_i_look8(gus, SNDRV_GF1_GB_RESET) & 0x07) != 0)
137 return -EIO;
138#endif
139 udelay(160);
140 snd_gf1_i_write8(gus, SNDRV_GF1_GB_RESET, 1); /* release reset */
141 udelay(160);
142#ifdef CONFIG_SND_DEBUG_DETECT
143 {
144 unsigned char d;
145
146 if (((d = snd_gf1_i_look8(gus, SNDRV_GF1_GB_RESET)) & 0x07) != 1) {
147 snd_printk("[0x%lx] check 2 failed - 0x%x\n", gus->gf1.port, d);
148 return -EIO;
149 }
150 }
151#else
152 if ((snd_gf1_i_look8(gus, SNDRV_GF1_GB_RESET) & 0x07) != 1)
153 return -EIO;
154#endif
155
156 return 0;
157}
158
159static void __init snd_gusextreme_init(int dev, snd_gus_card_t * gus)
160{
161 gus->joystick_dac = joystick_dac[dev];
162}
163
164static int __init snd_gusextreme_mixer(es1688_t *chip)
165{
166 snd_card_t *card = chip->card;
167 snd_ctl_elem_id_t id1, id2;
168 int err;
169
170 memset(&id1, 0, sizeof(id1));
171 memset(&id2, 0, sizeof(id2));
172 id1.iface = id2.iface = SNDRV_CTL_ELEM_IFACE_MIXER;
173 /* reassign AUX to SYNTHESIZER */
174 strcpy(id1.name, "Aux Playback Volume");
175 strcpy(id2.name, "Synth Playback Volume");
176 if ((err = snd_ctl_rename_id(card, &id1, &id2)) < 0)
177 return err;
178 /* reassign Master Playback Switch to Synth Playback Switch */
179 strcpy(id1.name, "Master Playback Switch");
180 strcpy(id2.name, "Synth Playback Switch");
181 if ((err = snd_ctl_rename_id(card, &id1, &id2)) < 0)
182 return err;
183 return 0;
184}
185
186static int __init snd_gusextreme_probe(int dev)
187{
188 static int possible_ess_irqs[] = {5, 9, 10, 7, -1};
189 static int possible_ess_dmas[] = {1, 3, 0, -1};
190 static int possible_gf1_irqs[] = {5, 11, 12, 9, 7, 15, 3, -1};
191 static int possible_gf1_dmas[] = {5, 6, 7, 1, 3, -1};
192 int xgf1_irq, xgf1_dma, xess_irq, xmpu_irq, xess_dma;
193 snd_card_t *card;
194 struct snd_gusextreme *acard;
195 snd_gus_card_t *gus;
196 es1688_t *es1688;
197 opl3_t *opl3;
198 int err;
199
200 card = snd_card_new(index[dev], id[dev], THIS_MODULE, 0);
201 if (card == NULL)
202 return -ENOMEM;
203 acard = (struct snd_gusextreme *)card->private_data;
204
205 xgf1_irq = gf1_irq[dev];
206 if (xgf1_irq == SNDRV_AUTO_IRQ) {
207 if ((xgf1_irq = snd_legacy_find_free_irq(possible_gf1_irqs)) < 0) {
208 snd_printk("unable to find a free IRQ for GF1\n");
209 err = -EBUSY;
210 goto out;
211 }
212 }
213 xess_irq = irq[dev];
214 if (xess_irq == SNDRV_AUTO_IRQ) {
215 if ((xess_irq = snd_legacy_find_free_irq(possible_ess_irqs)) < 0) {
216 snd_printk("unable to find a free IRQ for ES1688\n");
217 err = -EBUSY;
218 goto out;
219 }
220 }
221 if (mpu_port[dev] == SNDRV_AUTO_PORT)
222 mpu_port[dev] = 0;
223 xmpu_irq = mpu_irq[dev];
224 if (xmpu_irq > 15)
225 xmpu_irq = -1;
226 xgf1_dma = dma1[dev];
227 if (xgf1_dma == SNDRV_AUTO_DMA) {
228 if ((xgf1_dma = snd_legacy_find_free_dma(possible_gf1_dmas)) < 0) {
229 snd_printk("unable to find a free DMA for GF1\n");
230 err = -EBUSY;
231 goto out;
232 }
233 }
234 xess_dma = dma8[dev];
235 if (xess_dma == SNDRV_AUTO_DMA) {
236 if ((xess_dma = snd_legacy_find_free_dma(possible_ess_dmas)) < 0) {
237 snd_printk("unable to find a free DMA for ES1688\n");
238 err = -EBUSY;
239 goto out;
240 }
241 }
242
243 if ((err = snd_es1688_create(card, port[dev], mpu_port[dev],
244 xess_irq, xmpu_irq, xess_dma,
245 ES1688_HW_1688, &es1688)) < 0)
246 goto out;
247 if (gf1_port[dev] < 0)
248 gf1_port[dev] = port[dev] + 0x20;
249 if ((err = snd_gus_create(card,
250 gf1_port[dev],
251 xgf1_irq,
252 xgf1_dma,
253 -1,
254 0, channels[dev],
255 pcm_channels[dev], 0,
256 &gus)) < 0)
257 goto out;
258
259 if ((err = snd_gusextreme_detect(dev, card, gus, es1688)) < 0)
260 goto out;
261
262 snd_gusextreme_init(dev, gus);
263 if ((err = snd_gus_initialize(gus)) < 0)
264 goto out;
265
266 if (!gus->ess_flag) {
267 snd_printdd("GUS Extreme soundcard was not detected at 0x%lx\n", gus->gf1.port);
268 err = -ENODEV;
269 goto out;
270 }
271 if ((err = snd_es1688_pcm(es1688, 0, NULL)) < 0)
272 goto out;
273
274 if ((err = snd_es1688_mixer(es1688)) < 0)
275 goto out;
276
277 snd_component_add(card, "ES1688");
278 if (pcm_channels[dev] > 0) {
279 if ((err = snd_gf1_pcm_new(gus, 1, 1, NULL)) < 0)
280 goto out;
281 }
282 if ((err = snd_gf1_new_mixer(gus)) < 0)
283 goto out;
284
285 if ((err = snd_gusextreme_mixer(es1688)) < 0)
286 goto out;
287
288 if (snd_opl3_create(card, es1688->port, es1688->port + 2,
289 OPL3_HW_OPL3, 0, &opl3) < 0) {
290 printk(KERN_ERR "gusextreme: opl3 not detected at 0x%lx\n", es1688->port);
291 } else {
292 if ((err = snd_opl3_hwdep_new(opl3, 0, 2, NULL)) < 0)
293 goto out;
294 }
295
296 if (es1688->mpu_port >= 0x300 &&
297 (err = snd_mpu401_uart_new(card, 0, MPU401_HW_ES1688,
298 es1688->mpu_port, 0,
299 xmpu_irq,
300 SA_INTERRUPT,
301 NULL)) < 0)
302 goto out;
303
304 sprintf(card->longname, "Gravis UltraSound Extreme at 0x%lx, irq %i&%i, dma %i&%i",
305 es1688->port, xgf1_irq, xess_irq, xgf1_dma, xess_dma);
306 if ((err = snd_card_register(card)) < 0)
307 goto out;
308
309 snd_gusextreme_cards[dev] = card;
310 return 0;
311
312 out:
313 snd_card_free(card);
314 return err;
315}
316
317static int __init snd_gusextreme_legacy_auto_probe(unsigned long xport)
318{
319 static int dev;
320 int res;
321
322 for ( ; dev < SNDRV_CARDS; dev++) {
323 if (!enable[dev] || port[dev] != SNDRV_AUTO_PORT)
324 continue;
325 port[dev] = xport;
326 res = snd_gusextreme_probe(dev);
327 if (res < 0)
328 port[dev] = SNDRV_AUTO_PORT;
329 return res;
330 }
331 return -ENODEV;
332}
333
334static int __init alsa_card_gusextreme_init(void)
335{
336 static unsigned long possible_ports[] = {0x220, 0x240, 0x260, -1};
337 int dev, cards, i;
338
339 for (dev = cards = 0; dev < SNDRV_CARDS && enable[dev] > 0; dev++) {
340 if (port[dev] == SNDRV_AUTO_PORT)
341 continue;
342 if (snd_gusextreme_probe(dev) >= 0)
343 cards++;
344 }
345 i = snd_legacy_auto_probe(possible_ports, snd_gusextreme_legacy_auto_probe);
346 if (i > 0)
347 cards += i;
348
349 if (!cards) {
350#ifdef MODULE
351 printk(KERN_ERR "GUS Extreme soundcard not found or device busy\n");
352#endif
353 return -ENODEV;
354 }
355 return 0;
356}
357
358static void __exit alsa_card_gusextreme_exit(void)
359{
360 int idx;
361 snd_card_t *card;
362 struct snd_gusextreme *acard;
363
364 for (idx = 0; idx < SNDRV_CARDS; idx++) {
365 card = snd_gusextreme_cards[idx];
366 if (card == NULL)
367 continue;
368 acard = (struct snd_gusextreme *)card->private_data;
369 snd_card_free(snd_gusextreme_cards[idx]);
370 }
371}
372
373module_init(alsa_card_gusextreme_init)
374module_exit(alsa_card_gusextreme_exit)
diff --git a/sound/isa/gus/gusmax.c b/sound/isa/gus/gusmax.c
new file mode 100644
index 000000000000..400ff34710fb
--- /dev/null
+++ b/sound/isa/gus/gusmax.c
@@ -0,0 +1,400 @@
1/*
2 * Driver for Gravis UltraSound MAX soundcard
3 * Copyright (c) by Jaroslav Kysela <perex@suse.cz>
4 *
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 *
20 */
21
22#include <sound/driver.h>
23#include <asm/dma.h>
24#include <linux/init.h>
25#include <linux/delay.h>
26#include <linux/time.h>
27#include <linux/moduleparam.h>
28#include <sound/core.h>
29#include <sound/gus.h>
30#include <sound/cs4231.h>
31#define SNDRV_LEGACY_AUTO_PROBE
32#define SNDRV_LEGACY_FIND_FREE_IRQ
33#define SNDRV_LEGACY_FIND_FREE_DMA
34#include <sound/initval.h>
35
36MODULE_AUTHOR("Jaroslav Kysela <perex@suse.cz>");
37MODULE_DESCRIPTION("Gravis UltraSound MAX");
38MODULE_LICENSE("GPL");
39MODULE_SUPPORTED_DEVICE("{{Gravis,UltraSound MAX}}");
40
41static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-MAX */
42static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* ID for this card */
43static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE; /* Enable this card */
44static long port[SNDRV_CARDS] = SNDRV_DEFAULT_PORT; /* 0x220,0x230,0x240,0x250,0x260 */
45static int irq[SNDRV_CARDS] = SNDRV_DEFAULT_IRQ; /* 2,3,5,9,11,12,15 */
46static int dma1[SNDRV_CARDS] = SNDRV_DEFAULT_DMA; /* 1,3,5,6,7 */
47static int dma2[SNDRV_CARDS] = SNDRV_DEFAULT_DMA; /* 1,3,5,6,7 */
48static int joystick_dac[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 29};
49 /* 0 to 31, (0.59V-4.52V or 0.389V-2.98V) */
50static int channels[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 24};
51static int pcm_channels[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 2};
52
53module_param_array(index, int, NULL, 0444);
54MODULE_PARM_DESC(index, "Index value for GUS MAX soundcard.");
55module_param_array(id, charp, NULL, 0444);
56MODULE_PARM_DESC(id, "ID string for GUS MAX soundcard.");
57module_param_array(enable, bool, NULL, 0444);
58MODULE_PARM_DESC(enable, "Enable GUS MAX soundcard.");
59module_param_array(port, long, NULL, 0444);
60MODULE_PARM_DESC(port, "Port # for GUS MAX driver.");
61module_param_array(irq, int, NULL, 0444);
62MODULE_PARM_DESC(irq, "IRQ # for GUS MAX driver.");
63module_param_array(dma1, int, NULL, 0444);
64MODULE_PARM_DESC(dma1, "DMA1 # for GUS MAX driver.");
65module_param_array(dma2, int, NULL, 0444);
66MODULE_PARM_DESC(dma2, "DMA2 # for GUS MAX driver.");
67module_param_array(joystick_dac, int, NULL, 0444);
68MODULE_PARM_DESC(joystick_dac, "Joystick DAC level 0.59V-4.52V or 0.389V-2.98V for GUS MAX driver.");
69module_param_array(channels, int, NULL, 0444);
70MODULE_PARM_DESC(channels, "Used GF1 channels for GUS MAX driver.");
71module_param_array(pcm_channels, int, NULL, 0444);
72MODULE_PARM_DESC(pcm_channels, "Reserved PCM channels for GUS MAX driver.");
73
74struct snd_gusmax {
75 int irq;
76 snd_card_t *card;
77 snd_gus_card_t *gus;
78 cs4231_t *cs4231;
79 unsigned short gus_status_reg;
80 unsigned short pcm_status_reg;
81};
82
83static snd_card_t *snd_gusmax_cards[SNDRV_CARDS] = SNDRV_DEFAULT_PTR;
84
85
86static int __init snd_gusmax_detect(snd_gus_card_t * gus)
87{
88 snd_gf1_i_write8(gus, SNDRV_GF1_GB_RESET, 0); /* reset GF1 */
89#ifdef CONFIG_SND_DEBUG_DETECT
90 {
91 unsigned char d;
92
93 if (((d = snd_gf1_i_look8(gus, SNDRV_GF1_GB_RESET)) & 0x07) != 0) {
94 snd_printk("[0x%lx] check 1 failed - 0x%x\n", gus->gf1.port, d);
95 return -ENODEV;
96 }
97 }
98#else
99 if ((snd_gf1_i_look8(gus, SNDRV_GF1_GB_RESET) & 0x07) != 0)
100 return -ENODEV;
101#endif
102 udelay(160);
103 snd_gf1_i_write8(gus, SNDRV_GF1_GB_RESET, 1); /* release reset */
104 udelay(160);
105#ifdef CONFIG_SND_DEBUG_DETECT
106 {
107 unsigned char d;
108
109 if (((d = snd_gf1_i_look8(gus, SNDRV_GF1_GB_RESET)) & 0x07) != 1) {
110 snd_printk("[0x%lx] check 2 failed - 0x%x\n", gus->gf1.port, d);
111 return -ENODEV;
112 }
113 }
114#else
115 if ((snd_gf1_i_look8(gus, SNDRV_GF1_GB_RESET) & 0x07) != 1)
116 return -ENODEV;
117#endif
118 return 0;
119}
120
121static irqreturn_t snd_gusmax_interrupt(int irq, void *dev_id, struct pt_regs *regs)
122{
123 struct snd_gusmax *maxcard = (struct snd_gusmax *) dev_id;
124 int loop, max = 5;
125 int handled = 0;
126
127 do {
128 loop = 0;
129 if (inb(maxcard->gus_status_reg)) {
130 handled = 1;
131 snd_gus_interrupt(irq, maxcard->gus, regs);
132 loop++;
133 }
134 if (inb(maxcard->pcm_status_reg) & 0x01) { /* IRQ bit is set? */
135 handled = 1;
136 snd_cs4231_interrupt(irq, maxcard->cs4231, regs);
137 loop++;
138 }
139 } while (loop && --max > 0);
140 return IRQ_RETVAL(handled);
141}
142
143static void __init snd_gusmax_init(int dev, snd_card_t * card, snd_gus_card_t * gus)
144{
145 gus->equal_irq = 1;
146 gus->codec_flag = 1;
147 gus->joystick_dac = joystick_dac[dev];
148 /* init control register */
149 gus->max_cntrl_val = (gus->gf1.port >> 4) & 0x0f;
150 if (gus->gf1.dma1 > 3)
151 gus->max_cntrl_val |= 0x10;
152 if (gus->gf1.dma2 > 3)
153 gus->max_cntrl_val |= 0x20;
154 gus->max_cntrl_val |= 0x40;
155 outb(gus->max_cntrl_val, GUSP(gus, MAXCNTRLPORT));
156}
157
158#define CS4231_PRIVATE( left, right, shift, mute ) \
159 ((left << 24)|(right << 16)|(shift<<8)|mute)
160
161static int __init snd_gusmax_mixer(cs4231_t *chip)
162{
163 snd_card_t *card = chip->card;
164 snd_ctl_elem_id_t id1, id2;
165 int err;
166
167 memset(&id1, 0, sizeof(id1));
168 memset(&id2, 0, sizeof(id2));
169 id1.iface = id2.iface = SNDRV_CTL_ELEM_IFACE_MIXER;
170 /* reassign AUXA to SYNTHESIZER */
171 strcpy(id1.name, "Aux Playback Switch");
172 strcpy(id2.name, "Synth Playback Switch");
173 if ((err = snd_ctl_rename_id(card, &id1, &id2)) < 0)
174 return err;
175 strcpy(id1.name, "Aux Playback Volume");
176 strcpy(id2.name, "Synth Playback Volume");
177 if ((err = snd_ctl_rename_id(card, &id1, &id2)) < 0)
178 return err;
179 /* reassign AUXB to CD */
180 strcpy(id1.name, "Aux Playback Switch"); id1.index = 1;
181 strcpy(id2.name, "CD Playback Switch");
182 if ((err = snd_ctl_rename_id(card, &id1, &id2)) < 0)
183 return err;
184 strcpy(id1.name, "Aux Playback Volume");
185 strcpy(id2.name, "CD Playback Volume");
186 if ((err = snd_ctl_rename_id(card, &id1, &id2)) < 0)
187 return err;
188#if 0
189 /* reassign Mono Input to MIC */
190 if (snd_mixer_group_rename(mixer,
191 SNDRV_MIXER_IN_MONO, 0,
192 SNDRV_MIXER_IN_MIC, 0) < 0)
193 goto __error;
194 if (snd_mixer_elem_rename(mixer,
195 SNDRV_MIXER_IN_MONO, 0, SNDRV_MIXER_ETYPE_INPUT,
196 SNDRV_MIXER_IN_MIC, 0) < 0)
197 goto __error;
198 if (snd_mixer_elem_rename(mixer,
199 "Mono Capture Volume", 0, SNDRV_MIXER_ETYPE_VOLUME1,
200 "Mic Capture Volume", 0) < 0)
201 goto __error;
202 if (snd_mixer_elem_rename(mixer,
203 "Mono Capture Switch", 0, SNDRV_MIXER_ETYPE_SWITCH1,
204 "Mic Capture Switch", 0) < 0)
205 goto __error;
206#endif
207 return 0;
208}
209
210static void snd_gusmax_free(snd_card_t *card)
211{
212 struct snd_gusmax *maxcard = (struct snd_gusmax *)card->private_data;
213
214 if (maxcard == NULL)
215 return;
216 if (maxcard->irq >= 0)
217 free_irq(maxcard->irq, (void *)maxcard);
218}
219
220static int __init snd_gusmax_probe(int dev)
221{
222 static int possible_irqs[] = {5, 11, 12, 9, 7, 15, 3, -1};
223 static int possible_dmas[] = {5, 6, 7, 1, 3, -1};
224 int xirq, xdma1, xdma2, err;
225 snd_card_t *card;
226 snd_gus_card_t *gus = NULL;
227 cs4231_t *cs4231;
228 struct snd_gusmax *maxcard;
229
230 card = snd_card_new(index[dev], id[dev], THIS_MODULE,
231 sizeof(struct snd_gusmax));
232 if (card == NULL)
233 return -ENOMEM;
234 card->private_free = snd_gusmax_free;
235 maxcard = (struct snd_gusmax *)card->private_data;
236 maxcard->card = card;
237 maxcard->irq = -1;
238
239 xirq = irq[dev];
240 if (xirq == SNDRV_AUTO_IRQ) {
241 if ((xirq = snd_legacy_find_free_irq(possible_irqs)) < 0) {
242 snd_card_free(card);
243 snd_printk("unable to find a free IRQ\n");
244 return -EBUSY;
245 }
246 }
247 xdma1 = dma1[dev];
248 if (xdma1 == SNDRV_AUTO_DMA) {
249 if ((xdma1 = snd_legacy_find_free_dma(possible_dmas)) < 0) {
250 snd_card_free(card);
251 snd_printk("unable to find a free DMA1\n");
252 return -EBUSY;
253 }
254 }
255 xdma2 = dma2[dev];
256 if (xdma2 == SNDRV_AUTO_DMA) {
257 if ((xdma2 = snd_legacy_find_free_dma(possible_dmas)) < 0) {
258 snd_card_free(card);
259 snd_printk("unable to find a free DMA2\n");
260 return -EBUSY;
261 }
262 }
263
264 if ((err = snd_gus_create(card,
265 port[dev],
266 -xirq, xdma1, xdma2,
267 0, channels[dev],
268 pcm_channels[dev],
269 0, &gus)) < 0) {
270 snd_card_free(card);
271 return err;
272 }
273 if ((err = snd_gusmax_detect(gus)) < 0) {
274 snd_card_free(card);
275 return err;
276 }
277 maxcard->gus_status_reg = gus->gf1.reg_irqstat;
278 maxcard->pcm_status_reg = gus->gf1.port + 0x10c + 2;
279 snd_gusmax_init(dev, card, gus);
280 if ((err = snd_gus_initialize(gus)) < 0) {
281 snd_card_free(card);
282 return err;
283 }
284 if (!gus->max_flag) {
285 printk(KERN_ERR "GUS MAX soundcard was not detected at 0x%lx\n", gus->gf1.port);
286 snd_card_free(card);
287 return -ENODEV;
288 }
289
290 if (request_irq(xirq, snd_gusmax_interrupt, SA_INTERRUPT, "GUS MAX", (void *)maxcard)) {
291 snd_card_free(card);
292 printk(KERN_ERR "gusmax: unable to grab IRQ %d\n", xirq);
293 return -EBUSY;
294 }
295 maxcard->irq = xirq;
296
297 if ((err = snd_cs4231_create(card,
298 gus->gf1.port + 0x10c, -1, xirq,
299 xdma2 < 0 ? xdma1 : xdma2, xdma1,
300 CS4231_HW_DETECT,
301 CS4231_HWSHARE_IRQ |
302 CS4231_HWSHARE_DMA1 |
303 CS4231_HWSHARE_DMA2,
304 &cs4231)) < 0) {
305 snd_card_free(card);
306 return err;
307 }
308 if ((err = snd_cs4231_pcm(cs4231, 0, NULL)) < 0) {
309 snd_card_free(card);
310 return err;
311 }
312 if ((err = snd_cs4231_mixer(cs4231)) < 0) {
313 snd_card_free(card);
314 return err;
315 }
316 if ((err = snd_cs4231_timer(cs4231, 2, NULL)) < 0) {
317 snd_card_free(card);
318 return err;
319 }
320 if (pcm_channels[dev] > 0) {
321 if ((err = snd_gf1_pcm_new(gus, 1, 1, NULL)) < 0) {
322 snd_card_free(card);
323 return err;
324 }
325 }
326 if ((err = snd_gusmax_mixer(cs4231)) < 0) {
327 snd_card_free(card);
328 return err;
329 }
330
331 if ((err = snd_gf1_rawmidi_new(gus, 0, NULL)) < 0) {
332 snd_card_free(card);
333 return err;
334 }
335
336 sprintf(card->longname + strlen(card->longname), " at 0x%lx, irq %i, dma %i", gus->gf1.port, xirq, xdma1);
337 if (xdma2 >= 0)
338 sprintf(card->longname + strlen(card->longname), "&%i", xdma2);
339 if ((err = snd_card_register(card)) < 0) {
340 snd_card_free(card);
341 return err;
342 }
343
344 maxcard->gus = gus;
345 maxcard->cs4231 = cs4231;
346 snd_gusmax_cards[dev] = card;
347 return 0;
348}
349
350static int __init snd_gusmax_legacy_auto_probe(unsigned long xport)
351{
352 static int dev;
353 int res;
354
355 for ( ; dev < SNDRV_CARDS; dev++) {
356 if (!enable[dev] || port[dev] != SNDRV_AUTO_PORT)
357 continue;
358 port[dev] = xport;
359 res = snd_gusmax_probe(dev);
360 if (res < 0)
361 port[dev] = SNDRV_AUTO_PORT;
362 return res;
363 }
364 return -ENODEV;
365}
366
367static int __init alsa_card_gusmax_init(void)
368{
369 static unsigned long possible_ports[] = {0x220, 0x230, 0x240, 0x250, 0x260, -1};
370 int dev, cards, i;
371
372 for (dev = cards = 0; dev < SNDRV_CARDS && enable[dev] > 0; dev++) {
373 if (port[dev] == SNDRV_AUTO_PORT)
374 continue;
375 if (snd_gusmax_probe(dev) >= 0)
376 cards++;
377 }
378 i = snd_legacy_auto_probe(possible_ports, snd_gusmax_legacy_auto_probe);
379 if (i > 0)
380 cards += i;
381
382 if (!cards) {
383#ifdef MODULE
384 printk(KERN_ERR "GUS MAX soundcard not found or device busy\n");
385#endif
386 return -ENODEV;
387 }
388 return 0;
389}
390
391static void __exit alsa_card_gusmax_exit(void)
392{
393 int idx;
394
395 for (idx = 0; idx < SNDRV_CARDS; idx++)
396 snd_card_free(snd_gusmax_cards[idx]);
397}
398
399module_init(alsa_card_gusmax_init)
400module_exit(alsa_card_gusmax_exit)
diff --git a/sound/isa/gus/interwave-stb.c b/sound/isa/gus/interwave-stb.c
new file mode 100644
index 000000000000..dbe4f48a9846
--- /dev/null
+++ b/sound/isa/gus/interwave-stb.c
@@ -0,0 +1,2 @@
1#define SNDRV_STB
2#include "interwave.c"
diff --git a/sound/isa/gus/interwave.c b/sound/isa/gus/interwave.c
new file mode 100644
index 000000000000..46e867daba6a
--- /dev/null
+++ b/sound/isa/gus/interwave.c
@@ -0,0 +1,969 @@
1/*
2 * Driver for AMD InterWave soundcard
3 * Copyright (c) by Jaroslav Kysela <perex@suse.cz>
4 *
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 *
20 * 1999/07/22 Erik Inge Bolso <knan@mo.himolde.no>
21 * * mixer group handlers
22 *
23 */
24
25#include <sound/driver.h>
26#include <asm/dma.h>
27#include <linux/delay.h>
28#include <linux/init.h>
29#include <linux/slab.h>
30#include <linux/pnp.h>
31#include <linux/moduleparam.h>
32#include <sound/core.h>
33#include <sound/gus.h>
34#include <sound/cs4231.h>
35#ifdef SNDRV_STB
36#include <sound/tea6330t.h>
37#endif
38#define SNDRV_LEGACY_AUTO_PROBE
39#define SNDRV_LEGACY_FIND_FREE_IRQ
40#define SNDRV_LEGACY_FIND_FREE_DMA
41#include <sound/initval.h>
42
43MODULE_AUTHOR("Jaroslav Kysela <perex@suse.cz>");
44MODULE_LICENSE("GPL");
45#ifndef SNDRV_STB
46MODULE_DESCRIPTION("AMD InterWave");
47MODULE_SUPPORTED_DEVICE("{{Gravis,UltraSound Plug & Play},"
48 "{STB,SoundRage32},"
49 "{MED,MED3210},"
50 "{Dynasonix,Dynasonix Pro},"
51 "{Panasonic,PCA761AW}}");
52#else
53MODULE_DESCRIPTION("AMD InterWave STB with TEA6330T");
54MODULE_SUPPORTED_DEVICE("{{AMD,InterWave STB with TEA6330T}}");
55#endif
56
57static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-MAX */
58static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* ID for this card */
59static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_ISAPNP; /* Enable this card */
60#ifdef CONFIG_PNP
61static int isapnp[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 1};
62#endif
63static long port[SNDRV_CARDS] = SNDRV_DEFAULT_PORT; /* 0x210,0x220,0x230,0x240,0x250,0x260 */
64#ifdef SNDRV_STB
65static long port_tc[SNDRV_CARDS] = SNDRV_DEFAULT_PORT; /* 0x350,0x360,0x370,0x380 */
66#endif
67static int irq[SNDRV_CARDS] = SNDRV_DEFAULT_IRQ; /* 2,3,5,9,11,12,15 */
68static int dma1[SNDRV_CARDS] = SNDRV_DEFAULT_DMA; /* 0,1,3,5,6,7 */
69static int dma2[SNDRV_CARDS] = SNDRV_DEFAULT_DMA; /* 0,1,3,5,6,7 */
70static int joystick_dac[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 29};
71 /* 0 to 31, (0.59V-4.52V or 0.389V-2.98V) */
72static int midi[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 0};
73static int pcm_channels[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 2};
74static int effect[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 0};
75
76module_param_array(index, int, NULL, 0444);
77MODULE_PARM_DESC(index, "Index value for InterWave soundcard.");
78module_param_array(id, charp, NULL, 0444);
79MODULE_PARM_DESC(id, "ID string for InterWave soundcard.");
80module_param_array(enable, bool, NULL, 0444);
81MODULE_PARM_DESC(enable, "Enable InterWave soundcard.");
82#ifdef CONFIG_PNP
83module_param_array(isapnp, bool, NULL, 0444);
84MODULE_PARM_DESC(isapnp, "ISA PnP detection for specified soundcard.");
85#endif
86module_param_array(port, long, NULL, 0444);
87MODULE_PARM_DESC(port, "Port # for InterWave driver.");
88#ifdef SNDRV_STB
89module_param_array(port_tc, long, NULL, 0444);
90MODULE_PARM_DESC(port_tc, "Tone control (TEA6330T - i2c bus) port # for InterWave driver.");
91#endif
92module_param_array(irq, int, NULL, 0444);
93MODULE_PARM_DESC(irq, "IRQ # for InterWave driver.");
94module_param_array(dma1, int, NULL, 0444);
95MODULE_PARM_DESC(dma1, "DMA1 # for InterWave driver.");
96module_param_array(dma2, int, NULL, 0444);
97MODULE_PARM_DESC(dma2, "DMA2 # for InterWave driver.");
98module_param_array(joystick_dac, int, NULL, 0444);
99MODULE_PARM_DESC(joystick_dac, "Joystick DAC level 0.59V-4.52V or 0.389V-2.98V for InterWave driver.");
100module_param_array(midi, int, NULL, 0444);
101MODULE_PARM_DESC(midi, "MIDI UART enable for InterWave driver.");
102module_param_array(pcm_channels, int, NULL, 0444);
103MODULE_PARM_DESC(pcm_channels, "Reserved PCM channels for InterWave driver.");
104module_param_array(effect, int, NULL, 0444);
105MODULE_PARM_DESC(effect, "Effects enable for InterWave driver.");
106
107struct snd_interwave {
108 int irq;
109 snd_card_t *card;
110 snd_gus_card_t *gus;
111 cs4231_t *cs4231;
112#ifdef SNDRV_STB
113 struct resource *i2c_res;
114#endif
115 unsigned short gus_status_reg;
116 unsigned short pcm_status_reg;
117#ifdef CONFIG_PNP
118 struct pnp_dev *dev;
119#ifdef SNDRV_STB
120 struct pnp_dev *devtc;
121#endif
122#endif
123};
124
125static snd_card_t *snd_interwave_legacy[SNDRV_CARDS] = SNDRV_DEFAULT_PTR;
126
127#ifdef CONFIG_PNP
128
129static struct pnp_card_device_id snd_interwave_pnpids[] = {
130#ifndef SNDRV_STB
131 /* Gravis UltraSound Plug & Play */
132 { .id = "GRV0001", .devs = { { .id = "GRV0000" } } },
133 /* STB SoundRage32 */
134 { .id = "STB011a", .devs = { { .id = "STB0010" } } },
135 /* MED3210 */
136 { .id = "DXP3201", .devs = { { .id = "DXP0010" } } },
137 /* Dynasonic Pro */
138 /* This device also have CDC1117:DynaSonix Pro Audio Effects Processor */
139 { .id = "CDC1111", .devs = { { .id = "CDC1112" } } },
140 /* Panasonic PCA761AW Audio Card */
141 { .id = "ADV55ff", .devs = { { .id = "ADV0010" } } },
142 /* InterWave STB without TEA6330T */
143 { .id = "ADV550a", .devs = { { .id = "ADV0010" } } },
144#else
145 /* InterWave STB with TEA6330T */
146 { .id = "ADV550a", .devs = { { .id = "ADV0010" }, { .id = "ADV0015" } } },
147#endif
148 { .id = "" }
149};
150
151MODULE_DEVICE_TABLE(pnp_card, snd_interwave_pnpids);
152
153#endif /* CONFIG_PNP */
154
155
156#ifdef SNDRV_STB
157static void snd_interwave_i2c_setlines(snd_i2c_bus_t *bus, int ctrl, int data)
158{
159 unsigned long port = bus->private_value;
160
161#if 0
162 printk("i2c_setlines - 0x%lx <- %i,%i\n", port, ctrl, data);
163#endif
164 outb((data << 1) | ctrl, port);
165 udelay(10);
166}
167
168static int snd_interwave_i2c_getclockline(snd_i2c_bus_t *bus)
169{
170 unsigned long port = bus->private_value;
171 unsigned char res;
172
173 res = inb(port) & 1;
174#if 0
175 printk("i2c_getclockline - 0x%lx -> %i\n", port, res);
176#endif
177 return res;
178}
179
180static int snd_interwave_i2c_getdataline(snd_i2c_bus_t *bus, int ack)
181{
182 unsigned long port = bus->private_value;
183 unsigned char res;
184
185 if (ack)
186 udelay(10);
187 res = (inb(port) & 2) >> 1;
188#if 0
189 printk("i2c_getdataline - 0x%lx -> %i\n", port, res);
190#endif
191 return res;
192}
193
194static snd_i2c_bit_ops_t snd_interwave_i2c_bit_ops = {
195 .setlines = snd_interwave_i2c_setlines,
196 .getclock = snd_interwave_i2c_getclockline,
197 .getdata = snd_interwave_i2c_getdataline,
198};
199
200static int __devinit snd_interwave_detect_stb(struct snd_interwave *iwcard,
201 snd_gus_card_t * gus, int dev,
202 snd_i2c_bus_t **rbus)
203{
204 unsigned long port;
205 snd_i2c_bus_t *bus;
206 snd_card_t *card = iwcard->card;
207 char name[32];
208 int err;
209
210 *rbus = NULL;
211 port = port_tc[dev];
212 if (port == SNDRV_AUTO_PORT) {
213 port = 0x350;
214 if (gus->gf1.port == 0x250) {
215 port = 0x360;
216 }
217 while (port <= 0x380) {
218 if ((iwcard->i2c_res = request_region(port, 1, "InterWave (I2C bus)")) != NULL)
219 break;
220 port += 0x10;
221 }
222 } else {
223 iwcard->i2c_res = request_region(port, 1, "InterWave (I2C bus)");
224 }
225 if (iwcard->i2c_res == NULL) {
226 snd_printk(KERN_ERR "interwave: can't grab i2c bus port\n");
227 return -ENODEV;
228 }
229
230 sprintf(name, "InterWave-%i", card->number);
231 if ((err = snd_i2c_bus_create(card, name, NULL, &bus)) < 0)
232 return err;
233 bus->private_value = port;
234 bus->hw_ops.bit = &snd_interwave_i2c_bit_ops;
235 if ((err = snd_tea6330t_detect(bus, 0)) < 0)
236 return err;
237 *rbus = bus;
238 return 0;
239}
240#endif
241
242static int __devinit snd_interwave_detect(struct snd_interwave *iwcard,
243 snd_gus_card_t * gus,
244 int dev
245#ifdef SNDRV_STB
246 , snd_i2c_bus_t **rbus
247#endif
248 )
249{
250 unsigned long flags;
251 unsigned char rev1, rev2;
252
253 snd_gf1_i_write8(gus, SNDRV_GF1_GB_RESET, 0); /* reset GF1 */
254#ifdef CONFIG_SND_DEBUG_DETECT
255 {
256 int d;
257
258 if (((d = snd_gf1_i_look8(gus, SNDRV_GF1_GB_RESET)) & 0x07) != 0) {
259 snd_printk("[0x%lx] check 1 failed - 0x%x\n", gus->gf1.port, d);
260 return -ENODEV;
261 }
262 }
263#else
264 if ((snd_gf1_i_look8(gus, SNDRV_GF1_GB_RESET) & 0x07) != 0)
265 return -ENODEV;
266#endif
267 udelay(160);
268 snd_gf1_i_write8(gus, SNDRV_GF1_GB_RESET, 1); /* release reset */
269 udelay(160);
270#ifdef CONFIG_SND_DEBUG_DETECT
271 {
272 int d;
273
274 if (((d = snd_gf1_i_look8(gus, SNDRV_GF1_GB_RESET)) & 0x07) != 1) {
275 snd_printk("[0x%lx] check 2 failed - 0x%x\n", gus->gf1.port, d);
276 return -ENODEV;
277 }
278 }
279#else
280 if ((snd_gf1_i_look8(gus, SNDRV_GF1_GB_RESET) & 0x07) != 1)
281 return -ENODEV;
282#endif
283
284 spin_lock_irqsave(&gus->reg_lock, flags);
285 rev1 = snd_gf1_look8(gus, SNDRV_GF1_GB_VERSION_NUMBER);
286 snd_gf1_write8(gus, SNDRV_GF1_GB_VERSION_NUMBER, ~rev1);
287 rev2 = snd_gf1_look8(gus, SNDRV_GF1_GB_VERSION_NUMBER);
288 snd_gf1_write8(gus, SNDRV_GF1_GB_VERSION_NUMBER, rev1);
289 spin_unlock_irqrestore(&gus->reg_lock, flags);
290 snd_printdd("[0x%lx] InterWave check - rev1=0x%x, rev2=0x%x\n", gus->gf1.port, rev1, rev2);
291 if ((rev1 & 0xf0) == (rev2 & 0xf0) &&
292 (rev1 & 0x0f) != (rev2 & 0x0f)) {
293 snd_printdd("[0x%lx] InterWave check - passed\n", gus->gf1.port);
294 gus->interwave = 1;
295 strcpy(gus->card->shortname, "AMD InterWave");
296 gus->revision = rev1 >> 4;
297#ifndef SNDRV_STB
298 return 0; /* ok.. We have an InterWave board */
299#else
300 return snd_interwave_detect_stb(iwcard, gus, dev, rbus);
301#endif
302 }
303 snd_printdd("[0x%lx] InterWave check - failed\n", gus->gf1.port);
304 return -ENODEV;
305}
306
307static irqreturn_t snd_interwave_interrupt(int irq, void *dev_id, struct pt_regs *regs)
308{
309 struct snd_interwave *iwcard = (struct snd_interwave *) dev_id;
310 int loop, max = 5;
311 int handled = 0;
312
313 do {
314 loop = 0;
315 if (inb(iwcard->gus_status_reg)) {
316 handled = 1;
317 snd_gus_interrupt(irq, iwcard->gus, regs);
318 loop++;
319 }
320 if (inb(iwcard->pcm_status_reg) & 0x01) { /* IRQ bit is set? */
321 handled = 1;
322 snd_cs4231_interrupt(irq, iwcard->cs4231, regs);
323 loop++;
324 }
325 } while (loop && --max > 0);
326 return IRQ_RETVAL(handled);
327}
328
329static void __devinit snd_interwave_reset(snd_gus_card_t * gus)
330{
331 snd_gf1_write8(gus, SNDRV_GF1_GB_RESET, 0x00);
332 udelay(160);
333 snd_gf1_write8(gus, SNDRV_GF1_GB_RESET, 0x01);
334 udelay(160);
335}
336
337static void __devinit snd_interwave_bank_sizes(snd_gus_card_t * gus, int *sizes)
338{
339 unsigned int idx;
340 unsigned int local;
341 unsigned char d;
342
343 for (idx = 0; idx < 4; idx++) {
344 sizes[idx] = 0;
345 d = 0x55;
346 for (local = idx << 22;
347 local < (idx << 22) + 0x400000;
348 local += 0x40000, d++) {
349 snd_gf1_poke(gus, local, d);
350 snd_gf1_poke(gus, local + 1, d + 1);
351#if 0
352 printk("d = 0x%x, local = 0x%x, local + 1 = 0x%x, idx << 22 = 0x%x\n",
353 d,
354 snd_gf1_peek(gus, local),
355 snd_gf1_peek(gus, local + 1),
356 snd_gf1_peek(gus, idx << 22));
357#endif
358 if (snd_gf1_peek(gus, local) != d ||
359 snd_gf1_peek(gus, local + 1) != d + 1 ||
360 snd_gf1_peek(gus, idx << 22) != 0x55)
361 break;
362 sizes[idx]++;
363 }
364 }
365#if 0
366 printk("sizes: %i %i %i %i\n", sizes[0], sizes[1], sizes[2], sizes[3]);
367#endif
368}
369
370struct rom_hdr {
371 /* 000 */ unsigned char iwave[8];
372 /* 008 */ unsigned char rom_hdr_revision;
373 /* 009 */ unsigned char series_number;
374 /* 010 */ unsigned char series_name[16];
375 /* 026 */ unsigned char date[10];
376 /* 036 */ unsigned short vendor_revision_major;
377 /* 038 */ unsigned short vendor_revision_minor;
378 /* 040 */ unsigned int rom_size;
379 /* 044 */ unsigned char copyright[128];
380 /* 172 */ unsigned char vendor_name[64];
381 /* 236 */ unsigned char rom_description[128];
382 /* 364 */ unsigned char pad[147];
383 /* 511 */ unsigned char csum;
384};
385
386static void __devinit snd_interwave_detect_memory(snd_gus_card_t * gus)
387{
388 static unsigned int lmc[13] =
389 {
390 0x00000001, 0x00000101, 0x01010101, 0x00000401,
391 0x04040401, 0x00040101, 0x04040101, 0x00000004,
392 0x00000404, 0x04040404, 0x00000010, 0x00001010,
393 0x10101010
394 };
395
396 int bank_pos, pages;
397 unsigned int i, lmct;
398 int psizes[4];
399 unsigned char iwave[8];
400 unsigned char csum;
401
402 snd_interwave_reset(gus);
403 snd_gf1_write8(gus, SNDRV_GF1_GB_GLOBAL_MODE, snd_gf1_read8(gus, SNDRV_GF1_GB_GLOBAL_MODE) | 0x01); /* enhanced mode */
404 snd_gf1_write8(gus, SNDRV_GF1_GB_MEMORY_CONTROL, 0x01); /* DRAM I/O cycles selected */
405 snd_gf1_write16(gus, SNDRV_GF1_GW_MEMORY_CONFIG, (snd_gf1_look16(gus, SNDRV_GF1_GW_MEMORY_CONFIG) & 0xff10) | 0x004c);
406 /* ok.. simple test of memory size */
407 pages = 0;
408 snd_gf1_poke(gus, 0, 0x55);
409 snd_gf1_poke(gus, 1, 0xaa);
410#if 1
411 if (snd_gf1_peek(gus, 0) == 0x55 && snd_gf1_peek(gus, 1) == 0xaa)
412#else
413 if (0) /* ok.. for testing of 0k RAM */
414#endif
415 {
416 snd_interwave_bank_sizes(gus, psizes);
417 lmct = (psizes[3] << 24) | (psizes[2] << 16) |
418 (psizes[1] << 8) | psizes[0];
419#if 0
420 printk("lmct = 0x%08x\n", lmct);
421#endif
422 for (i = 0; i < ARRAY_SIZE(lmc); i++)
423 if (lmct == lmc[i]) {
424#if 0
425 printk("found !!! %i\n", i);
426#endif
427 snd_gf1_write16(gus, SNDRV_GF1_GW_MEMORY_CONFIG, (snd_gf1_look16(gus, SNDRV_GF1_GW_MEMORY_CONFIG) & 0xfff0) | i);
428 snd_interwave_bank_sizes(gus, psizes);
429 break;
430 }
431 if (i >= ARRAY_SIZE(lmc) && !gus->gf1.enh_mode)
432 snd_gf1_write16(gus, SNDRV_GF1_GW_MEMORY_CONFIG, (snd_gf1_look16(gus, SNDRV_GF1_GW_MEMORY_CONFIG) & 0xfff0) | 2);
433 for (i = 0; i < 4; i++) {
434 gus->gf1.mem_alloc.banks_8[i].address =
435 gus->gf1.mem_alloc.banks_16[i].address = i << 22;
436 gus->gf1.mem_alloc.banks_8[i].size =
437 gus->gf1.mem_alloc.banks_16[i].size = psizes[i] << 18;
438 pages += psizes[i];
439 }
440 }
441 pages <<= 18;
442 gus->gf1.memory = pages;
443
444 snd_gf1_write8(gus, SNDRV_GF1_GB_MEMORY_CONTROL, 0x03); /* select ROM */
445 snd_gf1_write16(gus, SNDRV_GF1_GW_MEMORY_CONFIG, (snd_gf1_look16(gus, SNDRV_GF1_GW_MEMORY_CONFIG) & 0xff1f) | (4 << 5));
446 gus->gf1.rom_banks = 0;
447 gus->gf1.rom_memory = 0;
448 for (bank_pos = 0; bank_pos < 16L * 1024L * 1024L; bank_pos += 4L * 1024L * 1024L) {
449 for (i = 0; i < 8; ++i)
450 iwave[i] = snd_gf1_peek(gus, bank_pos + i);
451#ifdef CONFIG_SND_DEBUG_ROM
452 printk("ROM at 0x%06x = %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n", bank_pos,
453 iwave[0], iwave[1], iwave[2], iwave[3],
454 iwave[4], iwave[5], iwave[6], iwave[7]);
455#endif
456 if (strncmp(iwave, "INTRWAVE", 8))
457 continue; /* first check */
458 csum = 0;
459 for (i = 0; i < sizeof(struct rom_hdr); i++)
460 csum += snd_gf1_peek(gus, bank_pos + i);
461#ifdef CONFIG_SND_DEBUG_ROM
462 printk("ROM checksum = 0x%x (computed)\n", csum);
463#endif
464 if (csum != 0)
465 continue; /* not valid rom */
466 gus->gf1.rom_banks++;
467 gus->gf1.rom_present |= 1 << (bank_pos >> 22);
468 gus->gf1.rom_memory = snd_gf1_peek(gus, bank_pos + 40) |
469 (snd_gf1_peek(gus, bank_pos + 41) << 8) |
470 (snd_gf1_peek(gus, bank_pos + 42) << 16) |
471 (snd_gf1_peek(gus, bank_pos + 43) << 24);
472 }
473#if 0
474 if (gus->gf1.rom_memory > 0) {
475 if (gus->gf1.rom_banks == 1 && gus->gf1.rom_present == 8)
476 gus->card->type = SNDRV_CARD_TYPE_IW_DYNASONIC;
477 }
478#endif
479 snd_gf1_write8(gus, SNDRV_GF1_GB_MEMORY_CONTROL, 0x00); /* select RAM */
480
481 if (!gus->gf1.enh_mode)
482 snd_interwave_reset(gus);
483}
484
485static void __devinit snd_interwave_init(int dev, snd_gus_card_t * gus)
486{
487 unsigned long flags;
488
489 /* ok.. some InterWave specific initialization */
490 spin_lock_irqsave(&gus->reg_lock, flags);
491 snd_gf1_write8(gus, SNDRV_GF1_GB_SOUND_BLASTER_CONTROL, 0x00);
492 snd_gf1_write8(gus, SNDRV_GF1_GB_COMPATIBILITY, 0x1f);
493 snd_gf1_write8(gus, SNDRV_GF1_GB_DECODE_CONTROL, 0x49);
494 snd_gf1_write8(gus, SNDRV_GF1_GB_VERSION_NUMBER, 0x11);
495 snd_gf1_write8(gus, SNDRV_GF1_GB_MPU401_CONTROL_A, 0x00);
496 snd_gf1_write8(gus, SNDRV_GF1_GB_MPU401_CONTROL_B, 0x30);
497 snd_gf1_write8(gus, SNDRV_GF1_GB_EMULATION_IRQ, 0x00);
498 spin_unlock_irqrestore(&gus->reg_lock, flags);
499 gus->equal_irq = 1;
500 gus->codec_flag = 1;
501 gus->interwave = 1;
502 gus->max_flag = 1;
503 gus->joystick_dac = joystick_dac[dev];
504
505}
506
507static snd_kcontrol_new_t snd_interwave_controls[] = {
508CS4231_DOUBLE("Master Playback Switch", 0, CS4231_LINE_LEFT_OUTPUT, CS4231_LINE_RIGHT_OUTPUT, 7, 7, 1, 1),
509CS4231_DOUBLE("Master Playback Volume", 0, CS4231_LINE_LEFT_OUTPUT, CS4231_LINE_RIGHT_OUTPUT, 0, 0, 31, 1),
510CS4231_DOUBLE("Mic Playback Switch", 0, CS4231_LEFT_MIC_INPUT, CS4231_RIGHT_MIC_INPUT, 7, 7, 1, 1),
511CS4231_DOUBLE("Mic Playback Volume", 0, CS4231_LEFT_MIC_INPUT, CS4231_RIGHT_MIC_INPUT, 0, 0, 31, 1)
512};
513
514static int __devinit snd_interwave_mixer(cs4231_t *chip)
515{
516 snd_card_t *card = chip->card;
517 snd_ctl_elem_id_t id1, id2;
518 unsigned int idx;
519 int err;
520
521 memset(&id1, 0, sizeof(id1));
522 memset(&id2, 0, sizeof(id2));
523 id1.iface = id2.iface = SNDRV_CTL_ELEM_IFACE_MIXER;
524#if 0
525 /* remove mono microphone controls */
526 strcpy(id1.name, "Mic Playback Switch");
527 if ((err = snd_ctl_remove_id(card, &id1)) < 0)
528 return err;
529 strcpy(id1.name, "Mic Playback Volume");
530 if ((err = snd_ctl_remove_id(card, &id1)) < 0)
531 return err;
532#endif
533 /* add new master and mic controls */
534 for (idx = 0; idx < ARRAY_SIZE(snd_interwave_controls); idx++)
535 if ((err = snd_ctl_add(card, snd_ctl_new1(&snd_interwave_controls[idx], chip))) < 0)
536 return err;
537 snd_cs4231_out(chip, CS4231_LINE_LEFT_OUTPUT, 0x9f);
538 snd_cs4231_out(chip, CS4231_LINE_RIGHT_OUTPUT, 0x9f);
539 snd_cs4231_out(chip, CS4231_LEFT_MIC_INPUT, 0x9f);
540 snd_cs4231_out(chip, CS4231_RIGHT_MIC_INPUT, 0x9f);
541 /* reassign AUXA to SYNTHESIZER */
542 strcpy(id1.name, "Aux Playback Switch");
543 strcpy(id2.name, "Synth Playback Switch");
544 if ((err = snd_ctl_rename_id(card, &id1, &id2)) < 0)
545 return err;
546 strcpy(id1.name, "Aux Playback Volume");
547 strcpy(id2.name, "Synth Playback Volume");
548 if ((err = snd_ctl_rename_id(card, &id1, &id2)) < 0)
549 return err;
550 /* reassign AUXB to CD */
551 strcpy(id1.name, "Aux Playback Switch"); id1.index = 1;
552 strcpy(id2.name, "CD Playback Switch");
553 if ((err = snd_ctl_rename_id(card, &id1, &id2)) < 0)
554 return err;
555 strcpy(id1.name, "Aux Playback Volume");
556 strcpy(id2.name, "CD Playback Volume");
557 if ((err = snd_ctl_rename_id(card, &id1, &id2)) < 0)
558 return err;
559 return 0;
560}
561
562#ifdef CONFIG_PNP
563
564static int __devinit snd_interwave_pnp(int dev, struct snd_interwave *iwcard,
565 struct pnp_card_link *card,
566 const struct pnp_card_device_id *id)
567{
568 struct pnp_dev *pdev;
569 struct pnp_resource_table * cfg = kmalloc(sizeof(struct pnp_resource_table), GFP_KERNEL);
570 int err;
571
572 iwcard->dev = pnp_request_card_device(card, id->devs[0].id, NULL);
573 if (iwcard->dev == NULL) {
574 kfree(cfg);
575 return -EBUSY;
576 }
577#ifdef SNDRV_STB
578 iwcard->devtc = pnp_request_card_device(card, id->devs[1].id, NULL);
579 if (iwcard->devtc == NULL) {
580 kfree(cfg);
581 return -EBUSY;
582 }
583#endif
584 /* Synth & Codec initialization */
585 pdev = iwcard->dev;
586 pnp_init_resource_table(cfg);
587 if (port[dev] != SNDRV_AUTO_PORT) {
588 pnp_resource_change(&cfg->port_resource[0], port[dev], 16);
589 pnp_resource_change(&cfg->port_resource[1], port[dev] + 0x100, 12);
590 pnp_resource_change(&cfg->port_resource[2], port[dev] + 0x10c, 4);
591 }
592 if (dma1[dev] != SNDRV_AUTO_DMA)
593 pnp_resource_change(&cfg->dma_resource[0], dma1[dev], 1);
594 if (dma2[dev] != SNDRV_AUTO_DMA)
595 pnp_resource_change(&cfg->dma_resource[1], dma2[dev], 1);
596 if (dma2[dev] < 0)
597 pnp_resource_change(&cfg->dma_resource[1], 4, 1);
598 if (irq[dev] != SNDRV_AUTO_IRQ)
599 pnp_resource_change(&cfg->irq_resource[0], irq[dev], 1);
600 if (pnp_manual_config_dev(pdev, cfg, 0) < 0)
601 snd_printk(KERN_ERR "InterWave - Synth - the requested resources are invalid, using auto config\n");
602 err = pnp_activate_dev(pdev);
603 if (err < 0) {
604 kfree(cfg);
605 snd_printk(KERN_ERR "InterWave PnP configure failure (out of resources?)\n");
606 return err;
607 }
608 if (pnp_port_start(pdev, 0) + 0x100 != pnp_port_start(pdev, 1) ||
609 pnp_port_start(pdev, 0) + 0x10c != pnp_port_start(pdev, 2)) {
610 kfree(cfg);
611 snd_printk(KERN_ERR "PnP configure failure (wrong ports)\n");
612 return -ENOENT;
613 }
614 port[dev] = pnp_port_start(pdev, 0);
615 dma1[dev] = pnp_dma(pdev, 0);
616 if (dma2[dev] >= 0)
617 dma2[dev] = pnp_dma(pdev, 1);
618 irq[dev] = pnp_irq(pdev, 0);
619 snd_printdd("isapnp IW: sb port=0x%lx, gf1 port=0x%lx, codec port=0x%lx\n",
620 pnp_port_start(pdev, 0),
621 pnp_port_start(pdev, 1),
622 pnp_port_start(pdev, 2));
623 snd_printdd("isapnp IW: dma1=%i, dma2=%i, irq=%i\n", dma1[dev], dma2[dev], irq[dev]);
624#ifdef SNDRV_STB
625 /* Tone Control initialization */
626 pdev = iwcard->devtc;
627 pnp_init_resource_table(cfg);
628 if (port_tc[dev] != SNDRV_AUTO_PORT)
629 pnp_resource_change(&cfg->port_resource[0], port_tc[dev], 1);
630 if (pnp_manual_config_dev(pdev, cfg, 0) < 0)
631 snd_printk(KERN_ERR "InterWave - ToneControl - the requested resources are invalid, using auto config\n");
632 err = pnp_activate_dev(pdev);
633 if (err < 0) {
634 kfree(cfg);
635 snd_printk(KERN_ERR "InterWave ToneControl PnP configure failure (out of resources?)\n");
636 return err;
637 }
638 port_tc[dev] = pnp_port_start(pdev, 0);
639 snd_printdd("isapnp IW: tone control port=0x%lx\n", port_tc[dev]);
640#endif
641 kfree(cfg);
642 return 0;
643}
644#endif /* CONFIG_PNP */
645
646static void snd_interwave_free(snd_card_t *card)
647{
648 struct snd_interwave *iwcard = (struct snd_interwave *)card->private_data;
649
650 if (iwcard == NULL)
651 return;
652#ifdef SNDRV_STB
653 if (iwcard->i2c_res) {
654 release_resource(iwcard->i2c_res);
655 kfree_nocheck(iwcard->i2c_res);
656 }
657#endif
658 if (iwcard->irq >= 0)
659 free_irq(iwcard->irq, (void *)iwcard);
660}
661
662static int __devinit snd_interwave_probe(int dev, struct pnp_card_link *pcard,
663 const struct pnp_card_device_id *pid)
664{
665 static int possible_irqs[] = {5, 11, 12, 9, 7, 15, 3, -1};
666 static int possible_dmas[] = {0, 1, 3, 5, 6, 7, -1};
667 int xirq, xdma1, xdma2;
668 snd_card_t *card;
669 struct snd_interwave *iwcard;
670 cs4231_t *cs4231;
671 snd_gus_card_t *gus;
672#ifdef SNDRV_STB
673 snd_i2c_bus_t *i2c_bus;
674#endif
675 snd_pcm_t *pcm;
676 char *str;
677 int err;
678
679 card = snd_card_new(index[dev], id[dev], THIS_MODULE,
680 sizeof(struct snd_interwave));
681 if (card == NULL)
682 return -ENOMEM;
683 iwcard = (struct snd_interwave *)card->private_data;
684 iwcard->card = card;
685 iwcard->irq = -1;
686 card->private_free = snd_interwave_free;
687#ifdef CONFIG_PNP
688 if (isapnp[dev]) {
689 if (snd_interwave_pnp(dev, iwcard, pcard, pid)) {
690 snd_card_free(card);
691 return -ENODEV;
692 }
693 snd_card_set_dev(card, &pcard->card->dev);
694 }
695#endif
696 xirq = irq[dev];
697 if (xirq == SNDRV_AUTO_IRQ) {
698 if ((xirq = snd_legacy_find_free_irq(possible_irqs)) < 0) {
699 snd_card_free(card);
700 snd_printk("unable to find a free IRQ\n");
701 return -EBUSY;
702 }
703 }
704 xdma1 = dma1[dev];
705 if (xdma1 == SNDRV_AUTO_DMA) {
706 if ((xdma1 = snd_legacy_find_free_dma(possible_dmas)) < 0) {
707 snd_card_free(card);
708 snd_printk("unable to find a free DMA1\n");
709 return -EBUSY;
710 }
711 }
712 xdma2 = dma2[dev];
713 if (xdma2 == SNDRV_AUTO_DMA) {
714 if ((xdma2 = snd_legacy_find_free_dma(possible_dmas)) < 0) {
715 snd_card_free(card);
716 snd_printk("unable to find a free DMA2\n");
717 return -EBUSY;
718 }
719 }
720
721 if ((err = snd_gus_create(card,
722 port[dev],
723 -xirq, xdma1, xdma2,
724 0, 32,
725 pcm_channels[dev], effect[dev], &gus)) < 0) {
726 snd_card_free(card);
727 return err;
728 }
729 if ((err = snd_interwave_detect(iwcard, gus, dev
730#ifdef SNDRV_STB
731 , &i2c_bus
732#endif
733 )) < 0) {
734 snd_card_free(card);
735 return err;
736 }
737 iwcard->gus_status_reg = gus->gf1.reg_irqstat;
738 iwcard->pcm_status_reg = gus->gf1.port + 0x10c + 2;
739
740 snd_interwave_init(dev, gus);
741 snd_interwave_detect_memory(gus);
742 if ((err = snd_gus_initialize(gus)) < 0) {
743 snd_card_free(card);
744 return err;
745 }
746
747 if (request_irq(xirq, snd_interwave_interrupt, SA_INTERRUPT, "InterWave", (void *)iwcard)) {
748 snd_card_free(card);
749 snd_printk("unable to grab IRQ %d\n", xirq);
750 return -EBUSY;
751 }
752 iwcard->irq = xirq;
753
754 if ((err = snd_cs4231_create(card,
755 gus->gf1.port + 0x10c, -1, xirq,
756 xdma2 < 0 ? xdma1 : xdma2, xdma1,
757 CS4231_HW_INTERWAVE,
758 CS4231_HWSHARE_IRQ |
759 CS4231_HWSHARE_DMA1 |
760 CS4231_HWSHARE_DMA2,
761 &cs4231)) < 0) {
762 snd_card_free(card);
763 return err;
764 }
765 if ((err = snd_cs4231_pcm(cs4231, 0, &pcm)) < 0) {
766 snd_card_free(card);
767 return err;
768 }
769 sprintf(pcm->name + strlen(pcm->name), " rev %c", gus->revision + 'A');
770 strcat(pcm->name, " (codec)");
771 if ((err = snd_cs4231_timer(cs4231, 2, NULL)) < 0) {
772 snd_card_free(card);
773 return err;
774 }
775 if ((err = snd_cs4231_mixer(cs4231)) < 0) {
776 snd_card_free(card);
777 return err;
778 }
779 if (pcm_channels[dev] > 0) {
780 if ((err = snd_gf1_pcm_new(gus, 1, 1, NULL)) < 0) {
781 snd_card_free(card);
782 return err;
783 }
784 }
785 if ((err = snd_interwave_mixer(cs4231)) < 0) {
786 snd_card_free(card);
787 return err;
788 }
789#ifdef SNDRV_STB
790 {
791 snd_ctl_elem_id_t id1, id2;
792 memset(&id1, 0, sizeof(id1));
793 memset(&id2, 0, sizeof(id2));
794 id1.iface = id2.iface = SNDRV_CTL_ELEM_IFACE_MIXER;
795 strcpy(id1.name, "Master Playback Switch");
796 strcpy(id2.name, id1.name);
797 id2.index = 1;
798 if ((err = snd_ctl_rename_id(card, &id1, &id2)) < 0) {
799 snd_card_free(card);
800 return err;
801 }
802 strcpy(id1.name, "Master Playback Volume");
803 strcpy(id2.name, id1.name);
804 if ((err = snd_ctl_rename_id(card, &id1, &id2)) < 0) {
805 snd_card_free(card);
806 return err;
807 }
808 if ((err = snd_tea6330t_update_mixer(card, i2c_bus, 0, 1)) < 0) {
809 snd_card_free(card);
810 return err;
811 }
812 }
813#endif
814
815 gus->uart_enable = midi[dev];
816 if ((err = snd_gf1_rawmidi_new(gus, 0, NULL)) < 0) {
817 snd_card_free(card);
818 return err;
819 }
820
821#ifndef SNDRV_STB
822 str = "AMD InterWave";
823 if (gus->gf1.rom_banks == 1 && gus->gf1.rom_present == 8)
824 str = "Dynasonic 3-D";
825#else
826 str = "InterWave STB";
827#endif
828 strcpy(card->driver, str);
829 strcpy(card->shortname, str);
830 sprintf(card->longname, "%s at 0x%lx, irq %i, dma %d",
831 str,
832 gus->gf1.port,
833 xirq,
834 xdma1);
835 if (xdma2 >= 0)
836 sprintf(card->longname + strlen(card->longname), "&%d", xdma2);
837
838 if ((err = snd_card_register(card)) < 0) {
839 snd_card_free(card);
840 return err;
841 }
842
843 iwcard->cs4231 = cs4231;
844 iwcard->gus = gus;
845 if (pcard)
846 pnp_set_card_drvdata(pcard, card);
847 else
848 snd_interwave_legacy[dev++] = card;
849 return 0;
850}
851
852static int __devinit snd_interwave_probe_legacy_port(unsigned long xport)
853{
854 static int dev;
855 int res;
856
857 for ( ; dev < SNDRV_CARDS; dev++) {
858 if (!enable[dev] || port[dev] != SNDRV_AUTO_PORT)
859 continue;
860#ifdef CONFIG_PNP
861 if (isapnp[dev])
862 continue;
863#endif
864 port[dev] = xport;
865 res = snd_interwave_probe(dev, NULL, NULL);
866 if (res < 0)
867 port[dev] = SNDRV_AUTO_PORT;
868 return res;
869 }
870 return -ENODEV;
871}
872
873#ifdef CONFIG_PNP
874
875static int __devinit snd_interwave_pnp_detect(struct pnp_card_link *card,
876 const struct pnp_card_device_id *id)
877{
878 static int dev;
879 int res;
880
881 for ( ; dev < SNDRV_CARDS; dev++) {
882 if (!enable[dev] || !isapnp[dev])
883 continue;
884 res = snd_interwave_probe(dev, card, id);
885 if (res < 0)
886 return res;
887 dev++;
888 return 0;
889 }
890
891 return -ENODEV;
892}
893
894static void __devexit snd_interwave_pnp_remove(struct pnp_card_link * pcard)
895{
896 snd_card_t *card = (snd_card_t *) pnp_get_card_drvdata(pcard);
897
898 snd_card_disconnect(card);
899 snd_card_free_in_thread(card);
900}
901
902static struct pnp_card_driver interwave_pnpc_driver = {
903 .flags = PNP_DRIVER_RES_DISABLE,
904 .name = "interwave",
905 .id_table = snd_interwave_pnpids,
906 .probe = snd_interwave_pnp_detect,
907 .remove = __devexit_p(snd_interwave_pnp_remove),
908};
909
910#endif /* CONFIG_PNP */
911
912static int __init alsa_card_interwave_init(void)
913{
914 int cards = 0, i;
915 static long possible_ports[] = {0x210, 0x220, 0x230, 0x240, 0x250, 0x260, -1};
916 int dev;
917
918 for (dev = 0; dev < SNDRV_CARDS; dev++) {
919 if (!enable[dev] || port[dev] == SNDRV_AUTO_PORT)
920 continue;
921#ifdef CONFIG_PNP
922 if (isapnp[dev])
923 continue;
924#endif
925 if (!snd_interwave_probe(dev, NULL, NULL)) {
926 cards++;
927 continue;
928 }
929#ifdef MODULE
930 printk(KERN_ERR "InterWave soundcard #%i not found at 0x%lx or device busy\n", dev, port[dev]);
931#endif
932 }
933 /* legacy auto configured cards */
934 i = snd_legacy_auto_probe(possible_ports, snd_interwave_probe_legacy_port);
935 if (i > 0)
936 cards += i;
937#ifdef CONFIG_PNP
938 /* ISA PnP cards */
939 i = pnp_register_card_driver(&interwave_pnpc_driver);
940 if (i > 0)
941 cards += i;
942#endif
943
944 if (!cards) {
945#ifdef CONFIG_PNP
946 pnp_unregister_card_driver(&interwave_pnpc_driver);
947#endif
948#ifdef MODULE
949 printk(KERN_ERR "InterWave soundcard not found or device busy\n");
950#endif
951 return -ENODEV;
952 }
953 return 0;
954}
955
956static void __exit alsa_card_interwave_exit(void)
957{
958 int dev;
959
960#ifdef CONFIG_PNP
961 /* PnP cards first */
962 pnp_unregister_card_driver(&interwave_pnpc_driver);
963#endif
964 for (dev = 0; dev < SNDRV_CARDS; dev++)
965 snd_card_free(snd_interwave_legacy[dev]);
966}
967
968module_init(alsa_card_interwave_init)
969module_exit(alsa_card_interwave_exit)
diff --git a/sound/isa/opl3sa2.c b/sound/isa/opl3sa2.c
new file mode 100644
index 000000000000..95c7b3e53407
--- /dev/null
+++ b/sound/isa/opl3sa2.c
@@ -0,0 +1,860 @@
1/*
2 * Driver for Yamaha OPL3-SA[2,3] soundcards
3 * Copyright (c) by Jaroslav Kysela <perex@suse.cz>
4 *
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 *
20 */
21
22#include <sound/driver.h>
23#include <linux/init.h>
24#include <linux/interrupt.h>
25#include <linux/pm.h>
26#include <linux/slab.h>
27#include <linux/pnp.h>
28#include <linux/moduleparam.h>
29#include <sound/core.h>
30#include <sound/cs4231.h>
31#include <sound/mpu401.h>
32#include <sound/opl3.h>
33#include <sound/initval.h>
34
35#include <asm/io.h>
36
37MODULE_AUTHOR("Jaroslav Kysela <perex@suse.cz>");
38MODULE_DESCRIPTION("Yamaha OPL3SA2+");
39MODULE_LICENSE("GPL");
40MODULE_SUPPORTED_DEVICE("{{Yamaha,YMF719E-S},"
41 "{Genius,Sound Maker 3DX},"
42 "{Yamaha,OPL3SA3},"
43 "{Intel,AL440LX sound},"
44 "{NeoMagic,MagicWave 3DX}}");
45
46static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-MAX */
47static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* ID for this card */
48static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_ISAPNP; /* Enable this card */
49#ifdef CONFIG_PNP
50static int isapnp[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 1};
51#endif
52static long port[SNDRV_CARDS] = SNDRV_DEFAULT_PORT; /* 0xf86,0x370,0x100 */
53static long sb_port[SNDRV_CARDS] = SNDRV_DEFAULT_PORT; /* 0x220,0x240,0x260 */
54static long wss_port[SNDRV_CARDS] = SNDRV_DEFAULT_PORT;/* 0x530,0xe80,0xf40,0x604 */
55static long fm_port[SNDRV_CARDS] = SNDRV_DEFAULT_PORT; /* 0x388 */
56static long midi_port[SNDRV_CARDS] = SNDRV_DEFAULT_PORT;/* 0x330,0x300 */
57static int irq[SNDRV_CARDS] = SNDRV_DEFAULT_IRQ; /* 0,1,3,5,9,11,12,15 */
58static int dma1[SNDRV_CARDS] = SNDRV_DEFAULT_DMA; /* 1,3,5,6,7 */
59static int dma2[SNDRV_CARDS] = SNDRV_DEFAULT_DMA; /* 1,3,5,6,7 */
60static int opl3sa3_ymode[SNDRV_CARDS] = { [0 ... (SNDRV_CARDS-1)] = 0 }; /* 0,1,2,3 */ /*SL Added*/
61
62module_param_array(index, int, NULL, 0444);
63MODULE_PARM_DESC(index, "Index value for OPL3-SA soundcard.");
64module_param_array(id, charp, NULL, 0444);
65MODULE_PARM_DESC(id, "ID string for OPL3-SA soundcard.");
66module_param_array(enable, bool, NULL, 0444);
67MODULE_PARM_DESC(enable, "Enable OPL3-SA soundcard.");
68#ifdef CONFIG_PNP
69module_param_array(isapnp, bool, NULL, 0444);
70MODULE_PARM_DESC(isapnp, "PnP detection for specified soundcard.");
71#endif
72module_param_array(port, long, NULL, 0444);
73MODULE_PARM_DESC(port, "Port # for OPL3-SA driver.");
74module_param_array(sb_port, long, NULL, 0444);
75MODULE_PARM_DESC(sb_port, "SB port # for OPL3-SA driver.");
76module_param_array(wss_port, long, NULL, 0444);
77MODULE_PARM_DESC(wss_port, "WSS port # for OPL3-SA driver.");
78module_param_array(fm_port, long, NULL, 0444);
79MODULE_PARM_DESC(fm_port, "FM port # for OPL3-SA driver.");
80module_param_array(midi_port, long, NULL, 0444);
81MODULE_PARM_DESC(midi_port, "MIDI port # for OPL3-SA driver.");
82module_param_array(irq, int, NULL, 0444);
83MODULE_PARM_DESC(irq, "IRQ # for OPL3-SA driver.");
84module_param_array(dma1, int, NULL, 0444);
85MODULE_PARM_DESC(dma1, "DMA1 # for OPL3-SA driver.");
86module_param_array(dma2, int, NULL, 0444);
87MODULE_PARM_DESC(dma2, "DMA2 # for OPL3-SA driver.");
88module_param_array(opl3sa3_ymode, int, NULL, 0444);
89MODULE_PARM_DESC(opl3sa3_ymode, "Speaker size selection for 3D Enhancement mode: Desktop/Large Notebook/Small Notebook/HiFi.");
90
91/* control ports */
92#define OPL3SA2_PM_CTRL 0x01
93#define OPL3SA2_SYS_CTRL 0x02
94#define OPL3SA2_IRQ_CONFIG 0x03
95#define OPL3SA2_IRQ_STATUS 0x04
96#define OPL3SA2_DMA_CONFIG 0x06
97#define OPL3SA2_MASTER_LEFT 0x07
98#define OPL3SA2_MASTER_RIGHT 0x08
99#define OPL3SA2_MIC 0x09
100#define OPL3SA2_MISC 0x0A
101
102/* opl3sa3 only */
103#define OPL3SA3_DGTL_DOWN 0x12
104#define OPL3SA3_ANLG_DOWN 0x13
105#define OPL3SA3_WIDE 0x14
106#define OPL3SA3_BASS 0x15
107#define OPL3SA3_TREBLE 0x16
108
109/* power management bits */
110#define OPL3SA2_PM_ADOWN 0x20
111#define OPL3SA2_PM_PSV 0x04
112#define OPL3SA2_PM_PDN 0x02
113#define OPL3SA2_PM_PDX 0x01
114
115#define OPL3SA2_PM_D0 0x00
116#define OPL3SA2_PM_D3 (OPL3SA2_PM_ADOWN|OPL3SA2_PM_PSV|OPL3SA2_PM_PDN|OPL3SA2_PM_PDX)
117
118typedef struct snd_opl3sa2 opl3sa2_t;
119
120struct snd_opl3sa2 {
121 snd_card_t *card;
122 int version; /* 2 or 3 */
123 unsigned long port; /* control port */
124 struct resource *res_port; /* control port resource */
125 int irq;
126 int single_dma;
127 spinlock_t reg_lock;
128 snd_hwdep_t *synth;
129 snd_rawmidi_t *rmidi;
130 cs4231_t *cs4231;
131#ifdef CONFIG_PNP
132 struct pnp_dev *dev;
133#endif
134 unsigned char ctlregs[0x20];
135 int ymode; /* SL added */
136 snd_kcontrol_t *master_switch;
137 snd_kcontrol_t *master_volume;
138#ifdef CONFIG_PM
139 void (*cs4231_suspend)(cs4231_t *);
140 void (*cs4231_resume)(cs4231_t *);
141#endif
142};
143
144static snd_card_t *snd_opl3sa2_legacy[SNDRV_CARDS] = SNDRV_DEFAULT_PTR;
145
146#ifdef CONFIG_PNP
147
148static struct pnp_card_device_id snd_opl3sa2_pnpids[] = {
149 /* Yamaha YMF719E-S (Genius Sound Maker 3DX) */
150 { .id = "YMH0020", .devs = { { "YMH0021" } } },
151 /* Yamaha OPL3-SA3 (integrated on Intel's Pentium II AL440LX motherboard) */
152 { .id = "YMH0030", .devs = { { "YMH0021" } } },
153 /* Yamaha OPL3-SA2 */
154 { .id = "YMH0800", .devs = { { "YMH0021" } } },
155 /* Yamaha OPL3-SA2 */
156 { .id = "YMH0801", .devs = { { "YMH0021" } } },
157 /* NeoMagic MagicWave 3DX */
158 { .id = "NMX2200", .devs = { { "YMH2210" } } },
159 /* --- */
160 { .id = "" } /* end */
161};
162
163MODULE_DEVICE_TABLE(pnp_card, snd_opl3sa2_pnpids);
164
165#endif /* CONFIG_PNP */
166
167
168/* read control port (w/o spinlock) */
169static unsigned char __snd_opl3sa2_read(opl3sa2_t *chip, unsigned char reg)
170{
171 unsigned char result;
172#if 0
173 outb(0x1d, port); /* password */
174 printk("read [0x%lx] = 0x%x\n", port, inb(port));
175#endif
176 outb(reg, chip->port); /* register */
177 result = inb(chip->port + 1);
178#if 0
179 printk("read [0x%lx] = 0x%x [0x%x]\n", port, result, inb(port));
180#endif
181 return result;
182}
183
184/* read control port (with spinlock) */
185static unsigned char snd_opl3sa2_read(opl3sa2_t *chip, unsigned char reg)
186{
187 unsigned long flags;
188 unsigned char result;
189
190 spin_lock_irqsave(&chip->reg_lock, flags);
191 result = __snd_opl3sa2_read(chip, reg);
192 spin_unlock_irqrestore(&chip->reg_lock, flags);
193 return result;
194}
195
196/* write control port (w/o spinlock) */
197static void __snd_opl3sa2_write(opl3sa2_t *chip, unsigned char reg, unsigned char value)
198{
199#if 0
200 outb(0x1d, port); /* password */
201#endif
202 outb(reg, chip->port); /* register */
203 outb(value, chip->port + 1);
204 chip->ctlregs[reg] = value;
205}
206
207/* write control port (with spinlock) */
208static void snd_opl3sa2_write(opl3sa2_t *chip, unsigned char reg, unsigned char value)
209{
210 unsigned long flags;
211 spin_lock_irqsave(&chip->reg_lock, flags);
212 __snd_opl3sa2_write(chip, reg, value);
213 spin_unlock_irqrestore(&chip->reg_lock, flags);
214}
215
216static int __init snd_opl3sa2_detect(opl3sa2_t *chip)
217{
218 snd_card_t *card;
219 unsigned long port;
220 unsigned char tmp, tmp1;
221 char str[2];
222
223 card = chip->card;
224 port = chip->port;
225 if ((chip->res_port = request_region(port, 2, "OPL3-SA control")) == NULL) {
226 snd_printk(KERN_ERR "opl3sa2: can't grab port 0x%lx\n", port);
227 return -EBUSY;
228 }
229 // snd_printk("REG 0A = 0x%x\n", snd_opl3sa2_read(chip, 0x0a));
230 chip->version = 0;
231 tmp = snd_opl3sa2_read(chip, OPL3SA2_MISC);
232 if (tmp == 0xff) {
233 snd_printd("OPL3-SA [0x%lx] detect = 0x%x\n", port, tmp);
234 return -ENODEV;
235 }
236 switch (tmp & 0x07) {
237 case 0x01:
238 chip->version = 2; /* YMF711 */
239 break;
240 default:
241 chip->version = 3;
242 /* 0x02 - standard */
243 /* 0x03 - YM715B */
244 /* 0x04 - YM719 - OPL-SA4? */
245 /* 0x05 - OPL3-SA3 - Libretto 100 */
246 break;
247 }
248 str[0] = chip->version + '0';
249 str[1] = 0;
250 strcat(card->shortname, str);
251 snd_opl3sa2_write(chip, OPL3SA2_MISC, tmp ^ 7);
252 if ((tmp1 = snd_opl3sa2_read(chip, OPL3SA2_MISC)) != tmp) {
253 snd_printd("OPL3-SA [0x%lx] detect (1) = 0x%x (0x%x)\n", port, tmp, tmp1);
254 return -ENODEV;
255 }
256 /* try if the MIC register is accesible */
257 tmp = snd_opl3sa2_read(chip, OPL3SA2_MIC);
258 snd_opl3sa2_write(chip, OPL3SA2_MIC, 0x8a);
259 if (((tmp1 = snd_opl3sa2_read(chip, OPL3SA2_MIC)) & 0x9f) != 0x8a) {
260 snd_printd("OPL3-SA [0x%lx] detect (2) = 0x%x (0x%x)\n", port, tmp, tmp1);
261 return -ENODEV;
262 }
263 snd_opl3sa2_write(chip, OPL3SA2_MIC, 0x9f);
264 /* initialization */
265 /* Power Management - full on */
266 snd_opl3sa2_write(chip, OPL3SA2_PM_CTRL, OPL3SA2_PM_D0);
267 if (chip->version > 2) {
268 /* ymode is bits 4&5 (of 0 to 7) on all but opl3sa2 versions */
269 snd_opl3sa2_write(chip, OPL3SA2_SYS_CTRL, (chip->ymode << 4));
270 } else {
271 /* default for opl3sa2 versions */
272 snd_opl3sa2_write(chip, OPL3SA2_SYS_CTRL, 0x00);
273 }
274 snd_opl3sa2_write(chip, OPL3SA2_IRQ_CONFIG, 0x0d); /* Interrupt Channel Configuration - IRQ A = OPL3 + MPU + WSS */
275 if (chip->single_dma) {
276 snd_opl3sa2_write(chip, OPL3SA2_DMA_CONFIG, 0x03); /* DMA Configuration - DMA A = WSS-R + WSS-P */
277 } else {
278 snd_opl3sa2_write(chip, OPL3SA2_DMA_CONFIG, 0x21); /* DMA Configuration - DMA B = WSS-R, DMA A = WSS-P */
279 }
280 snd_opl3sa2_write(chip, OPL3SA2_MISC, 0x80 | (tmp & 7)); /* Miscellaneous - default */
281 if (chip->version > 2) {
282 snd_opl3sa2_write(chip, OPL3SA3_DGTL_DOWN, 0x00); /* Digital Block Partial Power Down - default */
283 snd_opl3sa2_write(chip, OPL3SA3_ANLG_DOWN, 0x00); /* Analog Block Partial Power Down - default */
284 }
285 return 0;
286}
287
288static irqreturn_t snd_opl3sa2_interrupt(int irq, void *dev_id, struct pt_regs *regs)
289{
290 unsigned short status;
291 opl3sa2_t *chip = dev_id;
292 int handled = 0;
293
294 if (chip == NULL || chip->card == NULL)
295 return IRQ_NONE;
296
297 status = snd_opl3sa2_read(chip, OPL3SA2_IRQ_STATUS);
298
299 if (status & 0x20) {
300 handled = 1;
301 snd_opl3_interrupt(chip->synth);
302 }
303
304 if ((status & 0x10) && chip->rmidi != NULL) {
305 handled = 1;
306 snd_mpu401_uart_interrupt(irq, chip->rmidi->private_data, regs);
307 }
308
309 if (status & 0x07) { /* TI,CI,PI */
310 handled = 1;
311 snd_cs4231_interrupt(irq, chip->cs4231, regs);
312 }
313
314 if (status & 0x40) { /* hardware volume change */
315 handled = 1;
316 /* reading from Master Lch register at 0x07 clears this bit */
317 snd_opl3sa2_read(chip, OPL3SA2_MASTER_RIGHT);
318 snd_opl3sa2_read(chip, OPL3SA2_MASTER_LEFT);
319 if (chip->master_switch && chip->master_volume) {
320 snd_ctl_notify(chip->card, SNDRV_CTL_EVENT_MASK_VALUE, &chip->master_switch->id);
321 snd_ctl_notify(chip->card, SNDRV_CTL_EVENT_MASK_VALUE, &chip->master_volume->id);
322 }
323 }
324 return IRQ_RETVAL(handled);
325}
326
327#define OPL3SA2_SINGLE(xname, xindex, reg, shift, mask, invert) \
328{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xindex, \
329 .info = snd_opl3sa2_info_single, \
330 .get = snd_opl3sa2_get_single, .put = snd_opl3sa2_put_single, \
331 .private_value = reg | (shift << 8) | (mask << 16) | (invert << 24) }
332
333static int snd_opl3sa2_info_single(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
334{
335 int mask = (kcontrol->private_value >> 16) & 0xff;
336
337 uinfo->type = mask == 1 ? SNDRV_CTL_ELEM_TYPE_BOOLEAN : SNDRV_CTL_ELEM_TYPE_INTEGER;
338 uinfo->count = 1;
339 uinfo->value.integer.min = 0;
340 uinfo->value.integer.max = mask;
341 return 0;
342}
343
344static int snd_opl3sa2_get_single(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
345{
346 opl3sa2_t *chip = snd_kcontrol_chip(kcontrol);
347 unsigned long flags;
348 int reg = kcontrol->private_value & 0xff;
349 int shift = (kcontrol->private_value >> 8) & 0xff;
350 int mask = (kcontrol->private_value >> 16) & 0xff;
351 int invert = (kcontrol->private_value >> 24) & 0xff;
352
353 spin_lock_irqsave(&chip->reg_lock, flags);
354 ucontrol->value.integer.value[0] = (chip->ctlregs[reg] >> shift) & mask;
355 spin_unlock_irqrestore(&chip->reg_lock, flags);
356 if (invert)
357 ucontrol->value.integer.value[0] = mask - ucontrol->value.integer.value[0];
358 return 0;
359}
360
361static int snd_opl3sa2_put_single(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
362{
363 opl3sa2_t *chip = snd_kcontrol_chip(kcontrol);
364 unsigned long flags;
365 int reg = kcontrol->private_value & 0xff;
366 int shift = (kcontrol->private_value >> 8) & 0xff;
367 int mask = (kcontrol->private_value >> 16) & 0xff;
368 int invert = (kcontrol->private_value >> 24) & 0xff;
369 int change;
370 unsigned short val, oval;
371
372 val = (ucontrol->value.integer.value[0] & mask);
373 if (invert)
374 val = mask - val;
375 val <<= shift;
376 spin_lock_irqsave(&chip->reg_lock, flags);
377 oval = chip->ctlregs[reg];
378 val = (oval & ~(mask << shift)) | val;
379 change = val != oval;
380 __snd_opl3sa2_write(chip, reg, val);
381 spin_unlock_irqrestore(&chip->reg_lock, flags);
382 return change;
383}
384
385#define OPL3SA2_DOUBLE(xname, xindex, left_reg, right_reg, shift_left, shift_right, mask, invert) \
386{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xindex, \
387 .info = snd_opl3sa2_info_double, \
388 .get = snd_opl3sa2_get_double, .put = snd_opl3sa2_put_double, \
389 .private_value = left_reg | (right_reg << 8) | (shift_left << 16) | (shift_right << 19) | (mask << 24) | (invert << 22) }
390
391static int snd_opl3sa2_info_double(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
392{
393 int mask = (kcontrol->private_value >> 24) & 0xff;
394
395 uinfo->type = mask == 1 ? SNDRV_CTL_ELEM_TYPE_BOOLEAN : SNDRV_CTL_ELEM_TYPE_INTEGER;
396 uinfo->count = 2;
397 uinfo->value.integer.min = 0;
398 uinfo->value.integer.max = mask;
399 return 0;
400}
401
402static int snd_opl3sa2_get_double(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
403{
404 opl3sa2_t *chip = snd_kcontrol_chip(kcontrol);
405 unsigned long flags;
406 int left_reg = kcontrol->private_value & 0xff;
407 int right_reg = (kcontrol->private_value >> 8) & 0xff;
408 int shift_left = (kcontrol->private_value >> 16) & 0x07;
409 int shift_right = (kcontrol->private_value >> 19) & 0x07;
410 int mask = (kcontrol->private_value >> 24) & 0xff;
411 int invert = (kcontrol->private_value >> 22) & 1;
412
413 spin_lock_irqsave(&chip->reg_lock, flags);
414 ucontrol->value.integer.value[0] = (chip->ctlregs[left_reg] >> shift_left) & mask;
415 ucontrol->value.integer.value[1] = (chip->ctlregs[right_reg] >> shift_right) & mask;
416 spin_unlock_irqrestore(&chip->reg_lock, flags);
417 if (invert) {
418 ucontrol->value.integer.value[0] = mask - ucontrol->value.integer.value[0];
419 ucontrol->value.integer.value[1] = mask - ucontrol->value.integer.value[1];
420 }
421 return 0;
422}
423
424static int snd_opl3sa2_put_double(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
425{
426 opl3sa2_t *chip = snd_kcontrol_chip(kcontrol);
427 unsigned long flags;
428 int left_reg = kcontrol->private_value & 0xff;
429 int right_reg = (kcontrol->private_value >> 8) & 0xff;
430 int shift_left = (kcontrol->private_value >> 16) & 0x07;
431 int shift_right = (kcontrol->private_value >> 19) & 0x07;
432 int mask = (kcontrol->private_value >> 24) & 0xff;
433 int invert = (kcontrol->private_value >> 22) & 1;
434 int change;
435 unsigned short val1, val2, oval1, oval2;
436
437 val1 = ucontrol->value.integer.value[0] & mask;
438 val2 = ucontrol->value.integer.value[1] & mask;
439 if (invert) {
440 val1 = mask - val1;
441 val2 = mask - val2;
442 }
443 val1 <<= shift_left;
444 val2 <<= shift_right;
445 spin_lock_irqsave(&chip->reg_lock, flags);
446 if (left_reg != right_reg) {
447 oval1 = chip->ctlregs[left_reg];
448 oval2 = chip->ctlregs[right_reg];
449 val1 = (oval1 & ~(mask << shift_left)) | val1;
450 val2 = (oval2 & ~(mask << shift_right)) | val2;
451 change = val1 != oval1 || val2 != oval2;
452 __snd_opl3sa2_write(chip, left_reg, val1);
453 __snd_opl3sa2_write(chip, right_reg, val2);
454 } else {
455 oval1 = chip->ctlregs[left_reg];
456 val1 = (oval1 & ~((mask << shift_left) | (mask << shift_right))) | val1 | val2;
457 change = val1 != oval1;
458 __snd_opl3sa2_write(chip, left_reg, val1);
459 }
460 spin_unlock_irqrestore(&chip->reg_lock, flags);
461 return change;
462}
463
464static snd_kcontrol_new_t snd_opl3sa2_controls[] = {
465OPL3SA2_DOUBLE("Master Playback Switch", 0, 0x07, 0x08, 7, 7, 1, 1),
466OPL3SA2_DOUBLE("Master Playback Volume", 0, 0x07, 0x08, 0, 0, 15, 1),
467OPL3SA2_SINGLE("Mic Playback Switch", 0, 0x09, 7, 1, 1),
468OPL3SA2_SINGLE("Mic Playback Volume", 0, 0x09, 0, 31, 1)
469};
470
471static snd_kcontrol_new_t snd_opl3sa2_tone_controls[] = {
472OPL3SA2_DOUBLE("3D Control - Wide", 0, 0x14, 0x14, 4, 0, 7, 0),
473OPL3SA2_DOUBLE("Tone Control - Bass", 0, 0x15, 0x15, 4, 0, 7, 0),
474OPL3SA2_DOUBLE("Tone Control - Treble", 0, 0x16, 0x16, 4, 0, 7, 0)
475};
476
477static void snd_opl3sa2_master_free(snd_kcontrol_t *kcontrol)
478{
479 opl3sa2_t *chip = snd_kcontrol_chip(kcontrol);
480 chip->master_switch = NULL;
481 chip->master_volume = NULL;
482}
483
484static int __init snd_opl3sa2_mixer(opl3sa2_t *chip)
485{
486 snd_card_t *card = chip->card;
487 snd_ctl_elem_id_t id1, id2;
488 snd_kcontrol_t *kctl;
489 unsigned int idx;
490 int err;
491
492 memset(&id1, 0, sizeof(id1));
493 memset(&id2, 0, sizeof(id2));
494 id1.iface = id2.iface = SNDRV_CTL_ELEM_IFACE_MIXER;
495 /* reassign AUX0 to CD */
496 strcpy(id1.name, "Aux Playback Switch");
497 strcpy(id2.name, "CD Playback Switch");
498 if ((err = snd_ctl_rename_id(card, &id1, &id2)) < 0)
499 return err;
500 strcpy(id1.name, "Aux Playback Volume");
501 strcpy(id2.name, "CD Playback Volume");
502 if ((err = snd_ctl_rename_id(card, &id1, &id2)) < 0)
503 return err;
504 /* reassign AUX1 to FM */
505 strcpy(id1.name, "Aux Playback Switch"); id1.index = 1;
506 strcpy(id2.name, "FM Playback Switch");
507 if ((err = snd_ctl_rename_id(card, &id1, &id2)) < 0)
508 return err;
509 strcpy(id1.name, "Aux Playback Volume");
510 strcpy(id2.name, "FM Playback Volume");
511 if ((err = snd_ctl_rename_id(card, &id1, &id2)) < 0)
512 return err;
513 /* add OPL3SA2 controls */
514 for (idx = 0; idx < ARRAY_SIZE(snd_opl3sa2_controls); idx++) {
515 if ((err = snd_ctl_add(card, kctl = snd_ctl_new1(&snd_opl3sa2_controls[idx], chip))) < 0)
516 return err;
517 switch (idx) {
518 case 0: chip->master_switch = kctl; kctl->private_free = snd_opl3sa2_master_free; break;
519 case 1: chip->master_volume = kctl; kctl->private_free = snd_opl3sa2_master_free; break;
520 }
521 }
522 if (chip->version > 2) {
523 for (idx = 0; idx < ARRAY_SIZE(snd_opl3sa2_tone_controls); idx++)
524 if ((err = snd_ctl_add(card, snd_ctl_new1(&snd_opl3sa2_tone_controls[idx], chip))) < 0)
525 return err;
526 }
527 return 0;
528}
529
530/* Power Management support functions */
531#ifdef CONFIG_PM
532static int snd_opl3sa2_suspend(snd_card_t *card, pm_message_t state)
533{
534 opl3sa2_t *chip = card->pm_private_data;
535
536 snd_pcm_suspend_all(chip->cs4231->pcm); /* stop before saving regs */
537 chip->cs4231_suspend(chip->cs4231);
538
539 /* power down */
540 snd_opl3sa2_write(chip, OPL3SA2_PM_CTRL, OPL3SA2_PM_D3);
541
542 return 0;
543}
544
545static int snd_opl3sa2_resume(snd_card_t *card)
546{
547 opl3sa2_t *chip = card->pm_private_data;
548 int i;
549
550 /* power up */
551 snd_opl3sa2_write(chip, OPL3SA2_PM_CTRL, OPL3SA2_PM_D0);
552
553 /* restore registers */
554 for (i = 2; i <= 0x0a; i++) {
555 if (i != OPL3SA2_IRQ_STATUS)
556 snd_opl3sa2_write(chip, i, chip->ctlregs[i]);
557 }
558 if (chip->version > 2) {
559 for (i = 0x12; i <= 0x16; i++)
560 snd_opl3sa2_write(chip, i, chip->ctlregs[i]);
561 }
562 /* restore cs4231 */
563 chip->cs4231_resume(chip->cs4231);
564
565 return 0;
566}
567#endif /* CONFIG_PM */
568
569#ifdef CONFIG_PNP
570static int __init snd_opl3sa2_pnp(int dev, opl3sa2_t *chip,
571 struct pnp_card_link *card,
572 const struct pnp_card_device_id *id)
573{
574 struct pnp_dev *pdev;
575 struct pnp_resource_table * cfg = kmalloc(sizeof(struct pnp_resource_table), GFP_KERNEL);
576 int err;
577
578 if (!cfg)
579 return -ENOMEM;
580 pdev = chip->dev = pnp_request_card_device(card, id->devs[0].id, NULL);
581 if (chip->dev == NULL) {
582 kfree(cfg);
583 return -EBUSY;
584 }
585 /* PnP initialization */
586 pnp_init_resource_table(cfg);
587 if (sb_port[dev] != SNDRV_AUTO_PORT)
588 pnp_resource_change(&cfg->port_resource[0], sb_port[dev], 16);
589 if (wss_port[dev] != SNDRV_AUTO_PORT)
590 pnp_resource_change(&cfg->port_resource[1], wss_port[dev], 8);
591 if (fm_port[dev] != SNDRV_AUTO_PORT)
592 pnp_resource_change(&cfg->port_resource[2], fm_port[dev], 4);
593 if (midi_port[dev] != SNDRV_AUTO_PORT)
594 pnp_resource_change(&cfg->port_resource[3], midi_port[dev], 2);
595 if (port[dev] != SNDRV_AUTO_PORT)
596 pnp_resource_change(&cfg->port_resource[4], port[dev], 2);
597 if (dma1[dev] != SNDRV_AUTO_DMA)
598 pnp_resource_change(&cfg->dma_resource[0], dma1[dev], 1);
599 if (dma2[dev] != SNDRV_AUTO_DMA)
600 pnp_resource_change(&cfg->dma_resource[1], dma2[dev], 1);
601 if (irq[dev] != SNDRV_AUTO_IRQ)
602 pnp_resource_change(&cfg->irq_resource[0], irq[dev], 1);
603 err = pnp_manual_config_dev(pdev, cfg, 0);
604 if (err < 0)
605 snd_printk(KERN_ERR "PnP manual resources are invalid, using auto config\n");
606 err = pnp_activate_dev(pdev);
607 if (err < 0) {
608 kfree(cfg);
609 snd_printk(KERN_ERR "PnP configure failure (out of resources?) err = %d\n", err);
610 return -EBUSY;
611 }
612 sb_port[dev] = pnp_port_start(pdev, 0);
613 wss_port[dev] = pnp_port_start(pdev, 1);
614 fm_port[dev] = pnp_port_start(pdev, 2);
615 midi_port[dev] = pnp_port_start(pdev, 3);
616 port[dev] = pnp_port_start(pdev, 4);
617 dma1[dev] = pnp_dma(pdev, 0);
618 dma2[dev] = pnp_dma(pdev, 1);
619 irq[dev] = pnp_irq(pdev, 0);
620 snd_printdd("PnP OPL3-SA: sb port=0x%lx, wss port=0x%lx, fm port=0x%lx, midi port=0x%lx\n",
621 sb_port[dev], wss_port[dev], fm_port[dev], midi_port[dev]);
622 snd_printdd("PnP OPL3-SA: control port=0x%lx, dma1=%i, dma2=%i, irq=%i\n",
623 port[dev], dma1[dev], dma2[dev], irq[dev]);
624 kfree(cfg);
625 return 0;
626}
627#endif /* CONFIG_PNP */
628
629static int snd_opl3sa2_free(opl3sa2_t *chip)
630{
631 if (chip->irq >= 0)
632 free_irq(chip->irq, (void *)chip);
633 if (chip->res_port) {
634 release_resource(chip->res_port);
635 kfree_nocheck(chip->res_port);
636 }
637 kfree(chip);
638 return 0;
639}
640
641static int snd_opl3sa2_dev_free(snd_device_t *device)
642{
643 opl3sa2_t *chip = device->device_data;
644 return snd_opl3sa2_free(chip);
645}
646
647static int __devinit snd_opl3sa2_probe(int dev,
648 struct pnp_card_link *pcard,
649 const struct pnp_card_device_id *pid)
650{
651 int xirq, xdma1, xdma2;
652 snd_card_t *card;
653 struct snd_opl3sa2 *chip;
654 cs4231_t *cs4231;
655 opl3_t *opl3;
656 static snd_device_ops_t ops = {
657 .dev_free = snd_opl3sa2_dev_free,
658 };
659 int err;
660
661#ifdef CONFIG_PNP
662 if (!isapnp[dev]) {
663#endif
664 if (port[dev] == SNDRV_AUTO_PORT) {
665 snd_printk("specify port\n");
666 return -EINVAL;
667 }
668 if (wss_port[dev] == SNDRV_AUTO_PORT) {
669 snd_printk("specify wss_port\n");
670 return -EINVAL;
671 }
672 if (fm_port[dev] == SNDRV_AUTO_PORT) {
673 snd_printk("specify fm_port\n");
674 return -EINVAL;
675 }
676 if (midi_port[dev] == SNDRV_AUTO_PORT) {
677 snd_printk("specify midi_port\n");
678 return -EINVAL;
679 }
680#ifdef CONFIG_PNP
681 }
682#endif
683 card = snd_card_new(index[dev], id[dev], THIS_MODULE, 0);
684 if (card == NULL)
685 return -ENOMEM;
686 strcpy(card->driver, "OPL3SA2");
687 strcpy(card->shortname, "Yamaha OPL3-SA2");
688 chip = kcalloc(1, sizeof(*chip), GFP_KERNEL);
689 if (chip == NULL) {
690 err = -ENOMEM;
691 goto __error;
692 }
693 spin_lock_init(&chip->reg_lock);
694 chip->irq = -1;
695 if ((err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops)) < 0)
696 goto __error;
697#ifdef CONFIG_PNP
698 if (isapnp[dev]) {
699 if ((err = snd_opl3sa2_pnp(dev, chip, pcard, pid)) < 0)
700 goto __error;
701 snd_card_set_dev(card, &pcard->card->dev);
702 }
703#endif
704 chip->ymode = opl3sa3_ymode[dev] & 0x03 ; /* initialise this card from supplied (or default) parameter*/
705 chip->card = card;
706 chip->port = port[dev];
707 xirq = irq[dev];
708 xdma1 = dma1[dev];
709 xdma2 = dma2[dev];
710 if (xdma2 < 0)
711 chip->single_dma = 1;
712 if ((err = snd_opl3sa2_detect(chip)) < 0)
713 goto __error;
714 if (request_irq(xirq, snd_opl3sa2_interrupt, SA_INTERRUPT, "OPL3-SA2", (void *)chip)) {
715 snd_printk(KERN_ERR "opl3sa2: can't grab IRQ %d\n", xirq);
716 err = -ENODEV;
717 goto __error;
718 }
719 chip->irq = xirq;
720 if ((err = snd_cs4231_create(card,
721 wss_port[dev] + 4, -1,
722 xirq, xdma1, xdma2,
723 CS4231_HW_OPL3SA2,
724 CS4231_HWSHARE_IRQ,
725 &cs4231)) < 0) {
726 snd_printd("Oops, WSS not detected at 0x%lx\n", wss_port[dev] + 4);
727 goto __error;
728 }
729 chip->cs4231 = cs4231;
730 if ((err = snd_cs4231_pcm(cs4231, 0, NULL)) < 0)
731 goto __error;
732 if ((err = snd_cs4231_mixer(cs4231)) < 0)
733 goto __error;
734 if ((err = snd_opl3sa2_mixer(chip)) < 0)
735 goto __error;
736 if ((err = snd_cs4231_timer(cs4231, 0, NULL)) < 0)
737 goto __error;
738 if (fm_port[dev] >= 0x340 && fm_port[dev] < 0x400) {
739 if ((err = snd_opl3_create(card, fm_port[dev],
740 fm_port[dev] + 2,
741 OPL3_HW_OPL3, 0, &opl3)) < 0)
742 goto __error;
743 if ((err = snd_opl3_timer_new(opl3, 1, 2)) < 0)
744 goto __error;
745 if ((err = snd_opl3_hwdep_new(opl3, 0, 1, &chip->synth)) < 0)
746 goto __error;
747 }
748 if (midi_port[dev] >= 0x300 && midi_port[dev] < 0x340) {
749 if ((err = snd_mpu401_uart_new(card, 0, MPU401_HW_OPL3SA2,
750 midi_port[dev], 0,
751 xirq, 0, &chip->rmidi)) < 0)
752 goto __error;
753 }
754#ifdef CONFIG_PM
755 chip->cs4231_suspend = chip->cs4231->suspend;
756 chip->cs4231_resume = chip->cs4231->resume;
757 /* now clear callbacks for cs4231 */
758 chip->cs4231->suspend = NULL;
759 chip->cs4231->resume = NULL;
760 snd_card_set_isa_pm_callback(card, snd_opl3sa2_suspend, snd_opl3sa2_resume, chip);
761#endif
762
763 sprintf(card->longname, "%s at 0x%lx, irq %d, dma %d",
764 card->shortname, chip->port, xirq, xdma1);
765 if (dma2 >= 0)
766 sprintf(card->longname + strlen(card->longname), "&%d", xdma2);
767
768 if ((err = snd_card_register(card)) < 0)
769 goto __error;
770
771 if (pcard)
772 pnp_set_card_drvdata(pcard, card);
773 else
774 snd_opl3sa2_legacy[dev] = card;
775 return 0;
776
777 __error:
778 snd_card_free(card);
779 return err;
780}
781
782#ifdef CONFIG_PNP
783static int __devinit snd_opl3sa2_pnp_detect(struct pnp_card_link *card,
784 const struct pnp_card_device_id *id)
785{
786 static int dev;
787 int res;
788
789 for ( ; dev < SNDRV_CARDS; dev++) {
790 if (!enable[dev] || !isapnp[dev])
791 continue;
792 res = snd_opl3sa2_probe(dev, card, id);
793 if (res < 0)
794 return res;
795 dev++;
796 return 0;
797 }
798 return -ENODEV;
799}
800
801static void __devexit snd_opl3sa2_pnp_remove(struct pnp_card_link * pcard)
802{
803 snd_card_t *card = (snd_card_t *) pnp_get_card_drvdata(pcard);
804
805 snd_card_disconnect(card);
806 snd_card_free_in_thread(card);
807}
808
809static struct pnp_card_driver opl3sa2_pnpc_driver = {
810 .flags = PNP_DRIVER_RES_DISABLE,
811 .name = "opl3sa2",
812 .id_table = snd_opl3sa2_pnpids,
813 .probe = snd_opl3sa2_pnp_detect,
814 .remove = __devexit_p(snd_opl3sa2_pnp_remove),
815};
816#endif /* CONFIG_PNP */
817
818static int __init alsa_card_opl3sa2_init(void)
819{
820 int dev, cards = 0;
821
822 for (dev = 0; dev < SNDRV_CARDS; dev++) {
823 if (!enable[dev])
824 continue;
825#ifdef CONFIG_PNP
826 if (isapnp[dev])
827 continue;
828#endif
829 if (snd_opl3sa2_probe(dev, NULL, NULL) >= 0)
830 cards++;
831 }
832#ifdef CONFIG_PNP
833 cards += pnp_register_card_driver(&opl3sa2_pnpc_driver);
834#endif
835 if (!cards) {
836#ifdef MODULE
837 snd_printk(KERN_ERR "Yamaha OPL3-SA soundcard not found or device busy\n");
838#endif
839#ifdef CONFIG_PNP
840 pnp_unregister_card_driver(&opl3sa2_pnpc_driver);
841#endif
842 return -ENODEV;
843 }
844 return 0;
845}
846
847static void __exit alsa_card_opl3sa2_exit(void)
848{
849 int idx;
850
851#ifdef CONFIG_PNP
852 /* PnP cards first */
853 pnp_unregister_card_driver(&opl3sa2_pnpc_driver);
854#endif
855 for (idx = 0; idx < SNDRV_CARDS; idx++)
856 snd_card_free(snd_opl3sa2_legacy[idx]);
857}
858
859module_init(alsa_card_opl3sa2_init)
860module_exit(alsa_card_opl3sa2_exit)
diff --git a/sound/isa/opti9xx/Makefile b/sound/isa/opti9xx/Makefile
new file mode 100644
index 000000000000..28c64070cd56
--- /dev/null
+++ b/sound/isa/opti9xx/Makefile
@@ -0,0 +1,13 @@
1#
2# Makefile for ALSA
3# Copyright (c) 2001 by Jaroslav Kysela <perex@suse.cz>
4#
5
6snd-opti92x-ad1848-objs := opti92x-ad1848.o
7snd-opti92x-cs4231-objs := opti92x-cs4231.o
8snd-opti93x-objs := opti93x.o
9
10# Toplevel Module Dependency
11obj-$(CONFIG_SND_OPTI92X_AD1848) += snd-opti92x-ad1848.o
12obj-$(CONFIG_SND_OPTI92X_CS4231) += snd-opti92x-cs4231.o
13obj-$(CONFIG_SND_OPTI93X) += snd-opti93x.o
diff --git a/sound/isa/opti9xx/opti92x-ad1848.c b/sound/isa/opti9xx/opti92x-ad1848.c
new file mode 100644
index 000000000000..411a702d85ba
--- /dev/null
+++ b/sound/isa/opti9xx/opti92x-ad1848.c
@@ -0,0 +1,2226 @@
1/*
2 card-opti92x-ad1848.c - driver for OPTi 82c92x based soundcards.
3 Copyright (C) 1998-2000 by Massimo Piccioni <dafastidio@libero.it>
4
5 Part of this code was developed at the Italian Ministry of Air Defence,
6 Sixth Division (oh, che pace ...), Rome.
7
8 Thanks to Maria Grazia Pollarini, Salvatore Vassallo.
9
10 This program is free software; you can redistribute it and/or modify
11 it under the terms of the GNU General Public License as published by
12 the Free Software Foundation; either version 2 of the License, or
13 (at your option) any later version.
14
15 This program is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 GNU General Public License for more details.
19
20 You should have received a copy of the GNU General Public License
21 along with this program; if not, write to the Free Software
22 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
23*/
24
25
26#include <sound/driver.h>
27#include <asm/io.h>
28#include <asm/dma.h>
29#include <linux/delay.h>
30#include <linux/init.h>
31#include <linux/slab.h>
32#include <linux/pnp.h>
33#include <linux/moduleparam.h>
34#include <sound/core.h>
35#ifdef CS4231
36#include <sound/cs4231.h>
37#else
38#ifndef OPTi93X
39#include <sound/ad1848.h>
40#else
41#include <sound/control.h>
42#include <sound/pcm.h>
43#endif /* OPTi93X */
44#endif /* CS4231 */
45#include <sound/mpu401.h>
46#include <sound/opl3.h>
47#ifndef OPTi93X
48#include <sound/opl4.h>
49#endif
50#define SNDRV_LEGACY_FIND_FREE_IRQ
51#define SNDRV_LEGACY_FIND_FREE_DMA
52#include <sound/initval.h>
53
54MODULE_AUTHOR("Massimo Piccioni <dafastidio@libero.it>");
55MODULE_LICENSE("GPL");
56#ifdef OPTi93X
57MODULE_DESCRIPTION("OPTi93X");
58MODULE_SUPPORTED_DEVICE("{{OPTi,82C931/3}}");
59#else /* OPTi93X */
60#ifdef CS4231
61MODULE_DESCRIPTION("OPTi92X - CS4231");
62MODULE_SUPPORTED_DEVICE("{{OPTi,82C924 (CS4231)},"
63 "{OPTi,82C925 (CS4231)}}");
64#else /* CS4231 */
65MODULE_DESCRIPTION("OPTi92X - AD1848");
66MODULE_SUPPORTED_DEVICE("{{OPTi,82C924 (AD1848)},"
67 "{OPTi,82C925 (AD1848)},"
68 "{OAK,Mozart}}");
69#endif /* CS4231 */
70#endif /* OPTi93X */
71
72static int index = SNDRV_DEFAULT_IDX1; /* Index 0-MAX */
73static char *id = SNDRV_DEFAULT_STR1; /* ID for this card */
74//static int enable = SNDRV_DEFAULT_ENABLE1; /* Enable this card */
75static int isapnp = 1; /* Enable ISA PnP detection */
76static long port = SNDRV_DEFAULT_PORT1; /* 0x530,0xe80,0xf40,0x604 */
77static long mpu_port = SNDRV_DEFAULT_PORT1; /* 0x300,0x310,0x320,0x330 */
78static long fm_port = SNDRV_DEFAULT_PORT1; /* 0x388 */
79static int irq = SNDRV_DEFAULT_IRQ1; /* 5,7,9,10,11 */
80static int mpu_irq = SNDRV_DEFAULT_IRQ1; /* 5,7,9,10 */
81static int dma1 = SNDRV_DEFAULT_DMA1; /* 0,1,3 */
82#if defined(CS4231) || defined(OPTi93X)
83static int dma2 = SNDRV_DEFAULT_DMA1; /* 0,1,3 */
84#endif /* CS4231 || OPTi93X */
85
86module_param(index, int, 0444);
87MODULE_PARM_DESC(index, "Index value for opti9xx based soundcard.");
88module_param(id, charp, 0444);
89MODULE_PARM_DESC(id, "ID string for opti9xx based soundcard.");
90//module_param(enable, bool, 0444);
91//MODULE_PARM_DESC(enable, "Enable opti9xx soundcard.");
92module_param(isapnp, bool, 0444);
93MODULE_PARM_DESC(isapnp, "Enable ISA PnP detection for specified soundcard.");
94module_param(port, long, 0444);
95MODULE_PARM_DESC(port, "WSS port # for opti9xx driver.");
96module_param(mpu_port, long, 0444);
97MODULE_PARM_DESC(mpu_port, "MPU-401 port # for opti9xx driver.");
98module_param(fm_port, long, 0444);
99MODULE_PARM_DESC(fm_port, "FM port # for opti9xx driver.");
100module_param(irq, int, 0444);
101MODULE_PARM_DESC(irq, "WSS irq # for opti9xx driver.");
102module_param(mpu_irq, int, 0444);
103MODULE_PARM_DESC(mpu_irq, "MPU-401 irq # for opti9xx driver.");
104module_param(dma1, int, 0444);
105MODULE_PARM_DESC(dma1, "1st dma # for opti9xx driver.");
106#if defined(CS4231) || defined(OPTi93X)
107module_param(dma2, int, 0444);
108MODULE_PARM_DESC(dma2, "2nd dma # for opti9xx driver.");
109#endif /* CS4231 || OPTi93X */
110
111#define OPTi9XX_HW_DETECT 0
112#define OPTi9XX_HW_82C928 1
113#define OPTi9XX_HW_82C929 2
114#define OPTi9XX_HW_82C924 3
115#define OPTi9XX_HW_82C925 4
116#define OPTi9XX_HW_82C930 5
117#define OPTi9XX_HW_82C931 6
118#define OPTi9XX_HW_82C933 7
119#define OPTi9XX_HW_LAST OPTi9XX_HW_82C933
120
121#define OPTi9XX_MC_REG(n) n
122
123typedef struct _snd_opti9xx opti9xx_t;
124
125#ifdef OPTi93X
126
127#define OPTi93X_INDEX 0x00
128#define OPTi93X_DATA 0x01
129#define OPTi93X_STATUS 0x02
130#define OPTi93X_DDATA 0x03
131#define OPTi93X_PORT(chip, r) ((chip)->port + OPTi93X_##r)
132
133#define OPTi93X_MIXOUT_LEFT 0x00
134#define OPTi93X_MIXOUT_RIGHT 0x01
135#define OPTi93X_CD_LEFT_INPUT 0x02
136#define OPTi93X_CD_RIGHT_INPUT 0x03
137#define OPTi930_AUX_LEFT_INPUT 0x04
138#define OPTi930_AUX_RIGHT_INPUT 0x05
139#define OPTi931_FM_LEFT_INPUT 0x04
140#define OPTi931_FM_RIGHT_INPUT 0x05
141#define OPTi93X_DAC_LEFT 0x06
142#define OPTi93X_DAC_RIGHT 0x07
143#define OPTi93X_PLAY_FORMAT 0x08
144#define OPTi93X_IFACE_CONF 0x09
145#define OPTi93X_PIN_CTRL 0x0a
146#define OPTi93X_ERR_INIT 0x0b
147#define OPTi93X_ID 0x0c
148#define OPTi93X_PLAY_UPR_CNT 0x0e
149#define OPTi93X_PLAY_LWR_CNT 0x0f
150#define OPTi931_AUX_LEFT_INPUT 0x10
151#define OPTi931_AUX_RIGHT_INPUT 0x11
152#define OPTi93X_LINE_LEFT_INPUT 0x12
153#define OPTi93X_LINE_RIGHT_INPUT 0x13
154#define OPTi93X_MIC_LEFT_INPUT 0x14
155#define OPTi93X_MIC_RIGHT_INPUT 0x15
156#define OPTi93X_OUT_LEFT 0x16
157#define OPTi93X_OUT_RIGHT 0x17
158#define OPTi93X_CAPT_FORMAT 0x1c
159#define OPTi93X_CAPT_UPR_CNT 0x1e
160#define OPTi93X_CAPT_LWR_CNT 0x1f
161
162#define OPTi93X_TRD 0x20
163#define OPTi93X_MCE 0x40
164#define OPTi93X_INIT 0x80
165
166#define OPTi93X_MIXOUT_MIC_GAIN 0x20
167#define OPTi93X_MIXOUT_LINE 0x00
168#define OPTi93X_MIXOUT_CD 0x40
169#define OPTi93X_MIXOUT_MIC 0x80
170#define OPTi93X_MIXOUT_MIXER 0xc0
171
172#define OPTi93X_STEREO 0x10
173#define OPTi93X_LINEAR_8 0x00
174#define OPTi93X_ULAW_8 0x20
175#define OPTi93X_LINEAR_16_LIT 0x40
176#define OPTi93X_ALAW_8 0x60
177#define OPTi93X_ADPCM_16 0xa0
178#define OPTi93X_LINEAR_16_BIG 0xc0
179
180#define OPTi93X_CAPTURE_PIO 0x80
181#define OPTi93X_PLAYBACK_PIO 0x40
182#define OPTi93X_AUTOCALIB 0x08
183#define OPTi93X_SINGLE_DMA 0x04
184#define OPTi93X_CAPTURE_ENABLE 0x02
185#define OPTi93X_PLAYBACK_ENABLE 0x01
186
187#define OPTi93X_IRQ_ENABLE 0x02
188
189#define OPTi93X_DMA_REQUEST 0x10
190#define OPTi93X_CALIB_IN_PROGRESS 0x20
191
192#define OPTi93X_IRQ_PLAYBACK 0x04
193#define OPTi93X_IRQ_CAPTURE 0x08
194
195
196typedef struct _snd_opti93x opti93x_t;
197
198struct _snd_opti93x {
199 unsigned long port;
200 struct resource *res_port;
201 int irq;
202 int dma1;
203 int dma2;
204
205 opti9xx_t *chip;
206 unsigned short hardware;
207 unsigned char image[32];
208
209 unsigned char mce_bit;
210 unsigned short mode;
211 int mute;
212
213 spinlock_t lock;
214
215 snd_card_t *card;
216 snd_pcm_t *pcm;
217 snd_pcm_substream_t *playback_substream;
218 snd_pcm_substream_t *capture_substream;
219 unsigned int p_dma_size;
220 unsigned int c_dma_size;
221};
222
223#define OPTi93X_MODE_NONE 0x00
224#define OPTi93X_MODE_PLAY 0x01
225#define OPTi93X_MODE_CAPTURE 0x02
226#define OPTi93X_MODE_OPEN (OPTi93X_MODE_PLAY | OPTi93X_MODE_CAPTURE)
227
228#endif /* OPTi93X */
229
230struct _snd_opti9xx {
231 unsigned short hardware;
232 unsigned char password;
233 char name[7];
234
235 unsigned long mc_base;
236 struct resource *res_mc_base;
237 unsigned long mc_base_size;
238#ifdef OPTi93X
239 unsigned long mc_indir_index;
240#endif /* OPTi93X */
241 unsigned long pwd_reg;
242
243 spinlock_t lock;
244
245 long wss_base;
246 int irq;
247 int dma1;
248#if defined(CS4231) || defined(OPTi93X)
249 int dma2;
250#endif /* CS4231 || OPTi93X */
251
252 long fm_port;
253
254 long mpu_port;
255 int mpu_irq;
256
257#ifdef CONFIG_PNP
258 struct pnp_dev *dev;
259 struct pnp_dev *devmpu;
260#endif /* CONFIG_PNP */
261};
262
263static int snd_opti9xx_first_hit = 1;
264static snd_card_t *snd_opti9xx_legacy = SNDRV_DEFAULT_PTR1;
265
266#ifdef CONFIG_PNP
267
268static struct pnp_card_device_id snd_opti9xx_pnpids[] = {
269#ifndef OPTi93X
270 /* OPTi 82C924 */
271 { .id = "OPT0924", .devs = { { "OPT0000" }, { "OPT0002" } }, .driver_data = 0x0924 },
272 /* OPTi 82C925 */
273 { .id = "OPT0925", .devs = { { "OPT9250" }, { "OPT0002" } }, .driver_data = 0x0925 },
274#else
275 /* OPTi 82C931/3 */
276 { .id = "OPT0931", .devs = { { "OPT9310" }, { "OPT0002" } }, .driver_data = 0x0931 },
277#endif /* OPTi93X */
278 { .id = "" }
279};
280
281MODULE_DEVICE_TABLE(pnp_card, snd_opti9xx_pnpids);
282
283#endif /* CONFIG_PNP */
284
285#ifdef OPTi93X
286#define DRIVER_NAME "snd-card-opti93x"
287#else
288#define DRIVER_NAME "snd-card-opti92x"
289#endif /* OPTi93X */
290
291static char * snd_opti9xx_names[] = {
292 "unkown",
293 "82C928", "82C929",
294 "82C924", "82C925",
295 "82C930", "82C931", "82C933"
296};
297
298
299static long snd_legacy_find_free_ioport(long *port_table, long size)
300{
301 while (*port_table != -1) {
302 struct resource *res;
303 if ((res = request_region(*port_table, size, "ALSA test")) != NULL) {
304 release_resource(res);
305 kfree_nocheck(res);
306 return *port_table;
307 }
308 port_table++;
309 }
310 return -1;
311}
312
313static int __devinit snd_opti9xx_init(opti9xx_t *chip, unsigned short hardware)
314{
315 static int opti9xx_mc_size[] = {7, 7, 10, 10, 2, 2, 2};
316
317 chip->hardware = hardware;
318 strcpy(chip->name, snd_opti9xx_names[hardware]);
319
320 chip->mc_base_size = opti9xx_mc_size[hardware];
321
322 spin_lock_init(&chip->lock);
323
324 chip->wss_base = -1;
325 chip->irq = -1;
326 chip->dma1 = -1;
327#if defined(CS4231) || defined (OPTi93X)
328 chip->dma2 = -1;
329#endif /* CS4231 || OPTi93X */
330 chip->fm_port = -1;
331 chip->mpu_port = -1;
332 chip->mpu_irq = -1;
333
334 switch (hardware) {
335#ifndef OPTi93X
336 case OPTi9XX_HW_82C928:
337 case OPTi9XX_HW_82C929:
338 chip->mc_base = 0xf8c;
339 chip->password = (hardware == OPTi9XX_HW_82C928) ? 0xe2 : 0xe3;
340 chip->pwd_reg = 3;
341 break;
342
343 case OPTi9XX_HW_82C924:
344 case OPTi9XX_HW_82C925:
345 chip->mc_base = 0xf8c;
346 chip->password = 0xe5;
347 chip->pwd_reg = 3;
348 break;
349#else /* OPTi93X */
350
351 case OPTi9XX_HW_82C930:
352 case OPTi9XX_HW_82C931:
353 case OPTi9XX_HW_82C933:
354 chip->mc_base = (hardware == OPTi9XX_HW_82C930) ? 0xf8f : 0xf8d;
355 chip->mc_indir_index = 0xe0e;
356 chip->password = 0xe4;
357 chip->pwd_reg = 0;
358 break;
359#endif /* OPTi93X */
360
361 default:
362 snd_printk("chip %d not supported\n", hardware);
363 return -ENODEV;
364 }
365 return 0;
366}
367
368static unsigned char snd_opti9xx_read(opti9xx_t *chip,
369 unsigned char reg)
370{
371 unsigned long flags;
372 unsigned char retval = 0xff;
373
374 spin_lock_irqsave(&chip->lock, flags);
375 outb(chip->password, chip->mc_base + chip->pwd_reg);
376
377 switch (chip->hardware) {
378#ifndef OPTi93X
379 case OPTi9XX_HW_82C924:
380 case OPTi9XX_HW_82C925:
381 if (reg > 7) {
382 outb(reg, chip->mc_base + 8);
383 outb(chip->password, chip->mc_base + chip->pwd_reg);
384 retval = inb(chip->mc_base + 9);
385 break;
386 }
387
388 case OPTi9XX_HW_82C928:
389 case OPTi9XX_HW_82C929:
390 retval = inb(chip->mc_base + reg);
391 break;
392#else /* OPTi93X */
393
394 case OPTi9XX_HW_82C930:
395 case OPTi9XX_HW_82C931:
396 case OPTi9XX_HW_82C933:
397 outb(reg, chip->mc_indir_index);
398 outb(chip->password, chip->mc_base + chip->pwd_reg);
399 retval = inb(chip->mc_indir_index + 1);
400 break;
401#endif /* OPTi93X */
402
403 default:
404 snd_printk("chip %d not supported\n", chip->hardware);
405 }
406
407 spin_unlock_irqrestore(&chip->lock, flags);
408 return retval;
409}
410
411static void snd_opti9xx_write(opti9xx_t *chip, unsigned char reg,
412 unsigned char value)
413{
414 unsigned long flags;
415
416 spin_lock_irqsave(&chip->lock, flags);
417 outb(chip->password, chip->mc_base + chip->pwd_reg);
418
419 switch (chip->hardware) {
420#ifndef OPTi93X
421 case OPTi9XX_HW_82C924:
422 case OPTi9XX_HW_82C925:
423 if (reg > 7) {
424 outb(reg, chip->mc_base + 8);
425 outb(chip->password, chip->mc_base + chip->pwd_reg);
426 outb(value, chip->mc_base + 9);
427 break;
428 }
429
430 case OPTi9XX_HW_82C928:
431 case OPTi9XX_HW_82C929:
432 outb(value, chip->mc_base + reg);
433 break;
434#else /* OPTi93X */
435
436 case OPTi9XX_HW_82C930:
437 case OPTi9XX_HW_82C931:
438 case OPTi9XX_HW_82C933:
439 outb(reg, chip->mc_indir_index);
440 outb(chip->password, chip->mc_base + chip->pwd_reg);
441 outb(value, chip->mc_indir_index + 1);
442 break;
443#endif /* OPTi93X */
444
445 default:
446 snd_printk("chip %d not supported\n", chip->hardware);
447 }
448
449 spin_unlock_irqrestore(&chip->lock, flags);
450}
451
452
453#define snd_opti9xx_write_mask(chip, reg, value, mask) \
454 snd_opti9xx_write(chip, reg, \
455 (snd_opti9xx_read(chip, reg) & ~(mask)) | ((value) & (mask)))
456
457
458static int __devinit snd_opti9xx_configure(opti9xx_t *chip)
459{
460 unsigned char wss_base_bits;
461 unsigned char irq_bits;
462 unsigned char dma_bits;
463 unsigned char mpu_port_bits = 0;
464 unsigned char mpu_irq_bits;
465
466 switch (chip->hardware) {
467#ifndef OPTi93X
468 case OPTi9XX_HW_82C924:
469 snd_opti9xx_write_mask(chip, OPTi9XX_MC_REG(4), 0xf0, 0xfc);
470 snd_opti9xx_write_mask(chip, OPTi9XX_MC_REG(6), 0x02, 0x02);
471
472 case OPTi9XX_HW_82C925:
473 snd_opti9xx_write_mask(chip, OPTi9XX_MC_REG(1), 0x80, 0x80);
474 snd_opti9xx_write_mask(chip, OPTi9XX_MC_REG(2), 0x00, 0x20);
475 snd_opti9xx_write_mask(chip, OPTi9XX_MC_REG(3), 0xf0, 0xff);
476#ifdef CS4231
477 snd_opti9xx_write_mask(chip, OPTi9XX_MC_REG(5), 0x02, 0x02);
478#else
479 snd_opti9xx_write_mask(chip, OPTi9XX_MC_REG(5), 0x00, 0x02);
480#endif /* CS4231 */
481 break;
482
483 case OPTi9XX_HW_82C928:
484 case OPTi9XX_HW_82C929:
485 snd_opti9xx_write_mask(chip, OPTi9XX_MC_REG(1), 0x80, 0x80);
486 snd_opti9xx_write_mask(chip, OPTi9XX_MC_REG(2), 0x00, 0x20);
487 /*
488 snd_opti9xx_write_mask(chip, OPTi9XX_MC_REG(3), 0xa2, 0xae);
489 */
490 snd_opti9xx_write_mask(chip, OPTi9XX_MC_REG(4), 0x00, 0x0c);
491#ifdef CS4231
492 snd_opti9xx_write_mask(chip, OPTi9XX_MC_REG(5), 0x02, 0x02);
493#else
494 snd_opti9xx_write_mask(chip, OPTi9XX_MC_REG(5), 0x00, 0x02);
495#endif /* CS4231 */
496 break;
497
498#else /* OPTi93X */
499 case OPTi9XX_HW_82C930:
500 case OPTi9XX_HW_82C931:
501 case OPTi9XX_HW_82C933:
502 snd_opti9xx_write_mask(chip, OPTi9XX_MC_REG(6), 0x02, 0x03);
503 snd_opti9xx_write_mask(chip, OPTi9XX_MC_REG(3), 0x00, 0xff);
504 snd_opti9xx_write_mask(chip, OPTi9XX_MC_REG(4), 0x10 |
505 (chip->hardware == OPTi9XX_HW_82C930 ? 0x00 : 0x04),
506 0x34);
507 snd_opti9xx_write_mask(chip, OPTi9XX_MC_REG(5), 0x20, 0xbf);
508 break;
509#endif /* OPTi93X */
510
511 default:
512 snd_printk("chip %d not supported\n", chip->hardware);
513 return -EINVAL;
514 }
515
516 switch (chip->wss_base) {
517 case 0x530:
518 wss_base_bits = 0x00;
519 break;
520 case 0x604:
521 wss_base_bits = 0x03;
522 break;
523 case 0xe80:
524 wss_base_bits = 0x01;
525 break;
526 case 0xf40:
527 wss_base_bits = 0x02;
528 break;
529 default:
530 snd_printk("WSS port 0x%lx not valid\n", chip->wss_base);
531 goto __skip_base;
532 }
533 snd_opti9xx_write_mask(chip, OPTi9XX_MC_REG(1), wss_base_bits << 4, 0x30);
534
535__skip_base:
536 switch (chip->irq) {
537//#ifdef OPTi93X
538 case 5:
539 irq_bits = 0x05;
540 break;
541//#endif /* OPTi93X */
542 case 7:
543 irq_bits = 0x01;
544 break;
545 case 9:
546 irq_bits = 0x02;
547 break;
548 case 10:
549 irq_bits = 0x03;
550 break;
551 case 11:
552 irq_bits = 0x04;
553 break;
554 default:
555 snd_printk("WSS irq # %d not valid\n", chip->irq);
556 goto __skip_resources;
557 }
558
559 switch (chip->dma1) {
560 case 0:
561 dma_bits = 0x01;
562 break;
563 case 1:
564 dma_bits = 0x02;
565 break;
566 case 3:
567 dma_bits = 0x03;
568 break;
569 default:
570 snd_printk("WSS dma1 # %d not valid\n", chip->dma1);
571 goto __skip_resources;
572 }
573
574#if defined(CS4231) || defined(OPTi93X)
575 if (chip->dma1 == chip->dma2) {
576 snd_printk("don't want to share dmas\n");
577 return -EBUSY;
578 }
579
580 switch (chip->dma2) {
581 case 0:
582 case 1:
583 break;
584 default:
585 snd_printk("WSS dma2 # %d not valid\n", chip->dma2);
586 goto __skip_resources;
587 }
588 dma_bits |= 0x04;
589#endif /* CS4231 || OPTi93X */
590
591#ifndef OPTi93X
592 outb(irq_bits << 3 | dma_bits, chip->wss_base);
593#else /* OPTi93X */
594 snd_opti9xx_write(chip, OPTi9XX_MC_REG(3), (irq_bits << 3 | dma_bits));
595#endif /* OPTi93X */
596
597__skip_resources:
598 if (chip->hardware > OPTi9XX_HW_82C928) {
599 switch (chip->mpu_port) {
600 case 0:
601 case -1:
602 break;
603 case 0x300:
604 mpu_port_bits = 0x03;
605 break;
606 case 0x310:
607 mpu_port_bits = 0x02;
608 break;
609 case 0x320:
610 mpu_port_bits = 0x01;
611 break;
612 case 0x330:
613 mpu_port_bits = 0x00;
614 break;
615 default:
616 snd_printk("MPU-401 port 0x%lx not valid\n",
617 chip->mpu_port);
618 goto __skip_mpu;
619 }
620
621 switch (chip->mpu_irq) {
622 case 5:
623 mpu_irq_bits = 0x02;
624 break;
625 case 7:
626 mpu_irq_bits = 0x03;
627 break;
628 case 9:
629 mpu_irq_bits = 0x00;
630 break;
631 case 10:
632 mpu_irq_bits = 0x01;
633 break;
634 default:
635 snd_printk("MPU-401 irq # %d not valid\n",
636 chip->mpu_irq);
637 goto __skip_mpu;
638 }
639
640 snd_opti9xx_write_mask(chip, OPTi9XX_MC_REG(6),
641 (chip->mpu_port <= 0) ? 0x00 :
642 0x80 | mpu_port_bits << 5 | mpu_irq_bits << 3,
643 0xf8);
644 }
645__skip_mpu:
646
647 return 0;
648}
649
650#ifdef OPTi93X
651
652static unsigned char snd_opti93x_default_image[32] =
653{
654 0x00, /* 00/00 - l_mixout_outctrl */
655 0x00, /* 01/01 - r_mixout_outctrl */
656 0x88, /* 02/02 - l_cd_inctrl */
657 0x88, /* 03/03 - r_cd_inctrl */
658 0x88, /* 04/04 - l_a1/fm_inctrl */
659 0x88, /* 05/05 - r_a1/fm_inctrl */
660 0x80, /* 06/06 - l_dac_inctrl */
661 0x80, /* 07/07 - r_dac_inctrl */
662 0x00, /* 08/08 - ply_dataform_reg */
663 0x00, /* 09/09 - if_conf */
664 0x00, /* 0a/10 - pin_ctrl */
665 0x00, /* 0b/11 - err_init_reg */
666 0x0a, /* 0c/12 - id_reg */
667 0x00, /* 0d/13 - reserved */
668 0x00, /* 0e/14 - ply_upcount_reg */
669 0x00, /* 0f/15 - ply_lowcount_reg */
670 0x88, /* 10/16 - reserved/l_a1_inctrl */
671 0x88, /* 11/17 - reserved/r_a1_inctrl */
672 0x88, /* 12/18 - l_line_inctrl */
673 0x88, /* 13/19 - r_line_inctrl */
674 0x88, /* 14/20 - l_mic_inctrl */
675 0x88, /* 15/21 - r_mic_inctrl */
676 0x80, /* 16/22 - l_out_outctrl */
677 0x80, /* 17/23 - r_out_outctrl */
678 0x00, /* 18/24 - reserved */
679 0x00, /* 19/25 - reserved */
680 0x00, /* 1a/26 - reserved */
681 0x00, /* 1b/27 - reserved */
682 0x00, /* 1c/28 - cap_dataform_reg */
683 0x00, /* 1d/29 - reserved */
684 0x00, /* 1e/30 - cap_upcount_reg */
685 0x00 /* 1f/31 - cap_lowcount_reg */
686};
687
688
689static int snd_opti93x_busy_wait(opti93x_t *chip)
690{
691 int timeout;
692
693 for (timeout = 250; timeout-- > 0; udelay(10))
694 if (!(inb(OPTi93X_PORT(chip, INDEX)) & OPTi93X_INIT))
695 return 0;
696
697 snd_printk("chip still busy.\n");
698 return -EBUSY;
699}
700
701static unsigned char snd_opti93x_in(opti93x_t *chip, unsigned char reg)
702{
703 snd_opti93x_busy_wait(chip);
704 outb(chip->mce_bit | (reg & 0x1f), OPTi93X_PORT(chip, INDEX));
705 return inb(OPTi93X_PORT(chip, DATA));
706}
707
708static void snd_opti93x_out(opti93x_t *chip, unsigned char reg,
709 unsigned char value)
710{
711 snd_opti93x_busy_wait(chip);
712 outb(chip->mce_bit | (reg & 0x1f), OPTi93X_PORT(chip, INDEX));
713 outb(value, OPTi93X_PORT(chip, DATA));
714}
715
716static void snd_opti93x_out_image(opti93x_t *chip, unsigned char reg,
717 unsigned char value)
718{
719 snd_opti93x_out(chip, reg, chip->image[reg] = value);
720}
721
722static void snd_opti93x_out_mask(opti93x_t *chip, unsigned char reg,
723 unsigned char mask, unsigned char value)
724{
725 snd_opti93x_out_image(chip, reg,
726 (chip->image[reg] & ~mask) | (value & mask));
727}
728
729
730static void snd_opti93x_mce_up(opti93x_t *chip)
731{
732 snd_opti93x_busy_wait(chip);
733
734 chip->mce_bit = OPTi93X_MCE;
735 if (!(inb(OPTi93X_PORT(chip, INDEX)) & OPTi93X_MCE))
736 outb(chip->mce_bit, OPTi93X_PORT(chip, INDEX));
737}
738
739static void snd_opti93x_mce_down(opti93x_t *chip)
740{
741 snd_opti93x_busy_wait(chip);
742
743 chip->mce_bit = 0;
744 if (inb(OPTi93X_PORT(chip, INDEX)) & OPTi93X_MCE)
745 outb(chip->mce_bit, OPTi93X_PORT(chip, INDEX));
746}
747
748#define snd_opti93x_mute_reg(chip, reg, mute) \
749 snd_opti93x_out(chip, reg, mute ? 0x80 : chip->image[reg]);
750
751static void snd_opti93x_mute(opti93x_t *chip, int mute)
752{
753 mute = mute ? 1 : 0;
754 if (chip->mute == mute)
755 return;
756
757 chip->mute = mute;
758
759 snd_opti93x_mute_reg(chip, OPTi93X_CD_LEFT_INPUT, mute);
760 snd_opti93x_mute_reg(chip, OPTi93X_CD_RIGHT_INPUT, mute);
761 switch (chip->hardware) {
762 case OPTi9XX_HW_82C930:
763 snd_opti93x_mute_reg(chip, OPTi930_AUX_LEFT_INPUT, mute);
764 snd_opti93x_mute_reg(chip, OPTi930_AUX_RIGHT_INPUT, mute);
765 break;
766 case OPTi9XX_HW_82C931:
767 case OPTi9XX_HW_82C933:
768 snd_opti93x_mute_reg(chip, OPTi931_FM_LEFT_INPUT, mute);
769 snd_opti93x_mute_reg(chip, OPTi931_FM_RIGHT_INPUT, mute);
770 snd_opti93x_mute_reg(chip, OPTi931_AUX_LEFT_INPUT, mute);
771 snd_opti93x_mute_reg(chip, OPTi931_AUX_RIGHT_INPUT, mute);
772 }
773 snd_opti93x_mute_reg(chip, OPTi93X_DAC_LEFT, mute);
774 snd_opti93x_mute_reg(chip, OPTi93X_DAC_RIGHT, mute);
775 snd_opti93x_mute_reg(chip, OPTi93X_LINE_LEFT_INPUT, mute);
776 snd_opti93x_mute_reg(chip, OPTi93X_LINE_RIGHT_INPUT, mute);
777 snd_opti93x_mute_reg(chip, OPTi93X_MIC_LEFT_INPUT, mute);
778 snd_opti93x_mute_reg(chip, OPTi93X_MIC_RIGHT_INPUT, mute);
779 snd_opti93x_mute_reg(chip, OPTi93X_OUT_LEFT, mute);
780 snd_opti93x_mute_reg(chip, OPTi93X_OUT_RIGHT, mute);
781}
782
783
784static unsigned int snd_opti93x_get_count(unsigned char format,
785 unsigned int size)
786{
787 switch (format & 0xe0) {
788 case OPTi93X_LINEAR_16_LIT:
789 case OPTi93X_LINEAR_16_BIG:
790 size >>= 1;
791 break;
792 case OPTi93X_ADPCM_16:
793 return size >> 2;
794 }
795 return (format & OPTi93X_STEREO) ? (size >> 1) : size;
796}
797
798static unsigned int rates[] = { 5512, 6615, 8000, 9600, 11025, 16000,
799 18900, 22050, 27428, 32000, 33075, 37800,
800 44100, 48000 };
801#define RATES ARRAY_SIZE(rates)
802
803static snd_pcm_hw_constraint_list_t hw_constraints_rates = {
804 .count = RATES,
805 .list = rates,
806 .mask = 0,
807};
808
809static unsigned char bits[] = { 0x01, 0x0f, 0x00, 0x0e, 0x03, 0x02,
810 0x05, 0x07, 0x04, 0x06, 0x0d, 0x09,
811 0x0b, 0x0c};
812
813static unsigned char snd_opti93x_get_freq(unsigned int rate)
814{
815 unsigned int i;
816
817 for (i = 0; i < RATES; i++) {
818 if (rate == rates[i])
819 return bits[i];
820 }
821 snd_BUG();
822 return bits[RATES-1];
823}
824
825static unsigned char snd_opti93x_get_format(opti93x_t *chip,
826 unsigned int format, int channels)
827{
828 unsigned char retval = OPTi93X_LINEAR_8;
829
830 switch (format) {
831 case SNDRV_PCM_FORMAT_MU_LAW:
832 retval = OPTi93X_ULAW_8;
833 break;
834 case SNDRV_PCM_FORMAT_A_LAW:
835 retval = OPTi93X_ALAW_8;
836 break;
837 case SNDRV_PCM_FORMAT_S16_LE:
838 retval = OPTi93X_LINEAR_16_LIT;
839 break;
840 case SNDRV_PCM_FORMAT_S16_BE:
841 retval = OPTi93X_LINEAR_16_BIG;
842 break;
843 case SNDRV_PCM_FORMAT_IMA_ADPCM:
844 retval = OPTi93X_ADPCM_16;
845 }
846 return (channels > 1) ? (retval | OPTi93X_STEREO) : retval;
847}
848
849
850static void snd_opti93x_playback_format(opti93x_t *chip, unsigned char fmt)
851{
852 unsigned char mask;
853
854 snd_opti93x_mute(chip, 1);
855
856 snd_opti93x_mce_up(chip);
857 mask = (chip->mode & OPTi93X_MODE_CAPTURE) ? 0xf0 : 0xff;
858 snd_opti93x_out_mask(chip, OPTi93X_PLAY_FORMAT, mask, fmt);
859 snd_opti93x_mce_down(chip);
860
861 snd_opti93x_mute(chip, 0);
862}
863
864static void snd_opti93x_capture_format(opti93x_t *chip, unsigned char fmt)
865{
866 snd_opti93x_mute(chip, 1);
867
868 snd_opti93x_mce_up(chip);
869 if (!(chip->mode & OPTi93X_MODE_PLAY))
870 snd_opti93x_out_mask(chip, OPTi93X_PLAY_FORMAT, 0x0f, fmt);
871 else
872 fmt = chip->image[OPTi93X_PLAY_FORMAT] & 0xf0;
873 snd_opti93x_out_image(chip, OPTi93X_CAPT_FORMAT, fmt);
874 snd_opti93x_mce_down(chip);
875
876 snd_opti93x_mute(chip, 0);
877}
878
879
880static int snd_opti93x_open(opti93x_t *chip, unsigned int mode)
881{
882 unsigned long flags;
883
884 spin_lock_irqsave(&chip->lock, flags);
885
886 if (chip->mode & mode) {
887 spin_unlock_irqrestore(&chip->lock, flags);
888 return -EAGAIN;
889 }
890
891 if (!(chip->mode & OPTi93X_MODE_OPEN)) {
892 outb(0x00, OPTi93X_PORT(chip, STATUS));
893 snd_opti93x_out_mask(chip, OPTi93X_PIN_CTRL,
894 OPTi93X_IRQ_ENABLE, OPTi93X_IRQ_ENABLE);
895 chip->mode = mode;
896 }
897 else
898 chip->mode |= mode;
899
900 spin_unlock_irqrestore(&chip->lock, flags);
901 return 0;
902}
903
904static void snd_opti93x_close(opti93x_t *chip, unsigned int mode)
905{
906 unsigned long flags;
907
908 spin_lock_irqsave(&chip->lock, flags);
909
910 chip->mode &= ~mode;
911 if (chip->mode & OPTi93X_MODE_OPEN) {
912 spin_unlock_irqrestore(&chip->lock, flags);
913 return;
914 }
915
916 snd_opti93x_mute(chip, 1);
917
918 outb(0, OPTi93X_PORT(chip, STATUS));
919 snd_opti93x_out_mask(chip, OPTi93X_PIN_CTRL, OPTi93X_IRQ_ENABLE,
920 ~OPTi93X_IRQ_ENABLE);
921
922 snd_opti93x_mce_up(chip);
923 snd_opti93x_out_image(chip, OPTi93X_IFACE_CONF, 0x00);
924 snd_opti93x_mce_down(chip);
925 chip->mode = 0;
926
927 snd_opti93x_mute(chip, 0);
928 spin_unlock_irqrestore(&chip->lock, flags);
929}
930
931static int snd_opti93x_trigger(snd_pcm_substream_t *substream,
932 unsigned char what, int cmd)
933{
934 opti93x_t *chip = snd_pcm_substream_chip(substream);
935
936 switch (cmd) {
937 case SNDRV_PCM_TRIGGER_START:
938 case SNDRV_PCM_TRIGGER_STOP:
939 {
940 unsigned int what = 0;
941 struct list_head *pos;
942 snd_pcm_substream_t *s;
943 snd_pcm_group_for_each(pos, substream) {
944 s = snd_pcm_group_substream_entry(pos);
945 if (s == chip->playback_substream) {
946 what |= OPTi93X_PLAYBACK_ENABLE;
947 snd_pcm_trigger_done(s, substream);
948 } else if (s == chip->capture_substream) {
949 what |= OPTi93X_CAPTURE_ENABLE;
950 snd_pcm_trigger_done(s, substream);
951 }
952 }
953 spin_lock(&chip->lock);
954 if (cmd == SNDRV_PCM_TRIGGER_START) {
955 snd_opti93x_out_mask(chip, OPTi93X_IFACE_CONF, what, what);
956 if (what & OPTi93X_CAPTURE_ENABLE)
957 udelay(50);
958 } else
959 snd_opti93x_out_mask(chip, OPTi93X_IFACE_CONF, what, 0x00);
960 spin_unlock(&chip->lock);
961 break;
962 }
963 default:
964 return -EINVAL;
965 }
966 return 0;
967}
968
969static int snd_opti93x_playback_trigger(snd_pcm_substream_t *substream, int cmd)
970{
971 return snd_opti93x_trigger(substream,
972 OPTi93X_PLAYBACK_ENABLE, cmd);
973}
974
975static int snd_opti93x_capture_trigger(snd_pcm_substream_t * substream, int cmd)
976{
977 return snd_opti93x_trigger(substream,
978 OPTi93X_CAPTURE_ENABLE, cmd);
979}
980
981static int snd_opti93x_hw_params(snd_pcm_substream_t * substream,
982 snd_pcm_hw_params_t * hw_params)
983{
984 return snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(hw_params));
985}
986
987
988static int snd_opti93x_hw_free(snd_pcm_substream_t * substream)
989{
990 snd_pcm_lib_free_pages(substream);
991 return 0;
992}
993
994
995static int snd_opti93x_playback_prepare(snd_pcm_substream_t * substream)
996{
997 opti93x_t *chip = snd_pcm_substream_chip(substream);
998 snd_pcm_runtime_t *runtime = substream->runtime;
999 unsigned long flags;
1000 unsigned char format;
1001 unsigned int count = snd_pcm_lib_period_bytes(substream);
1002 unsigned int size = snd_pcm_lib_buffer_bytes(substream);
1003
1004 spin_lock_irqsave(&chip->lock, flags);
1005
1006 chip->p_dma_size = size;
1007 snd_opti93x_out_mask(chip, OPTi93X_IFACE_CONF,
1008 OPTi93X_PLAYBACK_ENABLE | OPTi93X_PLAYBACK_PIO,
1009 ~(OPTi93X_PLAYBACK_ENABLE | OPTi93X_PLAYBACK_PIO));
1010
1011 snd_dma_program(chip->dma1, runtime->dma_addr, size,
1012 DMA_MODE_WRITE | DMA_AUTOINIT);
1013
1014 format = snd_opti93x_get_freq(runtime->rate);
1015 format |= snd_opti93x_get_format(chip, runtime->format,
1016 runtime->channels);
1017 snd_opti93x_playback_format(chip, format);
1018 format = chip->image[OPTi93X_PLAY_FORMAT];
1019
1020 count = snd_opti93x_get_count(format, count) - 1;
1021 snd_opti93x_out_image(chip, OPTi93X_PLAY_LWR_CNT, count);
1022 snd_opti93x_out_image(chip, OPTi93X_PLAY_UPR_CNT, count >> 8);
1023
1024 spin_unlock_irqrestore(&chip->lock, flags);
1025 return 0;
1026}
1027
1028static int snd_opti93x_capture_prepare(snd_pcm_substream_t *substream)
1029{
1030 opti93x_t *chip = snd_pcm_substream_chip(substream);
1031 snd_pcm_runtime_t *runtime = substream->runtime;
1032 unsigned long flags;
1033 unsigned char format;
1034 unsigned int count = snd_pcm_lib_period_bytes(substream);
1035 unsigned int size = snd_pcm_lib_buffer_bytes(substream);
1036
1037 spin_lock_irqsave(&chip->lock, flags);
1038
1039 chip->c_dma_size = size;
1040 snd_opti93x_out_mask(chip, OPTi93X_IFACE_CONF,
1041 OPTi93X_CAPTURE_ENABLE | OPTi93X_CAPTURE_PIO,
1042 (unsigned char)~(OPTi93X_CAPTURE_ENABLE | OPTi93X_CAPTURE_PIO));
1043
1044 snd_dma_program(chip->dma2, runtime->dma_addr, size,
1045 DMA_MODE_READ | DMA_AUTOINIT);
1046
1047 format = snd_opti93x_get_freq(runtime->rate);
1048 format |= snd_opti93x_get_format(chip, runtime->format,
1049 runtime->channels);
1050 snd_opti93x_capture_format(chip, format);
1051 format = chip->image[OPTi93X_CAPT_FORMAT];
1052
1053 count = snd_opti93x_get_count(format, count) - 1;
1054 snd_opti93x_out_image(chip, OPTi93X_CAPT_LWR_CNT, count);
1055 snd_opti93x_out_image(chip, OPTi93X_CAPT_UPR_CNT, count >> 8);
1056
1057 spin_unlock_irqrestore(&chip->lock, flags);
1058 return 0;
1059}
1060
1061static snd_pcm_uframes_t snd_opti93x_playback_pointer(snd_pcm_substream_t *substream)
1062{
1063 opti93x_t *chip = snd_pcm_substream_chip(substream);
1064 size_t ptr;
1065
1066 if (!(chip->image[OPTi93X_IFACE_CONF] & OPTi93X_PLAYBACK_ENABLE))
1067 return 0;
1068
1069 ptr = snd_dma_pointer(chip->dma1, chip->p_dma_size);
1070 return bytes_to_frames(substream->runtime, ptr);
1071}
1072
1073static snd_pcm_uframes_t snd_opti93x_capture_pointer(snd_pcm_substream_t *substream)
1074{
1075 opti93x_t *chip = snd_pcm_substream_chip(substream);
1076 size_t ptr;
1077
1078 if (!(chip->image[OPTi93X_IFACE_CONF] & OPTi93X_CAPTURE_ENABLE))
1079 return 0;
1080
1081 ptr = snd_dma_pointer(chip->dma2, chip->c_dma_size);
1082 return bytes_to_frames(substream->runtime, ptr);
1083}
1084
1085
1086static void snd_opti93x_overrange(opti93x_t *chip)
1087{
1088 unsigned long flags;
1089
1090 spin_lock_irqsave(&chip->lock, flags);
1091
1092 if (snd_opti93x_in(chip, OPTi93X_ERR_INIT) & (0x08 | 0x02))
1093 chip->capture_substream->runtime->overrange++;
1094
1095 spin_unlock_irqrestore(&chip->lock, flags);
1096}
1097
1098static irqreturn_t snd_opti93x_interrupt(int irq, void *dev_id, struct pt_regs *regs)
1099{
1100 opti93x_t *codec = dev_id;
1101 unsigned char status;
1102
1103 status = snd_opti9xx_read(codec->chip, OPTi9XX_MC_REG(11));
1104 if ((status & OPTi93X_IRQ_PLAYBACK) && codec->playback_substream)
1105 snd_pcm_period_elapsed(codec->playback_substream);
1106 if ((status & OPTi93X_IRQ_CAPTURE) && codec->capture_substream) {
1107 snd_opti93x_overrange(codec);
1108 snd_pcm_period_elapsed(codec->capture_substream);
1109 }
1110 outb(0x00, OPTi93X_PORT(codec, STATUS));
1111 return IRQ_HANDLED;
1112}
1113
1114
1115static snd_pcm_hardware_t snd_opti93x_playback = {
1116 .info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED |
1117 SNDRV_PCM_INFO_MMAP_VALID | SNDRV_PCM_INFO_SYNC_START),
1118 .formats = (SNDRV_PCM_FMTBIT_MU_LAW | SNDRV_PCM_FMTBIT_A_LAW | SNDRV_PCM_FMTBIT_IMA_ADPCM |
1119 SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S16_BE),
1120 .rates = SNDRV_PCM_RATE_KNOT | SNDRV_PCM_RATE_8000_48000,
1121 .rate_min = 5512,
1122 .rate_max = 48000,
1123 .channels_min = 1,
1124 .channels_max = 2,
1125 .buffer_bytes_max = (128*1024),
1126 .period_bytes_min = 64,
1127 .period_bytes_max = (128*1024),
1128 .periods_min = 1,
1129 .periods_max = 1024,
1130 .fifo_size = 0,
1131};
1132
1133static snd_pcm_hardware_t snd_opti93x_capture = {
1134 .info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED |
1135 SNDRV_PCM_INFO_MMAP_VALID | SNDRV_PCM_INFO_SYNC_START),
1136 .formats = (SNDRV_PCM_FMTBIT_MU_LAW | SNDRV_PCM_FMTBIT_A_LAW | SNDRV_PCM_FMTBIT_IMA_ADPCM |
1137 SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S16_BE),
1138 .rates = SNDRV_PCM_RATE_8000_48000,
1139 .rate_min = 5512,
1140 .rate_max = 48000,
1141 .channels_min = 1,
1142 .channels_max = 2,
1143 .buffer_bytes_max = (128*1024),
1144 .period_bytes_min = 64,
1145 .period_bytes_max = (128*1024),
1146 .periods_min = 1,
1147 .periods_max = 1024,
1148 .fifo_size = 0,
1149};
1150
1151static int snd_opti93x_playback_open(snd_pcm_substream_t *substream)
1152{
1153 int error;
1154 opti93x_t *chip = snd_pcm_substream_chip(substream);
1155 snd_pcm_runtime_t *runtime = substream->runtime;
1156
1157 if ((error = snd_opti93x_open(chip, OPTi93X_MODE_PLAY)) < 0)
1158 return error;
1159 snd_pcm_set_sync(substream);
1160 chip->playback_substream = substream;
1161 runtime->hw = snd_opti93x_playback;
1162 snd_pcm_limit_isa_dma_size(chip->dma1, &runtime->hw.buffer_bytes_max);
1163 snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE, &hw_constraints_rates);
1164 return error;
1165}
1166
1167static int snd_opti93x_capture_open(snd_pcm_substream_t *substream)
1168{
1169 int error;
1170 opti93x_t *chip = snd_pcm_substream_chip(substream);
1171 snd_pcm_runtime_t *runtime = substream->runtime;
1172
1173 if ((error = snd_opti93x_open(chip, OPTi93X_MODE_CAPTURE)) < 0)
1174 return error;
1175 runtime->hw = snd_opti93x_capture;
1176 snd_pcm_set_sync(substream);
1177 chip->capture_substream = substream;
1178 snd_pcm_limit_isa_dma_size(chip->dma2, &runtime->hw.buffer_bytes_max);
1179 snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE, &hw_constraints_rates);
1180 return error;
1181}
1182
1183static int snd_opti93x_playback_close(snd_pcm_substream_t *substream)
1184{
1185 opti93x_t *chip = snd_pcm_substream_chip(substream);
1186
1187 chip->playback_substream = NULL;
1188 snd_opti93x_close(chip, OPTi93X_MODE_PLAY);
1189 return 0;
1190}
1191
1192static int snd_opti93x_capture_close(snd_pcm_substream_t *substream)
1193{
1194 opti93x_t *chip = snd_pcm_substream_chip(substream);
1195
1196 chip->capture_substream = NULL;
1197 snd_opti93x_close(chip, OPTi93X_MODE_CAPTURE);
1198 return 0;
1199}
1200
1201
1202static void snd_opti93x_init(opti93x_t *chip)
1203{
1204 unsigned long flags;
1205 int i;
1206
1207 spin_lock_irqsave(&chip->lock, flags);
1208 snd_opti93x_mce_up(chip);
1209
1210 for (i = 0; i < 32; i++)
1211 snd_opti93x_out_image(chip, i, snd_opti93x_default_image[i]);
1212
1213 snd_opti93x_mce_down(chip);
1214 spin_unlock_irqrestore(&chip->lock, flags);
1215}
1216
1217static int snd_opti93x_probe(opti93x_t *chip)
1218{
1219 unsigned long flags;
1220 unsigned char val;
1221
1222 spin_lock_irqsave(&chip->lock, flags);
1223 val = snd_opti93x_in(chip, OPTi93X_ID) & 0x0f;
1224 spin_unlock_irqrestore(&chip->lock, flags);
1225
1226 return (val == 0x0a) ? 0 : -ENODEV;
1227}
1228
1229static int snd_opti93x_free(opti93x_t *chip)
1230{
1231 if (chip->res_port) {
1232 release_resource(chip->res_port);
1233 kfree_nocheck(chip->res_port);
1234 }
1235 if (chip->dma1 >= 0) {
1236 disable_dma(chip->dma1);
1237 free_dma(chip->dma1);
1238 }
1239 if (chip->dma2 >= 0) {
1240 disable_dma(chip->dma2);
1241 free_dma(chip->dma2);
1242 }
1243 if (chip->irq >= 0) {
1244 free_irq(chip->irq, chip);
1245 }
1246 kfree(chip);
1247 return 0;
1248}
1249
1250static int snd_opti93x_dev_free(snd_device_t *device)
1251{
1252 opti93x_t *chip = device->device_data;
1253 return snd_opti93x_free(chip);
1254}
1255
1256static const char *snd_opti93x_chip_id(opti93x_t *codec)
1257{
1258 switch (codec->hardware) {
1259 case OPTi9XX_HW_82C930: return "82C930";
1260 case OPTi9XX_HW_82C931: return "82C931";
1261 case OPTi9XX_HW_82C933: return "82C933";
1262 default: return "???";
1263 }
1264}
1265
1266static int snd_opti93x_create(snd_card_t *card, opti9xx_t *chip,
1267 int dma1, int dma2,
1268 opti93x_t **rcodec)
1269{
1270 static snd_device_ops_t ops = {
1271 .dev_free = snd_opti93x_dev_free,
1272 };
1273 int error;
1274 opti93x_t *codec;
1275
1276 *rcodec = NULL;
1277 codec = kcalloc(1, sizeof(*codec), GFP_KERNEL);
1278 if (codec == NULL)
1279 return -ENOMEM;
1280 codec->irq = -1;
1281 codec->dma1 = -1;
1282 codec->dma2 = -1;
1283
1284 if ((codec->res_port = request_region(chip->wss_base + 4, 4, "OPTI93x CODEC")) == NULL) {
1285 snd_printk(KERN_ERR "opti9xx: can't grab port 0x%lx\n", chip->wss_base + 4);
1286 snd_opti93x_free(codec);
1287 return -EBUSY;
1288 }
1289 if (request_dma(dma1, "OPTI93x - 1")) {
1290 snd_printk(KERN_ERR "opti9xx: can't grab DMA1 %d\n", dma1);
1291 snd_opti93x_free(codec);
1292 return -EBUSY;
1293 }
1294 codec->dma1 = chip->dma1;
1295 if (request_dma(dma2, "OPTI93x - 2")) {
1296 snd_printk(KERN_ERR "opti9xx: can't grab DMA2 %d\n", dma2);
1297 snd_opti93x_free(codec);
1298 return -EBUSY;
1299 }
1300 codec->dma2 = chip->dma2;
1301
1302 if (request_irq(chip->irq, snd_opti93x_interrupt, SA_INTERRUPT, DRIVER_NAME" - WSS", codec)) {
1303 snd_printk(KERN_ERR "opti9xx: can't grab IRQ %d\n", chip->irq);
1304 snd_opti93x_free(codec);
1305 return -EBUSY;
1306 }
1307
1308 codec->card = card;
1309 codec->port = chip->wss_base + 4;
1310 codec->irq = chip->irq;
1311
1312 spin_lock_init(&codec->lock);
1313 codec->hardware = chip->hardware;
1314 codec->chip = chip;
1315
1316 if ((error = snd_opti93x_probe(codec))) {
1317 snd_opti93x_free(codec);
1318 return error;
1319 }
1320
1321 snd_opti93x_init(codec);
1322
1323 /* Register device */
1324 if ((error = snd_device_new(card, SNDRV_DEV_LOWLEVEL, codec, &ops)) < 0) {
1325 snd_opti93x_free(codec);
1326 return error;
1327 }
1328
1329 *rcodec = codec;
1330 return 0;
1331}
1332
1333static snd_pcm_ops_t snd_opti93x_playback_ops = {
1334 .open = snd_opti93x_playback_open,
1335 .close = snd_opti93x_playback_close,
1336 .ioctl = snd_pcm_lib_ioctl,
1337 .hw_params = snd_opti93x_hw_params,
1338 .hw_free = snd_opti93x_hw_free,
1339 .prepare = snd_opti93x_playback_prepare,
1340 .trigger = snd_opti93x_playback_trigger,
1341 .pointer = snd_opti93x_playback_pointer,
1342};
1343
1344static snd_pcm_ops_t snd_opti93x_capture_ops = {
1345 .open = snd_opti93x_capture_open,
1346 .close = snd_opti93x_capture_close,
1347 .ioctl = snd_pcm_lib_ioctl,
1348 .hw_params = snd_opti93x_hw_params,
1349 .hw_free = snd_opti93x_hw_free,
1350 .prepare = snd_opti93x_capture_prepare,
1351 .trigger = snd_opti93x_capture_trigger,
1352 .pointer = snd_opti93x_capture_pointer,
1353};
1354
1355static void snd_opti93x_pcm_free(snd_pcm_t *pcm)
1356{
1357 opti93x_t *codec = pcm->private_data;
1358 codec->pcm = NULL;
1359 snd_pcm_lib_preallocate_free_for_all(pcm);
1360}
1361
1362static int snd_opti93x_pcm(opti93x_t *codec, int device, snd_pcm_t **rpcm)
1363{
1364 int error;
1365 snd_pcm_t *pcm;
1366
1367 if ((error = snd_pcm_new(codec->card, "OPTi 82C93X", device, 1, 1, &pcm)))
1368 return error;
1369
1370 snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_opti93x_playback_ops);
1371 snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_opti93x_capture_ops);
1372
1373 pcm->private_data = codec;
1374 pcm->private_free = snd_opti93x_pcm_free;
1375 pcm->info_flags = SNDRV_PCM_INFO_JOINT_DUPLEX;
1376
1377 strcpy(pcm->name, snd_opti93x_chip_id(codec));
1378
1379 snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV,
1380 snd_dma_isa_data(),
1381 64*1024, codec->dma1 > 3 || codec->dma2 > 3 ? 128*1024 : 64*1024);
1382
1383 codec->pcm = pcm;
1384 if (rpcm)
1385 *rpcm = pcm;
1386 return 0;
1387}
1388
1389/*
1390 * MIXER part
1391 */
1392
1393static int snd_opti93x_info_mux(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
1394{
1395 static char *texts[4] = {
1396 "Line1", "Aux", "Mic", "Mix"
1397 };
1398
1399 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
1400 uinfo->count = 2;
1401 uinfo->value.enumerated.items = 4;
1402 if (uinfo->value.enumerated.item > 3)
1403 uinfo->value.enumerated.item = 3;
1404 strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]);
1405 return 0;
1406}
1407
1408static int snd_opti93x_get_mux(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
1409{
1410 opti93x_t *chip = snd_kcontrol_chip(kcontrol);
1411 unsigned long flags;
1412
1413 spin_lock_irqsave(&chip->lock, flags);
1414 ucontrol->value.enumerated.item[0] = (chip->image[OPTi93X_MIXOUT_LEFT] & OPTi93X_MIXOUT_MIXER) >> 6;
1415 ucontrol->value.enumerated.item[1] = (chip->image[OPTi93X_MIXOUT_RIGHT] & OPTi93X_MIXOUT_MIXER) >> 6;
1416 spin_unlock_irqrestore(&chip->lock, flags);
1417 return 0;
1418}
1419
1420static int snd_opti93x_put_mux(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
1421{
1422 opti93x_t *chip = snd_kcontrol_chip(kcontrol);
1423 unsigned long flags;
1424 unsigned short left, right;
1425 int change;
1426
1427 if (ucontrol->value.enumerated.item[0] > 3 ||
1428 ucontrol->value.enumerated.item[1] > 3)
1429 return -EINVAL;
1430 left = ucontrol->value.enumerated.item[0] << 6;
1431 right = ucontrol->value.enumerated.item[1] << 6;
1432 spin_lock_irqsave(&chip->lock, flags);
1433 left = (chip->image[OPTi93X_MIXOUT_LEFT] & ~OPTi93X_MIXOUT_MIXER) | left;
1434 right = (chip->image[OPTi93X_MIXOUT_RIGHT] & ~OPTi93X_MIXOUT_MIXER) | right;
1435 change = left != chip->image[OPTi93X_MIXOUT_LEFT] ||
1436 right != chip->image[OPTi93X_MIXOUT_RIGHT];
1437 snd_opti93x_out_image(chip, OPTi93X_MIXOUT_LEFT, left);
1438 snd_opti93x_out_image(chip, OPTi93X_MIXOUT_RIGHT, right);
1439 spin_unlock_irqrestore(&chip->lock, flags);
1440 return change;
1441}
1442
1443#if 0
1444
1445#define OPTi93X_SINGLE(xname, xindex, reg, shift, mask, invert) \
1446{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xindex, \
1447 .info = snd_opti93x_info_single, \
1448 .get = snd_opti93x_get_single, .put = snd_opti93x_put_single, \
1449 .private_value = reg | (shift << 8) | (mask << 16) | (invert << 24) }
1450
1451static int snd_opti93x_info_single(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
1452{
1453 int mask = (kcontrol->private_value >> 16) & 0xff;
1454
1455 uinfo->type = mask == 1 ? SNDRV_CTL_ELEM_TYPE_BOOLEAN : SNDRV_CTL_ELEM_TYPE_INTEGER;
1456 uinfo->count = 1;
1457 uinfo->value.integer.min = 0;
1458 uinfo->value.integer.max = mask;
1459 return 0;
1460}
1461
1462static int snd_opti93x_get_single(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
1463{
1464 opti93x_t *chip = snd_kcontrol_chip(kcontrol);
1465 unsigned long flags;
1466 int reg = kcontrol->private_value & 0xff;
1467 int shift = (kcontrol->private_value >> 8) & 0xff;
1468 int mask = (kcontrol->private_value >> 16) & 0xff;
1469 int invert = (kcontrol->private_value >> 24) & 0xff;
1470
1471 spin_lock_irqsave(&chip->lock, flags);
1472 ucontrol->value.integer.value[0] = (chip->image[reg] >> shift) & mask;
1473 spin_unlock_irqrestore(&chip->lock, flags);
1474 if (invert)
1475 ucontrol->value.integer.value[0] = mask - ucontrol->value.integer.value[0];
1476 return 0;
1477}
1478
1479static int snd_opti93x_put_single(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
1480{
1481 opti93x_t *chip = snd_kcontrol_chip(kcontrol);
1482 unsigned long flags;
1483 int reg = kcontrol->private_value & 0xff;
1484 int shift = (kcontrol->private_value >> 8) & 0xff;
1485 int mask = (kcontrol->private_value >> 16) & 0xff;
1486 int invert = (kcontrol->private_value >> 24) & 0xff;
1487 int change;
1488 unsigned short val;
1489
1490 val = (ucontrol->value.integer.value[0] & mask);
1491 if (invert)
1492 val = mask - val;
1493 val <<= shift;
1494 spin_lock_irqsave(&chip->lock, flags);
1495 val = (chip->image[reg] & ~(mask << shift)) | val;
1496 change = val != chip->image[reg];
1497 snd_opti93x_out(chip, reg, val);
1498 spin_unlock_irqrestore(&chip->lock, flags);
1499 return change;
1500}
1501
1502#endif /* single */
1503
1504#define OPTi93X_DOUBLE(xname, xindex, left_reg, right_reg, shift_left, shift_right, mask, invert) \
1505{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xindex, \
1506 .info = snd_opti93x_info_double, \
1507 .get = snd_opti93x_get_double, .put = snd_opti93x_put_double, \
1508 .private_value = left_reg | (right_reg << 8) | (shift_left << 16) | (shift_right << 19) | (mask << 24) | (invert << 22) }
1509
1510#define OPTi93X_DOUBLE_INVERT_INVERT(xctl) \
1511 do { xctl.private_value ^= 22; } while (0)
1512#define OPTi93X_DOUBLE_CHANGE_REGS(xctl, left_reg, right_reg) \
1513 do { xctl.private_value &= ~0x0000ffff; \
1514 xctl.private_value |= left_reg | (right_reg << 8); } while (0)
1515
1516static int snd_opti93x_info_double(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
1517{
1518 int mask = (kcontrol->private_value >> 24) & 0xff;
1519
1520 uinfo->type = mask == 1 ? SNDRV_CTL_ELEM_TYPE_BOOLEAN : SNDRV_CTL_ELEM_TYPE_INTEGER;
1521 uinfo->count = 2;
1522 uinfo->value.integer.min = 0;
1523 uinfo->value.integer.max = mask;
1524 return 0;
1525}
1526
1527static int snd_opti93x_get_double(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
1528{
1529 opti93x_t *chip = snd_kcontrol_chip(kcontrol);
1530 unsigned long flags;
1531 int left_reg = kcontrol->private_value & 0xff;
1532 int right_reg = (kcontrol->private_value >> 8) & 0xff;
1533 int shift_left = (kcontrol->private_value >> 16) & 0x07;
1534 int shift_right = (kcontrol->private_value >> 19) & 0x07;
1535 int mask = (kcontrol->private_value >> 24) & 0xff;
1536 int invert = (kcontrol->private_value >> 22) & 1;
1537
1538 spin_lock_irqsave(&chip->lock, flags);
1539 ucontrol->value.integer.value[0] = (chip->image[left_reg] >> shift_left) & mask;
1540 ucontrol->value.integer.value[1] = (chip->image[right_reg] >> shift_right) & mask;
1541 spin_unlock_irqrestore(&chip->lock, flags);
1542 if (invert) {
1543 ucontrol->value.integer.value[0] = mask - ucontrol->value.integer.value[0];
1544 ucontrol->value.integer.value[1] = mask - ucontrol->value.integer.value[1];
1545 }
1546 return 0;
1547}
1548
1549static int snd_opti93x_put_double(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
1550{
1551 opti93x_t *chip = snd_kcontrol_chip(kcontrol);
1552 unsigned long flags;
1553 int left_reg = kcontrol->private_value & 0xff;
1554 int right_reg = (kcontrol->private_value >> 8) & 0xff;
1555 int shift_left = (kcontrol->private_value >> 16) & 0x07;
1556 int shift_right = (kcontrol->private_value >> 19) & 0x07;
1557 int mask = (kcontrol->private_value >> 24) & 0xff;
1558 int invert = (kcontrol->private_value >> 22) & 1;
1559 int change;
1560 unsigned short val1, val2;
1561
1562 val1 = ucontrol->value.integer.value[0] & mask;
1563 val2 = ucontrol->value.integer.value[1] & mask;
1564 if (invert) {
1565 val1 = mask - val1;
1566 val2 = mask - val2;
1567 }
1568 val1 <<= shift_left;
1569 val2 <<= shift_right;
1570 spin_lock_irqsave(&chip->lock, flags);
1571 val1 = (chip->image[left_reg] & ~(mask << shift_left)) | val1;
1572 val2 = (chip->image[right_reg] & ~(mask << shift_right)) | val2;
1573 change = val1 != chip->image[left_reg] || val2 != chip->image[right_reg];
1574 snd_opti93x_out_image(chip, left_reg, val1);
1575 snd_opti93x_out_image(chip, right_reg, val2);
1576 spin_unlock_irqrestore(&chip->lock, flags);
1577 return change;
1578}
1579
1580static snd_kcontrol_new_t snd_opti93x_controls[] = {
1581OPTi93X_DOUBLE("Master Playback Switch", 0, OPTi93X_OUT_LEFT, OPTi93X_OUT_RIGHT, 7, 7, 1, 1),
1582OPTi93X_DOUBLE("Master Playback Volume", 0, OPTi93X_OUT_LEFT, OPTi93X_OUT_RIGHT, 1, 1, 31, 1),
1583OPTi93X_DOUBLE("PCM Playback Switch", 0, OPTi93X_DAC_LEFT, OPTi93X_DAC_RIGHT, 7, 7, 1, 1),
1584OPTi93X_DOUBLE("PCM Playback Volume", 0, OPTi93X_DAC_LEFT, OPTi93X_DAC_RIGHT, 0, 0, 31, 1),
1585OPTi93X_DOUBLE("FM Playback Switch", 0, OPTi931_FM_LEFT_INPUT, OPTi931_FM_RIGHT_INPUT, 7, 7, 1, 1),
1586OPTi93X_DOUBLE("FM Playback Volume", 0, OPTi931_FM_LEFT_INPUT, OPTi931_FM_RIGHT_INPUT, 1, 1, 15, 1),
1587OPTi93X_DOUBLE("Line Playback Switch", 0, OPTi93X_LINE_LEFT_INPUT, OPTi93X_LINE_RIGHT_INPUT, 7, 7, 1, 1),
1588OPTi93X_DOUBLE("Line Playback Volume", 0, OPTi93X_LINE_LEFT_INPUT, OPTi93X_LINE_RIGHT_INPUT, 1, 1, 15, 1),
1589OPTi93X_DOUBLE("Mic Playback Switch", 0, OPTi93X_MIC_LEFT_INPUT, OPTi93X_MIC_RIGHT_INPUT, 7, 7, 1, 1),
1590OPTi93X_DOUBLE("Mic Playback Volume", 0, OPTi93X_MIC_LEFT_INPUT, OPTi93X_MIC_RIGHT_INPUT, 1, 1, 15, 1),
1591OPTi93X_DOUBLE("Mic Boost", 0, OPTi93X_MIXOUT_LEFT, OPTi93X_MIXOUT_RIGHT, 5, 5, 1, 1),
1592OPTi93X_DOUBLE("CD Playback Switch", 0, OPTi93X_CD_LEFT_INPUT, OPTi93X_CD_RIGHT_INPUT, 7, 7, 1, 1),
1593OPTi93X_DOUBLE("CD Playback Volume", 0, OPTi93X_CD_LEFT_INPUT, OPTi93X_CD_RIGHT_INPUT, 1, 1, 15, 1),
1594OPTi93X_DOUBLE("Aux Playback Switch", 0, OPTi931_AUX_LEFT_INPUT, OPTi931_AUX_RIGHT_INPUT, 7, 7, 1, 1),
1595OPTi93X_DOUBLE("Aux Playback Volume", 0, OPTi931_AUX_LEFT_INPUT, OPTi931_AUX_RIGHT_INPUT, 1, 1, 15, 1),
1596OPTi93X_DOUBLE("Capture Volume", 0, OPTi93X_MIXOUT_LEFT, OPTi93X_MIXOUT_RIGHT, 0, 0, 15, 0),
1597{
1598 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1599 .name = "Capture Source",
1600 .info = snd_opti93x_info_mux,
1601 .get = snd_opti93x_get_mux,
1602 .put = snd_opti93x_put_mux,
1603}
1604};
1605
1606static int snd_opti93x_mixer(opti93x_t *chip)
1607{
1608 snd_card_t *card;
1609 snd_kcontrol_new_t knew;
1610 int err;
1611 unsigned int idx;
1612
1613 snd_assert(chip != NULL && chip->card != NULL, return -EINVAL);
1614
1615 card = chip->card;
1616
1617 strcpy(card->mixername, snd_opti93x_chip_id(chip));
1618
1619 for (idx = 0; idx < ARRAY_SIZE(snd_opti93x_controls); idx++) {
1620 knew = snd_opti93x_controls[idx];
1621 if (chip->hardware == OPTi9XX_HW_82C930) {
1622 if (strstr(knew.name, "FM")) /* skip FM controls */
1623 continue;
1624 else if (strcmp(knew.name, "Mic Playback Volume"))
1625 OPTi93X_DOUBLE_INVERT_INVERT(knew);
1626 else if (strstr(knew.name, "Aux"))
1627 OPTi93X_DOUBLE_CHANGE_REGS(knew, OPTi930_AUX_LEFT_INPUT, OPTi930_AUX_RIGHT_INPUT);
1628 else if (strcmp(knew.name, "PCM Playback Volume"))
1629 OPTi93X_DOUBLE_INVERT_INVERT(knew);
1630 else if (strcmp(knew.name, "Master Playback Volume"))
1631 OPTi93X_DOUBLE_INVERT_INVERT(knew);
1632 }
1633 if ((err = snd_ctl_add(card, snd_ctl_new1(&snd_opti93x_controls[idx], chip))) < 0)
1634 return err;
1635 }
1636 return 0;
1637}
1638
1639#endif /* OPTi93X */
1640
1641static int __devinit snd_card_opti9xx_detect(snd_card_t *card, opti9xx_t *chip)
1642{
1643 int i, err;
1644
1645#ifndef OPTi93X
1646 for (i = OPTi9XX_HW_82C928; i < OPTi9XX_HW_82C930; i++) {
1647 unsigned char value;
1648
1649 if ((err = snd_opti9xx_init(chip, i)) < 0)
1650 return err;
1651
1652 if ((chip->res_mc_base = request_region(chip->mc_base, chip->mc_base_size, "OPTi9xx MC")) == NULL)
1653 continue;
1654
1655 value = snd_opti9xx_read(chip, OPTi9XX_MC_REG(1));
1656 if ((value != 0xff) && (value != inb(chip->mc_base + 1)))
1657 if (value == snd_opti9xx_read(chip, OPTi9XX_MC_REG(1)))
1658 return 1;
1659
1660 release_resource(chip->res_mc_base);
1661 kfree_nocheck(chip->res_mc_base);
1662 chip->res_mc_base = NULL;
1663
1664 }
1665#else /* OPTi93X */
1666 for (i = OPTi9XX_HW_82C931; i >= OPTi9XX_HW_82C930; i--) {
1667 unsigned long flags;
1668 unsigned char value;
1669
1670 if ((err = snd_opti9xx_init(chip, i)) < 0)
1671 return err;
1672
1673 if ((chip->res_mc_base = request_region(chip->mc_base, chip->mc_base_size, "OPTi9xx MC")) == NULL)
1674 continue;
1675
1676 spin_lock_irqsave(&chip->lock, flags);
1677 outb(chip->password, chip->mc_base + chip->pwd_reg);
1678 outb(((chip->mc_indir_index & (1 << 8)) >> 4) |
1679 ((chip->mc_indir_index & 0xf0) >> 4), chip->mc_base);
1680 spin_unlock_irqrestore(&chip->lock, flags);
1681
1682 value = snd_opti9xx_read(chip, OPTi9XX_MC_REG(7));
1683 snd_opti9xx_write(chip, OPTi9XX_MC_REG(7), 0xff - value);
1684 if (snd_opti9xx_read(chip, OPTi9XX_MC_REG(7)) == 0xff - value)
1685 return 1;
1686
1687 release_resource(chip->res_mc_base);
1688 kfree_nocheck(chip->res_mc_base);
1689 chip->res_mc_base = NULL;
1690 }
1691#endif /* OPTi93X */
1692
1693 return -ENODEV;
1694}
1695
1696#ifdef CONFIG_PNP
1697static int __devinit snd_card_opti9xx_pnp(opti9xx_t *chip, struct pnp_card_link *card,
1698 const struct pnp_card_device_id *pid)
1699{
1700 struct pnp_dev *pdev;
1701 struct pnp_resource_table *cfg = kmalloc(sizeof(*cfg), GFP_KERNEL);
1702 int err;
1703
1704 chip->dev = pnp_request_card_device(card, pid->devs[0].id, NULL);
1705 if (chip->dev == NULL) {
1706 kfree(cfg);
1707 return -EBUSY;
1708 }
1709 chip->devmpu = pnp_request_card_device(card, pid->devs[1].id, NULL);
1710
1711 pdev = chip->dev;
1712 pnp_init_resource_table(cfg);
1713
1714#ifdef OPTi93X
1715 if (port != SNDRV_AUTO_PORT)
1716 pnp_resource_change(&cfg->port_resource[0], port + 4, 4);
1717#else
1718 if (pid->driver_data != 0x0924 && port != SNDRV_AUTO_PORT)
1719 pnp_resource_change(&cfg->port_resource[1], port, 4);
1720#endif /* OPTi93X */
1721 if (irq != SNDRV_AUTO_IRQ)
1722 pnp_resource_change(&cfg->irq_resource[0], irq, 1);
1723 if (dma1 != SNDRV_AUTO_DMA)
1724 pnp_resource_change(&cfg->dma_resource[0], dma1, 1);
1725#if defined(CS4231) || defined(OPTi93X)
1726 if (dma2 != SNDRV_AUTO_DMA)
1727 pnp_resource_change(&cfg->dma_resource[1], dma2, 1);
1728#else
1729#ifdef snd_opti9xx_fixup_dma2
1730 snd_opti9xx_fixup_dma2(pdev);
1731#endif
1732#endif /* CS4231 || OPTi93X */
1733#ifdef OPTi93X
1734 if (fm_port > 0 && fm_port != SNDRV_AUTO_PORT)
1735 pnp_resource_change(&cfg->port_resource[1], fm_port, 4);
1736#else
1737 if (fm_port > 0 && fm_port != SNDRV_AUTO_PORT)
1738 pnp_resource_change(&cfg->port_resource[2], fm_port, 4);
1739#endif
1740 if (pnp_manual_config_dev(pdev, cfg, 0) < 0)
1741 snd_printk(KERN_ERR "AUDIO the requested resources are invalid, using auto config\n");
1742 err = pnp_activate_dev(pdev);
1743 if (err < 0) {
1744 snd_printk(KERN_ERR "AUDIO pnp configure failure: %d\n", err);
1745 kfree(cfg);
1746 return err;
1747 }
1748
1749#ifdef OPTi93X
1750 port = pnp_port_start(pdev, 0) - 4;
1751 fm_port = pnp_port_start(pdev, 1);
1752#else
1753 if (pid->driver_data != 0x0924)
1754 port = pnp_port_start(pdev, 1);
1755 fm_port = pnp_port_start(pdev, 2);
1756#endif /* OPTi93X */
1757 irq = pnp_irq(pdev, 0);
1758 dma1 = pnp_dma(pdev, 0);
1759#if defined(CS4231) || defined(OPTi93X)
1760 dma2 = pnp_dma(pdev, 1);
1761#endif /* CS4231 || OPTi93X */
1762
1763 pdev = chip->devmpu;
1764 if (pdev && mpu_port > 0) {
1765 pnp_init_resource_table(cfg);
1766
1767 if (mpu_port != SNDRV_AUTO_PORT)
1768 pnp_resource_change(&cfg->port_resource[0], mpu_port, 2);
1769 if (mpu_irq != SNDRV_AUTO_IRQ)
1770 pnp_resource_change(&cfg->irq_resource[0], mpu_irq, 1);
1771
1772 if (pnp_manual_config_dev(pdev, cfg, 0) < 0)
1773 snd_printk(KERN_ERR "AUDIO the requested resources are invalid, using auto config\n");
1774 err = pnp_activate_dev(pdev);
1775 if (err < 0) {
1776 snd_printk(KERN_ERR "AUDIO pnp configure failure\n");
1777 mpu_port = -1;
1778 chip->devmpu = NULL;
1779 } else {
1780 mpu_port = pnp_port_start(pdev, 0);
1781 mpu_irq = pnp_irq(pdev, 0);
1782 }
1783 }
1784 kfree(cfg);
1785 return pid->driver_data;
1786}
1787#endif /* CONFIG_PNP */
1788
1789#if 0
1790static int __devinit snd_card_opti9xx_resources(struct snd_card_opti9xx *chip,
1791 snd_card_t *card)
1792{
1793 int error, i, pnp = 0;
1794
1795#ifdef CONFIG_PNP
1796 pnp = chip->dev != NULL;
1797#endif /* CONFIG_PNP */
1798
1799#ifndef OPTi93X
1800 if (chip->chip->hardware == OPTi9XX_HW_82C928)
1801 mpu_port = -1;
1802#endif /* OPTi93X */
1803 error = 0;
1804 if (!pnp && (mpu_port == SNDRV_DEFAULT_PORT1)) {
1805 for (i = 0; possible_mpu_ports[i] != -1; i++)
1806 if (!snd_register_ioport(card, possible_mpu_ports[i], 2,
1807 DRIVER_NAME" - MPU-401", NULL)) {
1808 mpu_port = possible_mpu_ports[i];
1809 break;
1810 }
1811 if (mpu_port == SNDRV_DEFAULT_PORT1)
1812 error = -EBUSY;
1813 }
1814 else
1815 error = (mpu_port == -1) ? -ENODEV :
1816 snd_register_ioport(card, mpu_port, 2,
1817 DRIVER_NAME" - MPU-401", NULL);
1818 if (error)
1819 chip->chip->mpu_port = -1;
1820 else if (pnp && (irq == mpu_irq))
1821 chip->chip->mpu_irq = mpu_irq;
1822 else if (!snd_register_interrupt(card,
1823 DRIVER_NAME" - MPU-401",
1824 mpu_irq, SNDRV_IRQ_TYPE_ISA,
1825 snd_card_opti9xx_mpu_interrupt, chip,
1826 pnp ? no_alternatives : possible_mpu_irqs,
1827 &chip->mpuirqptr)) {
1828 chip->chip->mpu_port = mpu_port;
1829 chip->chip->mpu_irq = chip->mpuirqptr->irq;
1830 }
1831 else
1832 chip->chip->mpu_port = -1;
1833
1834 if (!pnp && (port == SNDRV_DEFAULT_PORT1)) {
1835 for (i = 0; possible_ports[i] != -1; i++)
1836 if (!snd_register_ioport(card, possible_ports[i], 8,
1837 DRIVER_NAME" - WSS", NULL)) {
1838 port = possible_ports[i];
1839 break;
1840 }
1841 if (port == SNDRV_DEFAULT_PORT1)
1842 return -EBUSY;
1843 }
1844 else if ((error = snd_register_ioport(card, port, 8,
1845 DRIVER_NAME" - WSS", NULL)) < 0)
1846 return error;
1847 chip->chip->wss_base = port;
1848 if ((error = snd_register_interrupt(card, DRIVER_NAME" - WSS",
1849 irq, SNDRV_IRQ_TYPE_ISA,
1850 snd_card_opti9xx_interrupt, chip,
1851 pnp ? no_alternatives : possible_irqs,
1852 &chip->irqptr)) < 0)
1853 return error;
1854 chip->chip->irq = chip->irqptr->irq;
1855 if ((error = snd_register_dma_channel(card,
1856#if defined(CS4231) || defined(OPTi93X)
1857 DRIVER_NAME" - WSS playback",
1858#else
1859 DRIVER_NAME" - WSS",
1860#endif /* CS4231 || OPTi93X */
1861 dma1, SNDRV_DMA_TYPE_ISA, dma1_size,
1862 pnp ? no_alternatives : possible_dma1s,
1863 &chip->dma1ptr)) < 0)
1864 return error;
1865 chip->chip->dma1 = chip->dma1ptr->dma;
1866#if defined(CS4231) || defined(OPTi93X)
1867 if ((error = snd_register_dma_channel(card, DRIVER_NAME" - WSS capture",
1868 dma2, SNDRV_DMA_TYPE_ISA, dma2_size,
1869 pnp ? no_alternatives :
1870 possible_dma2s[chip->dma1ptr->dma],
1871 &chip->dma2ptr)) < 0)
1872 return error;
1873 chip->chip->dma2 = chip->dma2ptr->dma;
1874#endif /* CS4231 || OPTi93X */
1875
1876 if (snd_register_ioport(card,
1877 pnp ? fm_port : fm_port = 0x388, 4,
1878 DRIVER_NAME" - OPL", NULL) < 0)
1879 fm_port = -1;
1880 chip->chip->fm_port = fm_port;
1881
1882 return 0;
1883}
1884#endif
1885
1886static void snd_card_opti9xx_free(snd_card_t *card)
1887{
1888 opti9xx_t *chip = (opti9xx_t *)card->private_data;
1889
1890 if (chip) {
1891 if (chip->res_mc_base) {
1892 release_resource(chip->res_mc_base);
1893 kfree_nocheck(chip->res_mc_base);
1894 }
1895 }
1896}
1897
1898static int __devinit snd_card_opti9xx_probe(struct pnp_card_link *pcard,
1899 const struct pnp_card_device_id *pid)
1900{
1901 static long possible_ports[] = {0x530, 0xe80, 0xf40, 0x604, -1};
1902 static long possible_mpu_ports[] = {0x300, 0x310, 0x320, 0x330, -1};
1903#ifdef OPTi93X
1904 static int possible_irqs[] = {5, 9, 10, 11, 7, -1};
1905#else
1906 static int possible_irqs[] = {9, 10, 11, 7, -1};
1907#endif /* OPTi93X */
1908 static int possible_mpu_irqs[] = {5, 9, 10, 7, -1};
1909 static int possible_dma1s[] = {3, 1, 0, -1};
1910#if defined(CS4231) || defined(OPTi93X)
1911 static int possible_dma2s[][2] = {{1,-1}, {0,-1}, {-1,-1}, {0,-1}};
1912#endif /* CS4231 || OPTi93X */
1913 int error;
1914 opti9xx_t *chip;
1915#if defined(OPTi93X)
1916 opti93x_t *codec;
1917#elif defined(CS4231)
1918 cs4231_t *codec;
1919 snd_timer_t *timer;
1920#else
1921 ad1848_t *codec;
1922#endif
1923 snd_card_t *card;
1924 snd_pcm_t *pcm;
1925 snd_rawmidi_t *rmidi;
1926 snd_hwdep_t *synth;
1927#ifdef CONFIG_PNP
1928 int hw;
1929#endif /* CONFIG_PNP */
1930
1931 if (pcard && !snd_opti9xx_first_hit)
1932 return -EBUSY;
1933 if (!(card = snd_card_new(index, id, THIS_MODULE,
1934 sizeof(opti9xx_t))))
1935 return -ENOMEM;
1936 card->private_free = snd_card_opti9xx_free;
1937 chip = (opti9xx_t *)card->private_data;
1938
1939#ifdef CONFIG_PNP
1940 if (isapnp && pcard && (hw = snd_card_opti9xx_pnp(chip, pcard, pid)) > 0) {
1941 switch (hw) {
1942 case 0x0924:
1943 hw = OPTi9XX_HW_82C924;
1944 break;
1945 case 0x0925:
1946 hw = OPTi9XX_HW_82C925;
1947 break;
1948 case 0x0931:
1949 hw = OPTi9XX_HW_82C931;
1950 break;
1951 default:
1952 snd_card_free(card);
1953 return -ENODEV;
1954 }
1955
1956 if ((error = snd_opti9xx_init(chip, hw))) {
1957 snd_card_free(card);
1958 return error;
1959 }
1960 if (hw <= OPTi9XX_HW_82C930)
1961 chip->mc_base -= 0x80;
1962 snd_card_set_dev(card, &pcard->card->dev);
1963 } else {
1964#endif /* CONFIG_PNP */
1965 if ((error = snd_card_opti9xx_detect(card, chip)) < 0) {
1966 snd_card_free(card);
1967 return error;
1968 }
1969#ifdef CONFIG_PNP
1970 }
1971#endif /* CONFIG_PNP */
1972
1973 if (! chip->res_mc_base &&
1974 (chip->res_mc_base = request_region(chip->mc_base, chip->mc_base_size, "OPTi9xx MC")) == NULL) {
1975 snd_card_free(card);
1976 return -ENOMEM;
1977 }
1978
1979 chip->wss_base = port;
1980 chip->fm_port = fm_port;
1981 chip->mpu_port = mpu_port;
1982 chip->irq = irq;
1983 chip->mpu_irq = mpu_irq;
1984 chip->dma1 = dma1;
1985#if defined(CS4231) || defined(OPTi93X)
1986 chip->dma2 = dma2;
1987#endif
1988
1989 if (chip->wss_base == SNDRV_AUTO_PORT) {
1990 if ((chip->wss_base = snd_legacy_find_free_ioport(possible_ports, 4)) < 0) {
1991 snd_card_free(card);
1992 snd_printk("unable to find a free WSS port\n");
1993 return -EBUSY;
1994 }
1995 }
1996#ifdef CONFIG_PNP
1997 if (!isapnp) {
1998#endif
1999 if (chip->mpu_port == SNDRV_AUTO_PORT) {
2000 if ((chip->mpu_port = snd_legacy_find_free_ioport(possible_mpu_ports, 2)) < 0) {
2001 snd_card_free(card);
2002 snd_printk("unable to find a free MPU401 port\n");
2003 return -EBUSY;
2004 }
2005 }
2006 if (chip->irq == SNDRV_AUTO_IRQ) {
2007 if ((chip->irq = snd_legacy_find_free_irq(possible_irqs)) < 0) {
2008 snd_card_free(card);
2009 snd_printk("unable to find a free IRQ\n");
2010 return -EBUSY;
2011 }
2012 }
2013 if (chip->mpu_irq == SNDRV_AUTO_IRQ) {
2014 if ((chip->mpu_irq = snd_legacy_find_free_irq(possible_mpu_irqs)) < 0) {
2015 snd_card_free(card);
2016 snd_printk("unable to find a free MPU401 IRQ\n");
2017 return -EBUSY;
2018 }
2019 }
2020 if (chip->dma1 == SNDRV_AUTO_DMA) {
2021 if ((chip->dma1 = snd_legacy_find_free_dma(possible_dma1s)) < 0) {
2022 snd_card_free(card);
2023 snd_printk("unable to find a free DMA1\n");
2024 return -EBUSY;
2025 }
2026 }
2027#if defined(CS4231) || defined(OPTi93X)
2028 if (chip->dma2 == SNDRV_AUTO_DMA) {
2029 if ((chip->dma2 = snd_legacy_find_free_dma(possible_dma2s[chip->dma1 % 4])) < 0) {
2030 snd_card_free(card);
2031 snd_printk("unable to find a free DMA2\n");
2032 return -EBUSY;
2033 }
2034 }
2035#endif
2036
2037#ifdef CONFIG_PNP
2038 }
2039#endif
2040
2041 if ((error = snd_opti9xx_configure(chip))) {
2042 snd_card_free(card);
2043 return error;
2044 }
2045
2046#if defined(OPTi93X)
2047 if ((error = snd_opti93x_create(card, chip, chip->dma1, chip->dma2, &codec))) {
2048 snd_card_free(card);
2049 return error;
2050 }
2051 if ((error = snd_opti93x_pcm(codec, 0, &pcm)) < 0) {
2052 snd_card_free(card);
2053 return error;
2054 }
2055 if ((error = snd_opti93x_mixer(codec)) < 0) {
2056 snd_card_free(card);
2057 return error;
2058 }
2059#elif defined(CS4231)
2060 if ((error = snd_cs4231_create(card, chip->wss_base + 4, -1,
2061 chip->irq, chip->dma1, chip->dma2,
2062 CS4231_HW_DETECT,
2063 0,
2064 &codec)) < 0) {
2065 snd_card_free(card);
2066 return error;
2067 }
2068 if ((error = snd_cs4231_pcm(codec, 0, &pcm)) < 0) {
2069 snd_card_free(card);
2070 return error;
2071 }
2072 if ((error = snd_cs4231_mixer(codec)) < 0) {
2073 snd_card_free(card);
2074 return error;
2075 }
2076 if ((error = snd_cs4231_timer(codec, 0, &timer)) < 0) {
2077 snd_card_free(card);
2078 return error;
2079 }
2080#else
2081 if ((error = snd_ad1848_create(card, chip->wss_base + 4,
2082 chip->irq, chip->dma1,
2083 AD1848_HW_DETECT, &codec)) < 0) {
2084 snd_card_free(card);
2085 return error;
2086 }
2087 if ((error = snd_ad1848_pcm(codec, 0, &pcm)) < 0) {
2088 snd_card_free(card);
2089 return error;
2090 }
2091 if ((error = snd_ad1848_mixer(codec)) < 0) {
2092 snd_card_free(card);
2093 return error;
2094 }
2095#endif
2096 strcpy(card->driver, chip->name);
2097 sprintf(card->shortname, "OPTi %s", card->driver);
2098#if defined(CS4231) || defined(OPTi93X)
2099 sprintf(card->longname, "%s, %s at 0x%lx, irq %d, dma %d&%d",
2100 card->shortname, pcm->name, chip->wss_base + 4,
2101 chip->irq, chip->dma1, chip->dma2);
2102#else
2103 sprintf(card->longname, "%s, %s at 0x%lx, irq %d, dma %d",
2104 card->shortname, pcm->name, chip->wss_base + 4,
2105 chip->irq, chip->dma1);
2106#endif /* CS4231 || OPTi93X */
2107
2108 if (chip->mpu_port <= 0 || chip->mpu_port == SNDRV_AUTO_PORT)
2109 rmidi = NULL;
2110 else
2111 if ((error = snd_mpu401_uart_new(card, 0, MPU401_HW_MPU401,
2112 chip->mpu_port, 0, chip->mpu_irq, SA_INTERRUPT,
2113 &rmidi)))
2114 snd_printk("no MPU-401 device at 0x%lx?\n", chip->mpu_port);
2115
2116 if (chip->fm_port > 0 && chip->fm_port != SNDRV_AUTO_PORT) {
2117 opl3_t *opl3 = NULL;
2118#ifndef OPTi93X
2119 if (chip->hardware == OPTi9XX_HW_82C928 ||
2120 chip->hardware == OPTi9XX_HW_82C929 ||
2121 chip->hardware == OPTi9XX_HW_82C924) {
2122 opl4_t *opl4;
2123 /* assume we have an OPL4 */
2124 snd_opti9xx_write_mask(chip, OPTi9XX_MC_REG(2),
2125 0x20, 0x20);
2126 if (snd_opl4_create(card,
2127 chip->fm_port,
2128 chip->fm_port - 8,
2129 2, &opl3, &opl4) < 0) {
2130 /* no luck, use OPL3 instead */
2131 snd_opti9xx_write_mask(chip, OPTi9XX_MC_REG(2),
2132 0x00, 0x20);
2133 }
2134 }
2135#endif /* !OPTi93X */
2136 if (!opl3 && snd_opl3_create(card,
2137 chip->fm_port,
2138 chip->fm_port + 2,
2139 OPL3_HW_AUTO, 0, &opl3) < 0) {
2140 snd_printk("no OPL device at 0x%lx-0x%lx\n",
2141 chip->fm_port, chip->fm_port + 4 - 1);
2142 }
2143 if (opl3) {
2144 if ((error = snd_opl3_timer_new(opl3,
2145#ifdef CS4231
2146 1, 2)) < 0) {
2147#else
2148 0, 1)) < 0) {
2149#endif /* CS4231 */
2150 snd_card_free(card);
2151 return error;
2152 }
2153 if ((error = snd_opl3_hwdep_new(opl3, 0, 1, &synth)) < 0) {
2154 snd_card_free(card);
2155 return error;
2156 }
2157 }
2158 }
2159
2160 if ((error = snd_card_register(card))) {
2161 snd_card_free(card);
2162 return error;
2163 }
2164 snd_opti9xx_first_hit = 0;
2165 if (pcard)
2166 pnp_set_card_drvdata(pcard, card);
2167 else
2168 snd_opti9xx_legacy = card;
2169 return 0;
2170}
2171
2172#ifdef CONFIG_PNP
2173static void __devexit snd_opti9xx_pnp_remove(struct pnp_card_link * pcard)
2174{
2175 snd_card_t *card = (snd_card_t *) pnp_get_card_drvdata(pcard);
2176
2177 snd_card_disconnect(card);
2178 snd_card_free_in_thread(card);
2179 snd_opti9xx_first_hit = 0;
2180}
2181
2182static struct pnp_card_driver opti9xx_pnpc_driver = {
2183 .flags = PNP_DRIVER_RES_DISABLE,
2184 .name = "opti9xx",
2185 .id_table = snd_opti9xx_pnpids,
2186 .probe = snd_card_opti9xx_probe,
2187 .remove = __devexit_p(snd_opti9xx_pnp_remove),
2188};
2189#endif
2190
2191static int __init alsa_card_opti9xx_init(void)
2192{
2193 int cards, error;
2194
2195#ifdef CONFIG_PNP
2196 cards = pnp_register_card_driver(&opti9xx_pnpc_driver);
2197#else
2198 cards = 0;
2199#endif
2200 if (cards == 0 && (error = snd_card_opti9xx_probe(NULL, NULL)) < 0) {
2201#ifdef CONFIG_PNP
2202 pnp_unregister_card_driver(&opti9xx_pnpc_driver);
2203#endif
2204#ifdef MODULE
2205#ifdef OPTi93X
2206 printk(KERN_ERR "no OPTi 82C93x soundcard found\n");
2207#else
2208 printk(KERN_ERR "no OPTi 82C92x soundcard found\n");
2209#endif /* OPTi93X */
2210#endif
2211 return error;
2212 }
2213 return 0;
2214}
2215
2216static void __exit alsa_card_opti9xx_exit(void)
2217{
2218#ifdef CONFIG_PNP
2219 pnp_unregister_card_driver(&opti9xx_pnpc_driver);
2220#endif
2221 if (snd_opti9xx_legacy)
2222 snd_card_free(snd_opti9xx_legacy);
2223}
2224
2225module_init(alsa_card_opti9xx_init)
2226module_exit(alsa_card_opti9xx_exit)
diff --git a/sound/isa/opti9xx/opti92x-cs4231.c b/sound/isa/opti9xx/opti92x-cs4231.c
new file mode 100644
index 000000000000..b17ab19f6d81
--- /dev/null
+++ b/sound/isa/opti9xx/opti92x-cs4231.c
@@ -0,0 +1,2 @@
1#define CS4231
2#include "opti92x-ad1848.c"
diff --git a/sound/isa/opti9xx/opti93x.c b/sound/isa/opti9xx/opti93x.c
new file mode 100644
index 000000000000..bad9da521bf9
--- /dev/null
+++ b/sound/isa/opti9xx/opti93x.c
@@ -0,0 +1,3 @@
1#define OPTi93X
2#include "opti92x-ad1848.c"
3
diff --git a/sound/isa/sb/Makefile b/sound/isa/sb/Makefile
new file mode 100644
index 000000000000..fd9d9c5726fc
--- /dev/null
+++ b/sound/isa/sb/Makefile
@@ -0,0 +1,39 @@
1#
2# Makefile for ALSA
3# Copyright (c) 2001 by Jaroslav Kysela <perex@suse.cz>
4#
5
6snd-sb-common-objs := sb_common.o sb_mixer.o
7snd-sb8-dsp-objs := sb8_main.o sb8_midi.o
8snd-sb16-dsp-objs := sb16_main.o
9snd-sb16-csp-objs := sb16_csp.o
10snd-sb8-objs := sb8.o
11snd-sb16-objs := sb16.o
12snd-sbawe-objs := sbawe.o emu8000.o
13snd-emu8000-synth-objs := emu8000_synth.o emu8000_callback.o emu8000_patch.o emu8000_pcm.o
14snd-es968-objs := es968.o
15
16#
17# this function returns:
18# "m" - CONFIG_SND_SEQUENCER is m
19# <empty string> - CONFIG_SND_SEQUENCER is undefined
20# otherwise parameter #1 value
21#
22sequencer = $(if $(subst y,,$(CONFIG_SND_SEQUENCER)),$(if $(1),m),$(if $(CONFIG_SND_SEQUENCER),$(1)))
23
24# Toplevel Module Dependency
25obj-$(CONFIG_SND_ALS100) += snd-sb16-dsp.o snd-sb-common.o
26obj-$(CONFIG_SND_CMI8330) += snd-sb16-dsp.o snd-sb-common.o
27obj-$(CONFIG_SND_DT019X) += snd-sb16-dsp.o snd-sb-common.o
28obj-$(CONFIG_SND_SB8) += snd-sb8.o snd-sb8-dsp.o snd-sb-common.o
29obj-$(CONFIG_SND_SB16) += snd-sb16.o snd-sb16-dsp.o snd-sb-common.o
30obj-$(CONFIG_SND_SBAWE) += snd-sbawe.o snd-sb16-dsp.o snd-sb-common.o
31obj-$(CONFIG_SND_ES968) += snd-es968.o snd-sb8-dsp.o snd-sb-common.o
32obj-$(CONFIG_SND_ALS4000) += snd-sb-common.o
33ifeq ($(CONFIG_SND_SB16_CSP),y)
34 obj-$(CONFIG_SND_SB16) += snd-sb16-csp.o
35 obj-$(CONFIG_SND_SBAWE) += snd-sb16-csp.o
36endif
37obj-$(call sequencer,$(CONFIG_SND_SBAWE)) += snd-emu8000-synth.o
38
39obj-m := $(sort $(obj-m))
diff --git a/sound/isa/sb/emu8000.c b/sound/isa/sb/emu8000.c
new file mode 100644
index 000000000000..028af4066595
--- /dev/null
+++ b/sound/isa/sb/emu8000.c
@@ -0,0 +1,1170 @@
1/*
2 * Copyright (c) by Jaroslav Kysela <perex@suse.cz>
3 * and (c) 1999 Steve Ratcliffe <steve@parabola.demon.co.uk>
4 * Copyright (C) 1999-2000 Takashi Iwai <tiwai@suse.de>
5 *
6 * Routines for control of EMU8000 chip
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21 */
22
23#include <sound/driver.h>
24#include <linux/wait.h>
25#include <linux/sched.h>
26#include <linux/slab.h>
27#include <linux/ioport.h>
28#include <linux/delay.h>
29#include <sound/core.h>
30#include <sound/emu8000.h>
31#include <sound/emu8000_reg.h>
32#include <asm/io.h>
33#include <asm/uaccess.h>
34#include <linux/init.h>
35#include <sound/control.h>
36#include <sound/initval.h>
37
38/*
39 * emu8000 register controls
40 */
41
42/*
43 * The following routines read and write registers on the emu8000. They
44 * should always be called via the EMU8000*READ/WRITE macros and never
45 * directly. The macros handle the port number and command word.
46 */
47/* Write a word */
48void snd_emu8000_poke(emu8000_t *emu, unsigned int port, unsigned int reg, unsigned int val)
49{
50 unsigned long flags;
51 spin_lock_irqsave(&emu->reg_lock, flags);
52 if (reg != emu->last_reg) {
53 outw((unsigned short)reg, EMU8000_PTR(emu)); /* Set register */
54 emu->last_reg = reg;
55 }
56 outw((unsigned short)val, port); /* Send data */
57 spin_unlock_irqrestore(&emu->reg_lock, flags);
58}
59
60/* Read a word */
61unsigned short snd_emu8000_peek(emu8000_t *emu, unsigned int port, unsigned int reg)
62{
63 unsigned short res;
64 unsigned long flags;
65 spin_lock_irqsave(&emu->reg_lock, flags);
66 if (reg != emu->last_reg) {
67 outw((unsigned short)reg, EMU8000_PTR(emu)); /* Set register */
68 emu->last_reg = reg;
69 }
70 res = inw(port); /* Read data */
71 spin_unlock_irqrestore(&emu->reg_lock, flags);
72 return res;
73}
74
75/* Write a double word */
76void snd_emu8000_poke_dw(emu8000_t *emu, unsigned int port, unsigned int reg, unsigned int val)
77{
78 unsigned long flags;
79 spin_lock_irqsave(&emu->reg_lock, flags);
80 if (reg != emu->last_reg) {
81 outw((unsigned short)reg, EMU8000_PTR(emu)); /* Set register */
82 emu->last_reg = reg;
83 }
84 outw((unsigned short)val, port); /* Send low word of data */
85 outw((unsigned short)(val>>16), port+2); /* Send high word of data */
86 spin_unlock_irqrestore(&emu->reg_lock, flags);
87}
88
89/* Read a double word */
90unsigned int snd_emu8000_peek_dw(emu8000_t *emu, unsigned int port, unsigned int reg)
91{
92 unsigned short low;
93 unsigned int res;
94 unsigned long flags;
95 spin_lock_irqsave(&emu->reg_lock, flags);
96 if (reg != emu->last_reg) {
97 outw((unsigned short)reg, EMU8000_PTR(emu)); /* Set register */
98 emu->last_reg = reg;
99 }
100 low = inw(port); /* Read low word of data */
101 res = low + (inw(port+2) << 16);
102 spin_unlock_irqrestore(&emu->reg_lock, flags);
103 return res;
104}
105
106/*
107 * Set up / close a channel to be used for DMA.
108 */
109/*exported*/ void
110snd_emu8000_dma_chan(emu8000_t *emu, int ch, int mode)
111{
112 unsigned right_bit = (mode & EMU8000_RAM_RIGHT) ? 0x01000000 : 0;
113 mode &= EMU8000_RAM_MODE_MASK;
114 if (mode == EMU8000_RAM_CLOSE) {
115 EMU8000_CCCA_WRITE(emu, ch, 0);
116 EMU8000_DCYSUSV_WRITE(emu, ch, 0x807F);
117 return;
118 }
119 EMU8000_DCYSUSV_WRITE(emu, ch, 0x80);
120 EMU8000_VTFT_WRITE(emu, ch, 0);
121 EMU8000_CVCF_WRITE(emu, ch, 0);
122 EMU8000_PTRX_WRITE(emu, ch, 0x40000000);
123 EMU8000_CPF_WRITE(emu, ch, 0x40000000);
124 EMU8000_PSST_WRITE(emu, ch, 0);
125 EMU8000_CSL_WRITE(emu, ch, 0);
126 if (mode == EMU8000_RAM_WRITE) /* DMA write */
127 EMU8000_CCCA_WRITE(emu, ch, 0x06000000 | right_bit);
128 else /* DMA read */
129 EMU8000_CCCA_WRITE(emu, ch, 0x04000000 | right_bit);
130}
131
132/*
133 */
134static void __init
135snd_emu8000_read_wait(emu8000_t *emu)
136{
137 while ((EMU8000_SMALR_READ(emu) & 0x80000000) != 0) {
138 set_current_state(TASK_INTERRUPTIBLE);
139 schedule_timeout(1);
140 if (signal_pending(current))
141 break;
142 }
143}
144
145/*
146 */
147static void __init
148snd_emu8000_write_wait(emu8000_t *emu)
149{
150 while ((EMU8000_SMALW_READ(emu) & 0x80000000) != 0) {
151 set_current_state(TASK_INTERRUPTIBLE);
152 schedule_timeout(1);
153 if (signal_pending(current))
154 break;
155 }
156}
157
158/*
159 * detect a card at the given port
160 */
161static int __init
162snd_emu8000_detect(emu8000_t *emu)
163{
164 /* Initialise */
165 EMU8000_HWCF1_WRITE(emu, 0x0059);
166 EMU8000_HWCF2_WRITE(emu, 0x0020);
167 EMU8000_HWCF3_WRITE(emu, 0x0000);
168 /* Check for a recognisable emu8000 */
169 /*
170 if ((EMU8000_U1_READ(emu) & 0x000f) != 0x000c)
171 return -ENODEV;
172 */
173 if ((EMU8000_HWCF1_READ(emu) & 0x007e) != 0x0058)
174 return -ENODEV;
175 if ((EMU8000_HWCF2_READ(emu) & 0x0003) != 0x0003)
176 return -ENODEV;
177
178 snd_printdd("EMU8000 [0x%lx]: Synth chip found\n",
179 emu->port1);
180 return 0;
181}
182
183
184/*
185 * intiailize audio channels
186 */
187static void __init
188init_audio(emu8000_t *emu)
189{
190 int ch;
191
192 /* turn off envelope engines */
193 for (ch = 0; ch < EMU8000_CHANNELS; ch++)
194 EMU8000_DCYSUSV_WRITE(emu, ch, 0x80);
195
196 /* reset all other parameters to zero */
197 for (ch = 0; ch < EMU8000_CHANNELS; ch++) {
198 EMU8000_ENVVOL_WRITE(emu, ch, 0);
199 EMU8000_ENVVAL_WRITE(emu, ch, 0);
200 EMU8000_DCYSUS_WRITE(emu, ch, 0);
201 EMU8000_ATKHLDV_WRITE(emu, ch, 0);
202 EMU8000_LFO1VAL_WRITE(emu, ch, 0);
203 EMU8000_ATKHLD_WRITE(emu, ch, 0);
204 EMU8000_LFO2VAL_WRITE(emu, ch, 0);
205 EMU8000_IP_WRITE(emu, ch, 0);
206 EMU8000_IFATN_WRITE(emu, ch, 0);
207 EMU8000_PEFE_WRITE(emu, ch, 0);
208 EMU8000_FMMOD_WRITE(emu, ch, 0);
209 EMU8000_TREMFRQ_WRITE(emu, ch, 0);
210 EMU8000_FM2FRQ2_WRITE(emu, ch, 0);
211 EMU8000_PTRX_WRITE(emu, ch, 0);
212 EMU8000_VTFT_WRITE(emu, ch, 0);
213 EMU8000_PSST_WRITE(emu, ch, 0);
214 EMU8000_CSL_WRITE(emu, ch, 0);
215 EMU8000_CCCA_WRITE(emu, ch, 0);
216 }
217
218 for (ch = 0; ch < EMU8000_CHANNELS; ch++) {
219 EMU8000_CPF_WRITE(emu, ch, 0);
220 EMU8000_CVCF_WRITE(emu, ch, 0);
221 }
222}
223
224
225/*
226 * initialize DMA address
227 */
228static void __init
229init_dma(emu8000_t *emu)
230{
231 EMU8000_SMALR_WRITE(emu, 0);
232 EMU8000_SMARR_WRITE(emu, 0);
233 EMU8000_SMALW_WRITE(emu, 0);
234 EMU8000_SMARW_WRITE(emu, 0);
235}
236
237/*
238 * initialization arrays; from ADIP
239 */
240static unsigned short init1[128] /*__devinitdata*/ = {
241 0x03ff, 0x0030, 0x07ff, 0x0130, 0x0bff, 0x0230, 0x0fff, 0x0330,
242 0x13ff, 0x0430, 0x17ff, 0x0530, 0x1bff, 0x0630, 0x1fff, 0x0730,
243 0x23ff, 0x0830, 0x27ff, 0x0930, 0x2bff, 0x0a30, 0x2fff, 0x0b30,
244 0x33ff, 0x0c30, 0x37ff, 0x0d30, 0x3bff, 0x0e30, 0x3fff, 0x0f30,
245
246 0x43ff, 0x0030, 0x47ff, 0x0130, 0x4bff, 0x0230, 0x4fff, 0x0330,
247 0x53ff, 0x0430, 0x57ff, 0x0530, 0x5bff, 0x0630, 0x5fff, 0x0730,
248 0x63ff, 0x0830, 0x67ff, 0x0930, 0x6bff, 0x0a30, 0x6fff, 0x0b30,
249 0x73ff, 0x0c30, 0x77ff, 0x0d30, 0x7bff, 0x0e30, 0x7fff, 0x0f30,
250
251 0x83ff, 0x0030, 0x87ff, 0x0130, 0x8bff, 0x0230, 0x8fff, 0x0330,
252 0x93ff, 0x0430, 0x97ff, 0x0530, 0x9bff, 0x0630, 0x9fff, 0x0730,
253 0xa3ff, 0x0830, 0xa7ff, 0x0930, 0xabff, 0x0a30, 0xafff, 0x0b30,
254 0xb3ff, 0x0c30, 0xb7ff, 0x0d30, 0xbbff, 0x0e30, 0xbfff, 0x0f30,
255
256 0xc3ff, 0x0030, 0xc7ff, 0x0130, 0xcbff, 0x0230, 0xcfff, 0x0330,
257 0xd3ff, 0x0430, 0xd7ff, 0x0530, 0xdbff, 0x0630, 0xdfff, 0x0730,
258 0xe3ff, 0x0830, 0xe7ff, 0x0930, 0xebff, 0x0a30, 0xefff, 0x0b30,
259 0xf3ff, 0x0c30, 0xf7ff, 0x0d30, 0xfbff, 0x0e30, 0xffff, 0x0f30,
260};
261
262static unsigned short init2[128] /*__devinitdata*/ = {
263 0x03ff, 0x8030, 0x07ff, 0x8130, 0x0bff, 0x8230, 0x0fff, 0x8330,
264 0x13ff, 0x8430, 0x17ff, 0x8530, 0x1bff, 0x8630, 0x1fff, 0x8730,
265 0x23ff, 0x8830, 0x27ff, 0x8930, 0x2bff, 0x8a30, 0x2fff, 0x8b30,
266 0x33ff, 0x8c30, 0x37ff, 0x8d30, 0x3bff, 0x8e30, 0x3fff, 0x8f30,
267
268 0x43ff, 0x8030, 0x47ff, 0x8130, 0x4bff, 0x8230, 0x4fff, 0x8330,
269 0x53ff, 0x8430, 0x57ff, 0x8530, 0x5bff, 0x8630, 0x5fff, 0x8730,
270 0x63ff, 0x8830, 0x67ff, 0x8930, 0x6bff, 0x8a30, 0x6fff, 0x8b30,
271 0x73ff, 0x8c30, 0x77ff, 0x8d30, 0x7bff, 0x8e30, 0x7fff, 0x8f30,
272
273 0x83ff, 0x8030, 0x87ff, 0x8130, 0x8bff, 0x8230, 0x8fff, 0x8330,
274 0x93ff, 0x8430, 0x97ff, 0x8530, 0x9bff, 0x8630, 0x9fff, 0x8730,
275 0xa3ff, 0x8830, 0xa7ff, 0x8930, 0xabff, 0x8a30, 0xafff, 0x8b30,
276 0xb3ff, 0x8c30, 0xb7ff, 0x8d30, 0xbbff, 0x8e30, 0xbfff, 0x8f30,
277
278 0xc3ff, 0x8030, 0xc7ff, 0x8130, 0xcbff, 0x8230, 0xcfff, 0x8330,
279 0xd3ff, 0x8430, 0xd7ff, 0x8530, 0xdbff, 0x8630, 0xdfff, 0x8730,
280 0xe3ff, 0x8830, 0xe7ff, 0x8930, 0xebff, 0x8a30, 0xefff, 0x8b30,
281 0xf3ff, 0x8c30, 0xf7ff, 0x8d30, 0xfbff, 0x8e30, 0xffff, 0x8f30,
282};
283
284static unsigned short init3[128] /*__devinitdata*/ = {
285 0x0C10, 0x8470, 0x14FE, 0xB488, 0x167F, 0xA470, 0x18E7, 0x84B5,
286 0x1B6E, 0x842A, 0x1F1D, 0x852A, 0x0DA3, 0x8F7C, 0x167E, 0xF254,
287 0x0000, 0x842A, 0x0001, 0x852A, 0x18E6, 0x8BAA, 0x1B6D, 0xF234,
288 0x229F, 0x8429, 0x2746, 0x8529, 0x1F1C, 0x86E7, 0x229E, 0xF224,
289
290 0x0DA4, 0x8429, 0x2C29, 0x8529, 0x2745, 0x87F6, 0x2C28, 0xF254,
291 0x383B, 0x8428, 0x320F, 0x8528, 0x320E, 0x8F02, 0x1341, 0xF264,
292 0x3EB6, 0x8428, 0x3EB9, 0x8528, 0x383A, 0x8FA9, 0x3EB5, 0xF294,
293 0x3EB7, 0x8474, 0x3EBA, 0x8575, 0x3EB8, 0xC4C3, 0x3EBB, 0xC5C3,
294
295 0x0000, 0xA404, 0x0001, 0xA504, 0x141F, 0x8671, 0x14FD, 0x8287,
296 0x3EBC, 0xE610, 0x3EC8, 0x8C7B, 0x031A, 0x87E6, 0x3EC8, 0x86F7,
297 0x3EC0, 0x821E, 0x3EBE, 0xD208, 0x3EBD, 0x821F, 0x3ECA, 0x8386,
298 0x3EC1, 0x8C03, 0x3EC9, 0x831E, 0x3ECA, 0x8C4C, 0x3EBF, 0x8C55,
299
300 0x3EC9, 0xC208, 0x3EC4, 0xBC84, 0x3EC8, 0x8EAD, 0x3EC8, 0xD308,
301 0x3EC2, 0x8F7E, 0x3ECB, 0x8219, 0x3ECB, 0xD26E, 0x3EC5, 0x831F,
302 0x3EC6, 0xC308, 0x3EC3, 0xB2FF, 0x3EC9, 0x8265, 0x3EC9, 0x8319,
303 0x1342, 0xD36E, 0x3EC7, 0xB3FF, 0x0000, 0x8365, 0x1420, 0x9570,
304};
305
306static unsigned short init4[128] /*__devinitdata*/ = {
307 0x0C10, 0x8470, 0x14FE, 0xB488, 0x167F, 0xA470, 0x18E7, 0x84B5,
308 0x1B6E, 0x842A, 0x1F1D, 0x852A, 0x0DA3, 0x0F7C, 0x167E, 0x7254,
309 0x0000, 0x842A, 0x0001, 0x852A, 0x18E6, 0x0BAA, 0x1B6D, 0x7234,
310 0x229F, 0x8429, 0x2746, 0x8529, 0x1F1C, 0x06E7, 0x229E, 0x7224,
311
312 0x0DA4, 0x8429, 0x2C29, 0x8529, 0x2745, 0x07F6, 0x2C28, 0x7254,
313 0x383B, 0x8428, 0x320F, 0x8528, 0x320E, 0x0F02, 0x1341, 0x7264,
314 0x3EB6, 0x8428, 0x3EB9, 0x8528, 0x383A, 0x0FA9, 0x3EB5, 0x7294,
315 0x3EB7, 0x8474, 0x3EBA, 0x8575, 0x3EB8, 0x44C3, 0x3EBB, 0x45C3,
316
317 0x0000, 0xA404, 0x0001, 0xA504, 0x141F, 0x0671, 0x14FD, 0x0287,
318 0x3EBC, 0xE610, 0x3EC8, 0x0C7B, 0x031A, 0x07E6, 0x3EC8, 0x86F7,
319 0x3EC0, 0x821E, 0x3EBE, 0xD208, 0x3EBD, 0x021F, 0x3ECA, 0x0386,
320 0x3EC1, 0x0C03, 0x3EC9, 0x031E, 0x3ECA, 0x8C4C, 0x3EBF, 0x0C55,
321
322 0x3EC9, 0xC208, 0x3EC4, 0xBC84, 0x3EC8, 0x0EAD, 0x3EC8, 0xD308,
323 0x3EC2, 0x8F7E, 0x3ECB, 0x0219, 0x3ECB, 0xD26E, 0x3EC5, 0x031F,
324 0x3EC6, 0xC308, 0x3EC3, 0x32FF, 0x3EC9, 0x0265, 0x3EC9, 0x8319,
325 0x1342, 0xD36E, 0x3EC7, 0x33FF, 0x0000, 0x8365, 0x1420, 0x9570,
326};
327
328/* send an initialization array
329 * Taken from the oss driver, not obvious from the doc how this
330 * is meant to work
331 */
332static void __init
333send_array(emu8000_t *emu, unsigned short *data, int size)
334{
335 int i;
336 unsigned short *p;
337
338 p = data;
339 for (i = 0; i < size; i++, p++)
340 EMU8000_INIT1_WRITE(emu, i, *p);
341 for (i = 0; i < size; i++, p++)
342 EMU8000_INIT2_WRITE(emu, i, *p);
343 for (i = 0; i < size; i++, p++)
344 EMU8000_INIT3_WRITE(emu, i, *p);
345 for (i = 0; i < size; i++, p++)
346 EMU8000_INIT4_WRITE(emu, i, *p);
347}
348
349
350/*
351 * Send initialization arrays to start up, this just follows the
352 * initialisation sequence in the adip.
353 */
354static void __init
355init_arrays(emu8000_t *emu)
356{
357 send_array(emu, init1, ARRAY_SIZE(init1)/4);
358
359 msleep((1024 * 1000) / 44100); /* wait for 1024 clocks */
360 send_array(emu, init2, ARRAY_SIZE(init2)/4);
361 send_array(emu, init3, ARRAY_SIZE(init3)/4);
362
363 EMU8000_HWCF4_WRITE(emu, 0);
364 EMU8000_HWCF5_WRITE(emu, 0x83);
365 EMU8000_HWCF6_WRITE(emu, 0x8000);
366
367 send_array(emu, init4, ARRAY_SIZE(init4)/4);
368}
369
370
371#define UNIQUE_ID1 0xa5b9
372#define UNIQUE_ID2 0x9d53
373
374/*
375 * Size the onboard memory.
376 * This is written so as not to need arbitary delays after the write. It
377 * seems that the only way to do this is to use the one channel and keep
378 * reallocating between read and write.
379 */
380static void __init
381size_dram(emu8000_t *emu)
382{
383 int i, size;
384
385 if (emu->dram_checked)
386 return;
387
388 size = 0;
389
390 /* write out a magic number */
391 snd_emu8000_dma_chan(emu, 0, EMU8000_RAM_WRITE);
392 snd_emu8000_dma_chan(emu, 1, EMU8000_RAM_READ);
393 EMU8000_SMALW_WRITE(emu, EMU8000_DRAM_OFFSET);
394 EMU8000_SMLD_WRITE(emu, UNIQUE_ID1);
395 snd_emu8000_init_fm(emu); /* This must really be here and not 2 lines back even */
396
397 while (size < EMU8000_MAX_DRAM) {
398
399 size += 512 * 1024; /* increment 512kbytes */
400
401 /* Write a unique data on the test address.
402 * if the address is out of range, the data is written on
403 * 0x200000(=EMU8000_DRAM_OFFSET). Then the id word is
404 * changed by this data.
405 */
406 /*snd_emu8000_dma_chan(emu, 0, EMU8000_RAM_WRITE);*/
407 EMU8000_SMALW_WRITE(emu, EMU8000_DRAM_OFFSET + (size>>1));
408 EMU8000_SMLD_WRITE(emu, UNIQUE_ID2);
409 snd_emu8000_write_wait(emu);
410
411 /*
412 * read the data on the just written DRAM address
413 * if not the same then we have reached the end of ram.
414 */
415 /*snd_emu8000_dma_chan(emu, 0, EMU8000_RAM_READ);*/
416 EMU8000_SMALR_WRITE(emu, EMU8000_DRAM_OFFSET + (size>>1));
417 /*snd_emu8000_read_wait(emu);*/
418 EMU8000_SMLD_READ(emu); /* discard stale data */
419 if (EMU8000_SMLD_READ(emu) != UNIQUE_ID2)
420 break; /* we must have wrapped around */
421
422 snd_emu8000_read_wait(emu);
423
424 /*
425 * If it is the same it could be that the address just
426 * wraps back to the beginning; so check to see if the
427 * initial value has been overwritten.
428 */
429 EMU8000_SMALR_WRITE(emu, EMU8000_DRAM_OFFSET);
430 EMU8000_SMLD_READ(emu); /* discard stale data */
431 if (EMU8000_SMLD_READ(emu) != UNIQUE_ID1)
432 break; /* we must have wrapped around */
433 snd_emu8000_read_wait(emu);
434 }
435
436 /* wait until FULL bit in SMAxW register is false */
437 for (i = 0; i < 10000; i++) {
438 if ((EMU8000_SMALW_READ(emu) & 0x80000000) == 0)
439 break;
440 set_current_state(TASK_INTERRUPTIBLE);
441 schedule_timeout(1);
442 if (signal_pending(current))
443 break;
444 }
445 snd_emu8000_dma_chan(emu, 0, EMU8000_RAM_CLOSE);
446 snd_emu8000_dma_chan(emu, 1, EMU8000_RAM_CLOSE);
447
448 snd_printdd("EMU8000 [0x%lx]: %d Kb on-board memory detected\n",
449 emu->port1, size/1024);
450
451 emu->mem_size = size;
452 emu->dram_checked = 1;
453}
454
455
456/*
457 * Initiailise the FM section. You have to do this to use sample RAM
458 * and therefore lose 2 voices.
459 */
460/*exported*/ void
461snd_emu8000_init_fm(emu8000_t *emu)
462{
463 unsigned long flags;
464
465 /* Initialize the last two channels for DRAM refresh and producing
466 the reverb and chorus effects for Yamaha OPL-3 synthesizer */
467
468 /* 31: FM left channel, 0xffffe0-0xffffe8 */
469 EMU8000_DCYSUSV_WRITE(emu, 30, 0x80);
470 EMU8000_PSST_WRITE(emu, 30, 0xFFFFFFE0); /* full left */
471 EMU8000_CSL_WRITE(emu, 30, 0x00FFFFE8 | (emu->fm_chorus_depth << 24));
472 EMU8000_PTRX_WRITE(emu, 30, (emu->fm_reverb_depth << 8));
473 EMU8000_CPF_WRITE(emu, 30, 0);
474 EMU8000_CCCA_WRITE(emu, 30, 0x00FFFFE3);
475
476 /* 32: FM right channel, 0xfffff0-0xfffff8 */
477 EMU8000_DCYSUSV_WRITE(emu, 31, 0x80);
478 EMU8000_PSST_WRITE(emu, 31, 0x00FFFFF0); /* full right */
479 EMU8000_CSL_WRITE(emu, 31, 0x00FFFFF8 | (emu->fm_chorus_depth << 24));
480 EMU8000_PTRX_WRITE(emu, 31, (emu->fm_reverb_depth << 8));
481 EMU8000_CPF_WRITE(emu, 31, 0x8000);
482 EMU8000_CCCA_WRITE(emu, 31, 0x00FFFFF3);
483
484 snd_emu8000_poke((emu), EMU8000_DATA0(emu), EMU8000_CMD(1, (30)), 0);
485
486 spin_lock_irqsave(&emu->reg_lock, flags);
487 while (!(inw(EMU8000_PTR(emu)) & 0x1000))
488 ;
489 while ((inw(EMU8000_PTR(emu)) & 0x1000))
490 ;
491 spin_unlock_irqrestore(&emu->reg_lock, flags);
492 snd_emu8000_poke((emu), EMU8000_DATA0(emu), EMU8000_CMD(1, (30)), 0x4828);
493 /* this is really odd part.. */
494 outb(0x3C, EMU8000_PTR(emu));
495 outb(0, EMU8000_DATA1(emu));
496
497 /* skew volume & cutoff */
498 EMU8000_VTFT_WRITE(emu, 30, 0x8000FFFF);
499 EMU8000_VTFT_WRITE(emu, 31, 0x8000FFFF);
500}
501
502
503/*
504 * The main initialization routine.
505 */
506static void __init
507snd_emu8000_init_hw(emu8000_t *emu)
508{
509 int i;
510
511 emu->last_reg = 0xffff; /* reset the last register index */
512
513 /* initialize hardware configuration */
514 EMU8000_HWCF1_WRITE(emu, 0x0059);
515 EMU8000_HWCF2_WRITE(emu, 0x0020);
516
517 /* disable audio; this seems to reduce a clicking noise a bit.. */
518 EMU8000_HWCF3_WRITE(emu, 0);
519
520 /* initialize audio channels */
521 init_audio(emu);
522
523 /* initialize DMA */
524 init_dma(emu);
525
526 /* initialize init arrays */
527 init_arrays(emu);
528
529 /*
530 * Initialize the FM section of the AWE32, this is needed
531 * for DRAM refresh as well
532 */
533 snd_emu8000_init_fm(emu);
534
535 /* terminate all voices */
536 for (i = 0; i < EMU8000_DRAM_VOICES; i++)
537 EMU8000_DCYSUSV_WRITE(emu, 0, 0x807F);
538
539 /* check DRAM memory size */
540 size_dram(emu);
541
542 /* enable audio */
543 EMU8000_HWCF3_WRITE(emu, 0x4);
544
545 /* set equzlier, chorus and reverb modes */
546 snd_emu8000_update_equalizer(emu);
547 snd_emu8000_update_chorus_mode(emu);
548 snd_emu8000_update_reverb_mode(emu);
549}
550
551
552/*----------------------------------------------------------------
553 * Bass/Treble Equalizer
554 *----------------------------------------------------------------*/
555
556static unsigned short bass_parm[12][3] = {
557 {0xD26A, 0xD36A, 0x0000}, /* -12 dB */
558 {0xD25B, 0xD35B, 0x0000}, /* -8 */
559 {0xD24C, 0xD34C, 0x0000}, /* -6 */
560 {0xD23D, 0xD33D, 0x0000}, /* -4 */
561 {0xD21F, 0xD31F, 0x0000}, /* -2 */
562 {0xC208, 0xC308, 0x0001}, /* 0 (HW default) */
563 {0xC219, 0xC319, 0x0001}, /* +2 */
564 {0xC22A, 0xC32A, 0x0001}, /* +4 */
565 {0xC24C, 0xC34C, 0x0001}, /* +6 */
566 {0xC26E, 0xC36E, 0x0001}, /* +8 */
567 {0xC248, 0xC384, 0x0002}, /* +10 */
568 {0xC26A, 0xC36A, 0x0002}, /* +12 dB */
569};
570
571static unsigned short treble_parm[12][9] = {
572 {0x821E, 0xC26A, 0x031E, 0xC36A, 0x021E, 0xD208, 0x831E, 0xD308, 0x0001}, /* -12 dB */
573 {0x821E, 0xC25B, 0x031E, 0xC35B, 0x021E, 0xD208, 0x831E, 0xD308, 0x0001},
574 {0x821E, 0xC24C, 0x031E, 0xC34C, 0x021E, 0xD208, 0x831E, 0xD308, 0x0001},
575 {0x821E, 0xC23D, 0x031E, 0xC33D, 0x021E, 0xD208, 0x831E, 0xD308, 0x0001},
576 {0x821E, 0xC21F, 0x031E, 0xC31F, 0x021E, 0xD208, 0x831E, 0xD308, 0x0001},
577 {0x821E, 0xD208, 0x031E, 0xD308, 0x021E, 0xD208, 0x831E, 0xD308, 0x0002},
578 {0x821E, 0xD208, 0x031E, 0xD308, 0x021D, 0xD219, 0x831D, 0xD319, 0x0002},
579 {0x821E, 0xD208, 0x031E, 0xD308, 0x021C, 0xD22A, 0x831C, 0xD32A, 0x0002},
580 {0x821E, 0xD208, 0x031E, 0xD308, 0x021A, 0xD24C, 0x831A, 0xD34C, 0x0002},
581 {0x821E, 0xD208, 0x031E, 0xD308, 0x0219, 0xD26E, 0x8319, 0xD36E, 0x0002}, /* +8 (HW default) */
582 {0x821D, 0xD219, 0x031D, 0xD319, 0x0219, 0xD26E, 0x8319, 0xD36E, 0x0002},
583 {0x821C, 0xD22A, 0x031C, 0xD32A, 0x0219, 0xD26E, 0x8319, 0xD36E, 0x0002} /* +12 dB */
584};
585
586
587/*
588 * set Emu8000 digital equalizer; from 0 to 11 [-12dB - 12dB]
589 */
590/*exported*/ void
591snd_emu8000_update_equalizer(emu8000_t *emu)
592{
593 unsigned short w;
594 int bass = emu->bass_level;
595 int treble = emu->treble_level;
596
597 if (bass < 0 || bass > 11 || treble < 0 || treble > 11)
598 return;
599 EMU8000_INIT4_WRITE(emu, 0x01, bass_parm[bass][0]);
600 EMU8000_INIT4_WRITE(emu, 0x11, bass_parm[bass][1]);
601 EMU8000_INIT3_WRITE(emu, 0x11, treble_parm[treble][0]);
602 EMU8000_INIT3_WRITE(emu, 0x13, treble_parm[treble][1]);
603 EMU8000_INIT3_WRITE(emu, 0x1b, treble_parm[treble][2]);
604 EMU8000_INIT4_WRITE(emu, 0x07, treble_parm[treble][3]);
605 EMU8000_INIT4_WRITE(emu, 0x0b, treble_parm[treble][4]);
606 EMU8000_INIT4_WRITE(emu, 0x0d, treble_parm[treble][5]);
607 EMU8000_INIT4_WRITE(emu, 0x17, treble_parm[treble][6]);
608 EMU8000_INIT4_WRITE(emu, 0x19, treble_parm[treble][7]);
609 w = bass_parm[bass][2] + treble_parm[treble][8];
610 EMU8000_INIT4_WRITE(emu, 0x15, (unsigned short)(w + 0x0262));
611 EMU8000_INIT4_WRITE(emu, 0x1d, (unsigned short)(w + 0x8362));
612}
613
614
615/*----------------------------------------------------------------
616 * Chorus mode control
617 *----------------------------------------------------------------*/
618
619/*
620 * chorus mode parameters
621 */
622#define SNDRV_EMU8000_CHORUS_1 0
623#define SNDRV_EMU8000_CHORUS_2 1
624#define SNDRV_EMU8000_CHORUS_3 2
625#define SNDRV_EMU8000_CHORUS_4 3
626#define SNDRV_EMU8000_CHORUS_FEEDBACK 4
627#define SNDRV_EMU8000_CHORUS_FLANGER 5
628#define SNDRV_EMU8000_CHORUS_SHORTDELAY 6
629#define SNDRV_EMU8000_CHORUS_SHORTDELAY2 7
630#define SNDRV_EMU8000_CHORUS_PREDEFINED 8
631/* user can define chorus modes up to 32 */
632#define SNDRV_EMU8000_CHORUS_NUMBERS 32
633
634typedef struct soundfont_chorus_fx_t {
635 unsigned short feedback; /* feedback level (0xE600-0xE6FF) */
636 unsigned short delay_offset; /* delay (0-0x0DA3) [1/44100 sec] */
637 unsigned short lfo_depth; /* LFO depth (0xBC00-0xBCFF) */
638 unsigned int delay; /* right delay (0-0xFFFFFFFF) [1/256/44100 sec] */
639 unsigned int lfo_freq; /* LFO freq LFO freq (0-0xFFFFFFFF) */
640} soundfont_chorus_fx_t;
641
642/* 5 parameters for each chorus mode; 3 x 16bit, 2 x 32bit */
643static char chorus_defined[SNDRV_EMU8000_CHORUS_NUMBERS];
644static soundfont_chorus_fx_t chorus_parm[SNDRV_EMU8000_CHORUS_NUMBERS] = {
645 {0xE600, 0x03F6, 0xBC2C ,0x00000000, 0x0000006D}, /* chorus 1 */
646 {0xE608, 0x031A, 0xBC6E, 0x00000000, 0x0000017C}, /* chorus 2 */
647 {0xE610, 0x031A, 0xBC84, 0x00000000, 0x00000083}, /* chorus 3 */
648 {0xE620, 0x0269, 0xBC6E, 0x00000000, 0x0000017C}, /* chorus 4 */
649 {0xE680, 0x04D3, 0xBCA6, 0x00000000, 0x0000005B}, /* feedback */
650 {0xE6E0, 0x044E, 0xBC37, 0x00000000, 0x00000026}, /* flanger */
651 {0xE600, 0x0B06, 0xBC00, 0x0006E000, 0x00000083}, /* short delay */
652 {0xE6C0, 0x0B06, 0xBC00, 0x0006E000, 0x00000083}, /* short delay + feedback */
653};
654
655/*exported*/ int
656snd_emu8000_load_chorus_fx(emu8000_t *emu, int mode, const void __user *buf, long len)
657{
658 soundfont_chorus_fx_t rec;
659 if (mode < SNDRV_EMU8000_CHORUS_PREDEFINED || mode >= SNDRV_EMU8000_CHORUS_NUMBERS) {
660 snd_printk(KERN_WARNING "invalid chorus mode %d for uploading\n", mode);
661 return -EINVAL;
662 }
663 if (len < (long)sizeof(rec) || copy_from_user(&rec, buf, sizeof(rec)))
664 return -EFAULT;
665 chorus_parm[mode] = rec;
666 chorus_defined[mode] = 1;
667 return 0;
668}
669
670/*exported*/ void
671snd_emu8000_update_chorus_mode(emu8000_t *emu)
672{
673 int effect = emu->chorus_mode;
674 if (effect < 0 || effect >= SNDRV_EMU8000_CHORUS_NUMBERS ||
675 (effect >= SNDRV_EMU8000_CHORUS_PREDEFINED && !chorus_defined[effect]))
676 return;
677 EMU8000_INIT3_WRITE(emu, 0x09, chorus_parm[effect].feedback);
678 EMU8000_INIT3_WRITE(emu, 0x0c, chorus_parm[effect].delay_offset);
679 EMU8000_INIT4_WRITE(emu, 0x03, chorus_parm[effect].lfo_depth);
680 EMU8000_HWCF4_WRITE(emu, chorus_parm[effect].delay);
681 EMU8000_HWCF5_WRITE(emu, chorus_parm[effect].lfo_freq);
682 EMU8000_HWCF6_WRITE(emu, 0x8000);
683 EMU8000_HWCF7_WRITE(emu, 0x0000);
684}
685
686/*----------------------------------------------------------------
687 * Reverb mode control
688 *----------------------------------------------------------------*/
689
690/*
691 * reverb mode parameters
692 */
693#define SNDRV_EMU8000_REVERB_ROOM1 0
694#define SNDRV_EMU8000_REVERB_ROOM2 1
695#define SNDRV_EMU8000_REVERB_ROOM3 2
696#define SNDRV_EMU8000_REVERB_HALL1 3
697#define SNDRV_EMU8000_REVERB_HALL2 4
698#define SNDRV_EMU8000_REVERB_PLATE 5
699#define SNDRV_EMU8000_REVERB_DELAY 6
700#define SNDRV_EMU8000_REVERB_PANNINGDELAY 7
701#define SNDRV_EMU8000_REVERB_PREDEFINED 8
702/* user can define reverb modes up to 32 */
703#define SNDRV_EMU8000_REVERB_NUMBERS 32
704
705typedef struct soundfont_reverb_fx_t {
706 unsigned short parms[28];
707} soundfont_reverb_fx_t;
708
709/* reverb mode settings; write the following 28 data of 16 bit length
710 * on the corresponding ports in the reverb_cmds array
711 */
712static char reverb_defined[SNDRV_EMU8000_CHORUS_NUMBERS];
713static soundfont_reverb_fx_t reverb_parm[SNDRV_EMU8000_REVERB_NUMBERS] = {
714{{ /* room 1 */
715 0xB488, 0xA450, 0x9550, 0x84B5, 0x383A, 0x3EB5, 0x72F4,
716 0x72A4, 0x7254, 0x7204, 0x7204, 0x7204, 0x4416, 0x4516,
717 0xA490, 0xA590, 0x842A, 0x852A, 0x842A, 0x852A, 0x8429,
718 0x8529, 0x8429, 0x8529, 0x8428, 0x8528, 0x8428, 0x8528,
719}},
720{{ /* room 2 */
721 0xB488, 0xA458, 0x9558, 0x84B5, 0x383A, 0x3EB5, 0x7284,
722 0x7254, 0x7224, 0x7224, 0x7254, 0x7284, 0x4448, 0x4548,
723 0xA440, 0xA540, 0x842A, 0x852A, 0x842A, 0x852A, 0x8429,
724 0x8529, 0x8429, 0x8529, 0x8428, 0x8528, 0x8428, 0x8528,
725}},
726{{ /* room 3 */
727 0xB488, 0xA460, 0x9560, 0x84B5, 0x383A, 0x3EB5, 0x7284,
728 0x7254, 0x7224, 0x7224, 0x7254, 0x7284, 0x4416, 0x4516,
729 0xA490, 0xA590, 0x842C, 0x852C, 0x842C, 0x852C, 0x842B,
730 0x852B, 0x842B, 0x852B, 0x842A, 0x852A, 0x842A, 0x852A,
731}},
732{{ /* hall 1 */
733 0xB488, 0xA470, 0x9570, 0x84B5, 0x383A, 0x3EB5, 0x7284,
734 0x7254, 0x7224, 0x7224, 0x7254, 0x7284, 0x4448, 0x4548,
735 0xA440, 0xA540, 0x842B, 0x852B, 0x842B, 0x852B, 0x842A,
736 0x852A, 0x842A, 0x852A, 0x8429, 0x8529, 0x8429, 0x8529,
737}},
738{{ /* hall 2 */
739 0xB488, 0xA470, 0x9570, 0x84B5, 0x383A, 0x3EB5, 0x7254,
740 0x7234, 0x7224, 0x7254, 0x7264, 0x7294, 0x44C3, 0x45C3,
741 0xA404, 0xA504, 0x842A, 0x852A, 0x842A, 0x852A, 0x8429,
742 0x8529, 0x8429, 0x8529, 0x8428, 0x8528, 0x8428, 0x8528,
743}},
744{{ /* plate */
745 0xB4FF, 0xA470, 0x9570, 0x84B5, 0x383A, 0x3EB5, 0x7234,
746 0x7234, 0x7234, 0x7234, 0x7234, 0x7234, 0x4448, 0x4548,
747 0xA440, 0xA540, 0x842A, 0x852A, 0x842A, 0x852A, 0x8429,
748 0x8529, 0x8429, 0x8529, 0x8428, 0x8528, 0x8428, 0x8528,
749}},
750{{ /* delay */
751 0xB4FF, 0xA470, 0x9500, 0x84B5, 0x333A, 0x39B5, 0x7204,
752 0x7204, 0x7204, 0x7204, 0x7204, 0x72F4, 0x4400, 0x4500,
753 0xA4FF, 0xA5FF, 0x8420, 0x8520, 0x8420, 0x8520, 0x8420,
754 0x8520, 0x8420, 0x8520, 0x8420, 0x8520, 0x8420, 0x8520,
755}},
756{{ /* panning delay */
757 0xB4FF, 0xA490, 0x9590, 0x8474, 0x333A, 0x39B5, 0x7204,
758 0x7204, 0x7204, 0x7204, 0x7204, 0x72F4, 0x4400, 0x4500,
759 0xA4FF, 0xA5FF, 0x8420, 0x8520, 0x8420, 0x8520, 0x8420,
760 0x8520, 0x8420, 0x8520, 0x8420, 0x8520, 0x8420, 0x8520,
761}},
762};
763
764enum { DATA1, DATA2 };
765#define AWE_INIT1(c) EMU8000_CMD(2,c), DATA1
766#define AWE_INIT2(c) EMU8000_CMD(2,c), DATA2
767#define AWE_INIT3(c) EMU8000_CMD(3,c), DATA1
768#define AWE_INIT4(c) EMU8000_CMD(3,c), DATA2
769
770static struct reverb_cmd_pair {
771 unsigned short cmd, port;
772} reverb_cmds[28] = {
773 {AWE_INIT1(0x03)}, {AWE_INIT1(0x05)}, {AWE_INIT4(0x1F)}, {AWE_INIT1(0x07)},
774 {AWE_INIT2(0x14)}, {AWE_INIT2(0x16)}, {AWE_INIT1(0x0F)}, {AWE_INIT1(0x17)},
775 {AWE_INIT1(0x1F)}, {AWE_INIT2(0x07)}, {AWE_INIT2(0x0F)}, {AWE_INIT2(0x17)},
776 {AWE_INIT2(0x1D)}, {AWE_INIT2(0x1F)}, {AWE_INIT3(0x01)}, {AWE_INIT3(0x03)},
777 {AWE_INIT1(0x09)}, {AWE_INIT1(0x0B)}, {AWE_INIT1(0x11)}, {AWE_INIT1(0x13)},
778 {AWE_INIT1(0x19)}, {AWE_INIT1(0x1B)}, {AWE_INIT2(0x01)}, {AWE_INIT2(0x03)},
779 {AWE_INIT2(0x09)}, {AWE_INIT2(0x0B)}, {AWE_INIT2(0x11)}, {AWE_INIT2(0x13)},
780};
781
782/*exported*/ int
783snd_emu8000_load_reverb_fx(emu8000_t *emu, int mode, const void __user *buf, long len)
784{
785 soundfont_reverb_fx_t rec;
786
787 if (mode < SNDRV_EMU8000_REVERB_PREDEFINED || mode >= SNDRV_EMU8000_REVERB_NUMBERS) {
788 snd_printk(KERN_WARNING "invalid reverb mode %d for uploading\n", mode);
789 return -EINVAL;
790 }
791 if (len < (long)sizeof(rec) || copy_from_user(&rec, buf, sizeof(rec)))
792 return -EFAULT;
793 reverb_parm[mode] = rec;
794 reverb_defined[mode] = 1;
795 return 0;
796}
797
798/*exported*/ void
799snd_emu8000_update_reverb_mode(emu8000_t *emu)
800{
801 int effect = emu->reverb_mode;
802 int i;
803
804 if (effect < 0 || effect >= SNDRV_EMU8000_REVERB_NUMBERS ||
805 (effect >= SNDRV_EMU8000_REVERB_PREDEFINED && !reverb_defined[effect]))
806 return;
807 for (i = 0; i < 28; i++) {
808 int port;
809 if (reverb_cmds[i].port == DATA1)
810 port = EMU8000_DATA1(emu);
811 else
812 port = EMU8000_DATA2(emu);
813 snd_emu8000_poke(emu, port, reverb_cmds[i].cmd, reverb_parm[effect].parms[i]);
814 }
815}
816
817
818/*----------------------------------------------------------------
819 * mixer interface
820 *----------------------------------------------------------------*/
821
822/*
823 * bass/treble
824 */
825static int mixer_bass_treble_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
826{
827 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
828 uinfo->count = 1;
829 uinfo->value.integer.min = 0;
830 uinfo->value.integer.max = 11;
831 return 0;
832}
833
834static int mixer_bass_treble_get(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
835{
836 emu8000_t *emu = snd_kcontrol_chip(kcontrol);
837
838 ucontrol->value.integer.value[0] = kcontrol->private_value ? emu->treble_level : emu->bass_level;
839 return 0;
840}
841
842static int mixer_bass_treble_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
843{
844 emu8000_t *emu = snd_kcontrol_chip(kcontrol);
845 unsigned long flags;
846 int change;
847 unsigned short val1;
848
849 val1 = ucontrol->value.integer.value[0] % 12;
850 spin_lock_irqsave(&emu->control_lock, flags);
851 if (kcontrol->private_value) {
852 change = val1 != emu->treble_level;
853 emu->treble_level = val1;
854 } else {
855 change = val1 != emu->bass_level;
856 emu->bass_level = val1;
857 }
858 spin_unlock_irqrestore(&emu->control_lock, flags);
859 snd_emu8000_update_equalizer(emu);
860 return change;
861}
862
863static snd_kcontrol_new_t mixer_bass_control =
864{
865 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
866 .name = "Synth Tone Control - Bass",
867 .info = mixer_bass_treble_info,
868 .get = mixer_bass_treble_get,
869 .put = mixer_bass_treble_put,
870 .private_value = 0,
871};
872
873static snd_kcontrol_new_t mixer_treble_control =
874{
875 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
876 .name = "Synth Tone Control - Treble",
877 .info = mixer_bass_treble_info,
878 .get = mixer_bass_treble_get,
879 .put = mixer_bass_treble_put,
880 .private_value = 1,
881};
882
883/*
884 * chorus/reverb mode
885 */
886static int mixer_chorus_reverb_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
887{
888 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
889 uinfo->count = 1;
890 uinfo->value.integer.min = 0;
891 uinfo->value.integer.max = kcontrol->private_value ? (SNDRV_EMU8000_CHORUS_NUMBERS-1) : (SNDRV_EMU8000_REVERB_NUMBERS-1);
892 return 0;
893}
894
895static int mixer_chorus_reverb_get(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
896{
897 emu8000_t *emu = snd_kcontrol_chip(kcontrol);
898
899 ucontrol->value.integer.value[0] = kcontrol->private_value ? emu->chorus_mode : emu->reverb_mode;
900 return 0;
901}
902
903static int mixer_chorus_reverb_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
904{
905 emu8000_t *emu = snd_kcontrol_chip(kcontrol);
906 unsigned long flags;
907 int change;
908 unsigned short val1;
909
910 spin_lock_irqsave(&emu->control_lock, flags);
911 if (kcontrol->private_value) {
912 val1 = ucontrol->value.integer.value[0] % SNDRV_EMU8000_CHORUS_NUMBERS;
913 change = val1 != emu->chorus_mode;
914 emu->chorus_mode = val1;
915 } else {
916 val1 = ucontrol->value.integer.value[0] % SNDRV_EMU8000_REVERB_NUMBERS;
917 change = val1 != emu->reverb_mode;
918 emu->reverb_mode = val1;
919 }
920 spin_unlock_irqrestore(&emu->control_lock, flags);
921 if (change) {
922 if (kcontrol->private_value)
923 snd_emu8000_update_chorus_mode(emu);
924 else
925 snd_emu8000_update_reverb_mode(emu);
926 }
927 return change;
928}
929
930static snd_kcontrol_new_t mixer_chorus_mode_control =
931{
932 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
933 .name = "Chorus Mode",
934 .info = mixer_chorus_reverb_info,
935 .get = mixer_chorus_reverb_get,
936 .put = mixer_chorus_reverb_put,
937 .private_value = 1,
938};
939
940static snd_kcontrol_new_t mixer_reverb_mode_control =
941{
942 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
943 .name = "Reverb Mode",
944 .info = mixer_chorus_reverb_info,
945 .get = mixer_chorus_reverb_get,
946 .put = mixer_chorus_reverb_put,
947 .private_value = 0,
948};
949
950/*
951 * FM OPL3 chorus/reverb depth
952 */
953static int mixer_fm_depth_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
954{
955 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
956 uinfo->count = 1;
957 uinfo->value.integer.min = 0;
958 uinfo->value.integer.max = 255;
959 return 0;
960}
961
962static int mixer_fm_depth_get(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
963{
964 emu8000_t *emu = snd_kcontrol_chip(kcontrol);
965
966 ucontrol->value.integer.value[0] = kcontrol->private_value ? emu->fm_chorus_depth : emu->fm_reverb_depth;
967 return 0;
968}
969
970static int mixer_fm_depth_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
971{
972 emu8000_t *emu = snd_kcontrol_chip(kcontrol);
973 unsigned long flags;
974 int change;
975 unsigned short val1;
976
977 val1 = ucontrol->value.integer.value[0] % 256;
978 spin_lock_irqsave(&emu->control_lock, flags);
979 if (kcontrol->private_value) {
980 change = val1 != emu->fm_chorus_depth;
981 emu->fm_chorus_depth = val1;
982 } else {
983 change = val1 != emu->fm_reverb_depth;
984 emu->fm_reverb_depth = val1;
985 }
986 spin_unlock_irqrestore(&emu->control_lock, flags);
987 if (change)
988 snd_emu8000_init_fm(emu);
989 return change;
990}
991
992static snd_kcontrol_new_t mixer_fm_chorus_depth_control =
993{
994 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
995 .name = "FM Chorus Depth",
996 .info = mixer_fm_depth_info,
997 .get = mixer_fm_depth_get,
998 .put = mixer_fm_depth_put,
999 .private_value = 1,
1000};
1001
1002static snd_kcontrol_new_t mixer_fm_reverb_depth_control =
1003{
1004 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1005 .name = "FM Reverb Depth",
1006 .info = mixer_fm_depth_info,
1007 .get = mixer_fm_depth_get,
1008 .put = mixer_fm_depth_put,
1009 .private_value = 0,
1010};
1011
1012
1013static snd_kcontrol_new_t *mixer_defs[EMU8000_NUM_CONTROLS] = {
1014 &mixer_bass_control,
1015 &mixer_treble_control,
1016 &mixer_chorus_mode_control,
1017 &mixer_reverb_mode_control,
1018 &mixer_fm_chorus_depth_control,
1019 &mixer_fm_reverb_depth_control,
1020};
1021
1022/*
1023 * create and attach mixer elements for WaveTable treble/bass controls
1024 */
1025static int __init
1026snd_emu8000_create_mixer(snd_card_t *card, emu8000_t *emu)
1027{
1028 int i, err = 0;
1029
1030 snd_assert(emu != NULL && card != NULL, return -EINVAL);
1031
1032 spin_lock_init(&emu->control_lock);
1033
1034 memset(emu->controls, 0, sizeof(emu->controls));
1035 for (i = 0; i < EMU8000_NUM_CONTROLS; i++) {
1036 if ((err = snd_ctl_add(card, emu->controls[i] = snd_ctl_new1(mixer_defs[i], emu))) < 0)
1037 goto __error;
1038 }
1039 return 0;
1040
1041__error:
1042 for (i = 0; i < EMU8000_NUM_CONTROLS; i++) {
1043 down_write(&card->controls_rwsem);
1044 if (emu->controls[i])
1045 snd_ctl_remove(card, emu->controls[i]);
1046 up_write(&card->controls_rwsem);
1047 }
1048 return err;
1049}
1050
1051
1052/*
1053 * free resources
1054 */
1055static int snd_emu8000_free(emu8000_t *hw)
1056{
1057 if (hw->res_port1) {
1058 release_resource(hw->res_port1);
1059 kfree_nocheck(hw->res_port1);
1060 }
1061 if (hw->res_port2) {
1062 release_resource(hw->res_port2);
1063 kfree_nocheck(hw->res_port2);
1064 }
1065 if (hw->res_port3) {
1066 release_resource(hw->res_port3);
1067 kfree_nocheck(hw->res_port3);
1068 }
1069 kfree(hw);
1070 return 0;
1071}
1072
1073/*
1074 */
1075static int snd_emu8000_dev_free(snd_device_t *device)
1076{
1077 emu8000_t *hw = device->device_data;
1078 return snd_emu8000_free(hw);
1079}
1080
1081/*
1082 * initialize and register emu8000 synth device.
1083 */
1084int __init
1085snd_emu8000_new(snd_card_t *card, int index, long port, int seq_ports, snd_seq_device_t **awe_ret)
1086{
1087 snd_seq_device_t *awe;
1088 emu8000_t *hw;
1089 int err;
1090 static snd_device_ops_t ops = {
1091 .dev_free = snd_emu8000_dev_free,
1092 };
1093
1094 if (awe_ret)
1095 *awe_ret = NULL;
1096
1097 if (seq_ports <= 0)
1098 return 0;
1099
1100 hw = kcalloc(1, sizeof(*hw), GFP_KERNEL);
1101 if (hw == NULL)
1102 return -ENOMEM;
1103 spin_lock_init(&hw->reg_lock);
1104 hw->index = index;
1105 hw->port1 = port;
1106 hw->port2 = port + 0x400;
1107 hw->port3 = port + 0x800;
1108 if (!(hw->res_port1 = request_region(hw->port1, 4, "Emu8000-1")) ||
1109 !(hw->res_port2 = request_region(hw->port2, 4, "Emu8000-2")) ||
1110 !(hw->res_port3 = request_region(hw->port3, 4, "Emu8000-3"))) {
1111 snd_printk(KERN_ERR "sbawe: can't grab ports 0x%lx, 0x%lx, 0x%lx\n", hw->port1, hw->port2, hw->port3);
1112 snd_emu8000_free(hw);
1113 return -EBUSY;
1114 }
1115 hw->mem_size = 0;
1116 hw->card = card;
1117 hw->seq_ports = seq_ports;
1118 hw->bass_level = 5;
1119 hw->treble_level = 9;
1120 hw->chorus_mode = 2;
1121 hw->reverb_mode = 4;
1122 hw->fm_chorus_depth = 0;
1123 hw->fm_reverb_depth = 0;
1124
1125 if (snd_emu8000_detect(hw) < 0) {
1126 snd_emu8000_free(hw);
1127 return -ENODEV;
1128 }
1129
1130 snd_emu8000_init_hw(hw);
1131 if ((err = snd_emu8000_create_mixer(card, hw)) < 0) {
1132 snd_emu8000_free(hw);
1133 return err;
1134 }
1135
1136 if ((err = snd_device_new(card, SNDRV_DEV_CODEC, hw, &ops)) < 0) {
1137 snd_emu8000_free(hw);
1138 return err;
1139 }
1140#if defined(CONFIG_SND_SEQUENCER) || (defined(MODULE) && defined(CONFIG_SND_SEQUENCER_MODULE))
1141 if (snd_seq_device_new(card, index, SNDRV_SEQ_DEV_ID_EMU8000,
1142 sizeof(emu8000_t*), &awe) >= 0) {
1143 strcpy(awe->name, "EMU-8000");
1144 *(emu8000_t**)SNDRV_SEQ_DEVICE_ARGPTR(awe) = hw;
1145 }
1146#else
1147 awe = NULL;
1148#endif
1149 if (awe_ret)
1150 *awe_ret = awe;
1151
1152 return 0;
1153}
1154
1155
1156/*
1157 * exported stuff
1158 */
1159
1160EXPORT_SYMBOL(snd_emu8000_poke);
1161EXPORT_SYMBOL(snd_emu8000_peek);
1162EXPORT_SYMBOL(snd_emu8000_poke_dw);
1163EXPORT_SYMBOL(snd_emu8000_peek_dw);
1164EXPORT_SYMBOL(snd_emu8000_dma_chan);
1165EXPORT_SYMBOL(snd_emu8000_init_fm);
1166EXPORT_SYMBOL(snd_emu8000_load_chorus_fx);
1167EXPORT_SYMBOL(snd_emu8000_load_reverb_fx);
1168EXPORT_SYMBOL(snd_emu8000_update_chorus_mode);
1169EXPORT_SYMBOL(snd_emu8000_update_reverb_mode);
1170EXPORT_SYMBOL(snd_emu8000_update_equalizer);
diff --git a/sound/isa/sb/emu8000_callback.c b/sound/isa/sb/emu8000_callback.c
new file mode 100644
index 000000000000..1cc4101a17a4
--- /dev/null
+++ b/sound/isa/sb/emu8000_callback.c
@@ -0,0 +1,543 @@
1/*
2 * synth callback routines for the emu8000 (AWE32/64)
3 *
4 * Copyright (C) 1999 Steve Ratcliffe
5 * Copyright (C) 1999-2000 Takashi Iwai <tiwai@suse.de>
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 */
21
22#include "emu8000_local.h"
23#include <sound/asoundef.h>
24
25/*
26 * prototypes
27 */
28static snd_emux_voice_t *get_voice(snd_emux_t *emu, snd_emux_port_t *port);
29static int start_voice(snd_emux_voice_t *vp);
30static void trigger_voice(snd_emux_voice_t *vp);
31static void release_voice(snd_emux_voice_t *vp);
32static void update_voice(snd_emux_voice_t *vp, int update);
33static void reset_voice(snd_emux_t *emu, int ch);
34static void terminate_voice(snd_emux_voice_t *vp);
35static void sysex(snd_emux_t *emu, char *buf, int len, int parsed, snd_midi_channel_set_t *chset);
36#ifdef CONFIG_SND_SEQUENCER_OSS
37static int oss_ioctl(snd_emux_t *emu, int cmd, int p1, int p2);
38#endif
39static int load_fx(snd_emux_t *emu, int type, int mode, const void __user *buf, long len);
40
41static void set_pitch(emu8000_t *hw, snd_emux_voice_t *vp);
42static void set_volume(emu8000_t *hw, snd_emux_voice_t *vp);
43static void set_pan(emu8000_t *hw, snd_emux_voice_t *vp);
44static void set_fmmod(emu8000_t *hw, snd_emux_voice_t *vp);
45static void set_tremfreq(emu8000_t *hw, snd_emux_voice_t *vp);
46static void set_fm2frq2(emu8000_t *hw, snd_emux_voice_t *vp);
47static void set_filterQ(emu8000_t *hw, snd_emux_voice_t *vp);
48static void snd_emu8000_tweak_voice(emu8000_t *emu, int ch);
49
50/*
51 * Ensure a value is between two points
52 * macro evaluates its args more than once, so changed to upper-case.
53 */
54#define LIMITVALUE(x, a, b) do { if ((x) < (a)) (x) = (a); else if ((x) > (b)) (x) = (b); } while (0)
55#define LIMITMAX(x, a) do {if ((x) > (a)) (x) = (a); } while (0)
56
57
58/*
59 * set up operators
60 */
61static snd_emux_operators_t emu8000_ops = {
62 .owner = THIS_MODULE,
63 .get_voice = get_voice,
64 .prepare = start_voice,
65 .trigger = trigger_voice,
66 .release = release_voice,
67 .update = update_voice,
68 .terminate = terminate_voice,
69 .reset = reset_voice,
70 .sample_new = snd_emu8000_sample_new,
71 .sample_free = snd_emu8000_sample_free,
72 .sample_reset = snd_emu8000_sample_reset,
73 .load_fx = load_fx,
74 .sysex = sysex,
75#ifdef CONFIG_SND_SEQUENCER_OSS
76 .oss_ioctl = oss_ioctl,
77#endif
78};
79
80void
81snd_emu8000_ops_setup(emu8000_t *hw)
82{
83 hw->emu->ops = emu8000_ops;
84}
85
86
87
88/*
89 * Terminate a voice
90 */
91static void
92release_voice(snd_emux_voice_t *vp)
93{
94 int dcysusv;
95 emu8000_t *hw;
96
97 hw = vp->hw;
98 dcysusv = 0x8000 | (unsigned char)vp->reg.parm.modrelease;
99 EMU8000_DCYSUS_WRITE(hw, vp->ch, dcysusv);
100 dcysusv = 0x8000 | (unsigned char)vp->reg.parm.volrelease;
101 EMU8000_DCYSUSV_WRITE(hw, vp->ch, dcysusv);
102}
103
104
105/*
106 */
107static void
108terminate_voice(snd_emux_voice_t *vp)
109{
110 emu8000_t *hw;
111
112 hw = vp->hw;
113 EMU8000_DCYSUSV_WRITE(hw, vp->ch, 0x807F);
114}
115
116
117/*
118 */
119static void
120update_voice(snd_emux_voice_t *vp, int update)
121{
122 emu8000_t *hw;
123
124 hw = vp->hw;
125 if (update & SNDRV_EMUX_UPDATE_VOLUME)
126 set_volume(hw, vp);
127 if (update & SNDRV_EMUX_UPDATE_PITCH)
128 set_pitch(hw, vp);
129 if ((update & SNDRV_EMUX_UPDATE_PAN) &&
130 vp->port->ctrls[EMUX_MD_REALTIME_PAN])
131 set_pan(hw, vp);
132 if (update & SNDRV_EMUX_UPDATE_FMMOD)
133 set_fmmod(hw, vp);
134 if (update & SNDRV_EMUX_UPDATE_TREMFREQ)
135 set_tremfreq(hw, vp);
136 if (update & SNDRV_EMUX_UPDATE_FM2FRQ2)
137 set_fm2frq2(hw, vp);
138 if (update & SNDRV_EMUX_UPDATE_Q)
139 set_filterQ(hw, vp);
140}
141
142
143/*
144 * Find a channel (voice) within the EMU that is not in use or at least
145 * less in use than other channels. Always returns a valid pointer
146 * no matter what. If there is a real shortage of voices then one
147 * will be cut. Such is life.
148 *
149 * The channel index (vp->ch) must be initialized in this routine.
150 * In Emu8k, it is identical with the array index.
151 */
152static snd_emux_voice_t *
153get_voice(snd_emux_t *emu, snd_emux_port_t *port)
154{
155 int i;
156 snd_emux_voice_t *vp;
157 emu8000_t *hw;
158
159 /* what we are looking for, in order of preference */
160 enum {
161 OFF=0, RELEASED, PLAYING, END
162 };
163
164 /* Keeps track of what we are finding */
165 struct best {
166 unsigned int time;
167 int voice;
168 } best[END];
169 struct best *bp;
170
171 hw = emu->hw;
172
173 for (i = 0; i < END; i++) {
174 best[i].time = (unsigned int)(-1); /* XXX MAX_?INT really */;
175 best[i].voice = -1;
176 }
177
178 /*
179 * Go through them all and get a best one to use.
180 */
181 for (i = 0; i < emu->max_voices; i++) {
182 int state, val;
183
184 vp = &emu->voices[i];
185 state = vp->state;
186
187 if (state == SNDRV_EMUX_ST_OFF)
188 bp = best + OFF;
189 else if (state == SNDRV_EMUX_ST_RELEASED ||
190 state == SNDRV_EMUX_ST_PENDING) {
191 bp = best + RELEASED;
192 val = (EMU8000_CVCF_READ(hw, vp->ch) >> 16) & 0xffff;
193 if (! val)
194 bp = best + OFF;
195 }
196 else if (state & SNDRV_EMUX_ST_ON)
197 bp = best + PLAYING;
198 else
199 continue;
200
201 /* check if sample is finished playing (non-looping only) */
202 if (state != SNDRV_EMUX_ST_OFF &&
203 (vp->reg.sample_mode & SNDRV_SFNT_SAMPLE_SINGLESHOT)) {
204 val = EMU8000_CCCA_READ(hw, vp->ch) & 0xffffff;
205 if (val >= vp->reg.loopstart)
206 bp = best + OFF;
207 }
208
209 if (vp->time < bp->time) {
210 bp->time = vp->time;
211 bp->voice = i;
212 }
213 }
214
215 for (i = 0; i < END; i++) {
216 if (best[i].voice >= 0) {
217 vp = &emu->voices[best[i].voice];
218 vp->ch = best[i].voice;
219 return vp;
220 }
221 }
222
223 /* not found */
224 return NULL;
225}
226
227/*
228 */
229static int
230start_voice(snd_emux_voice_t *vp)
231{
232 unsigned int temp;
233 int ch;
234 int addr;
235 snd_midi_channel_t *chan;
236 emu8000_t *hw;
237
238 hw = vp->hw;
239 ch = vp->ch;
240 chan = vp->chan;
241
242 /* channel to be silent and idle */
243 EMU8000_DCYSUSV_WRITE(hw, ch, 0x0080);
244 EMU8000_VTFT_WRITE(hw, ch, 0x0000FFFF);
245 EMU8000_CVCF_WRITE(hw, ch, 0x0000FFFF);
246 EMU8000_PTRX_WRITE(hw, ch, 0);
247 EMU8000_CPF_WRITE(hw, ch, 0);
248
249 /* set pitch offset */
250 set_pitch(hw, vp);
251
252 /* set envelope parameters */
253 EMU8000_ENVVAL_WRITE(hw, ch, vp->reg.parm.moddelay);
254 EMU8000_ATKHLD_WRITE(hw, ch, vp->reg.parm.modatkhld);
255 EMU8000_DCYSUS_WRITE(hw, ch, vp->reg.parm.moddcysus);
256 EMU8000_ENVVOL_WRITE(hw, ch, vp->reg.parm.voldelay);
257 EMU8000_ATKHLDV_WRITE(hw, ch, vp->reg.parm.volatkhld);
258 /* decay/sustain parameter for volume envelope is used
259 for triggerg the voice */
260
261 /* cutoff and volume */
262 set_volume(hw, vp);
263
264 /* modulation envelope heights */
265 EMU8000_PEFE_WRITE(hw, ch, vp->reg.parm.pefe);
266
267 /* lfo1/2 delay */
268 EMU8000_LFO1VAL_WRITE(hw, ch, vp->reg.parm.lfo1delay);
269 EMU8000_LFO2VAL_WRITE(hw, ch, vp->reg.parm.lfo2delay);
270
271 /* lfo1 pitch & cutoff shift */
272 set_fmmod(hw, vp);
273 /* lfo1 volume & freq */
274 set_tremfreq(hw, vp);
275 /* lfo2 pitch & freq */
276 set_fm2frq2(hw, vp);
277 /* pan & loop start */
278 set_pan(hw, vp);
279
280 /* chorus & loop end (chorus 8bit, MSB) */
281 addr = vp->reg.loopend - 1;
282 temp = vp->reg.parm.chorus;
283 temp += (int)chan->control[MIDI_CTL_E3_CHORUS_DEPTH] * 9 / 10;
284 LIMITMAX(temp, 255);
285 temp = (temp <<24) | (unsigned int)addr;
286 EMU8000_CSL_WRITE(hw, ch, temp);
287
288 /* Q & current address (Q 4bit value, MSB) */
289 addr = vp->reg.start - 1;
290 temp = vp->reg.parm.filterQ;
291 temp = (temp<<28) | (unsigned int)addr;
292 EMU8000_CCCA_WRITE(hw, ch, temp);
293
294 /* clear unknown registers */
295 EMU8000_00A0_WRITE(hw, ch, 0);
296 EMU8000_0080_WRITE(hw, ch, 0);
297
298 /* reset volume */
299 temp = vp->vtarget << 16;
300 EMU8000_VTFT_WRITE(hw, ch, temp | vp->ftarget);
301 EMU8000_CVCF_WRITE(hw, ch, temp | 0xff00);
302
303 return 0;
304}
305
306/*
307 * Start envelope
308 */
309static void
310trigger_voice(snd_emux_voice_t *vp)
311{
312 int ch = vp->ch;
313 unsigned int temp;
314 emu8000_t *hw;
315
316 hw = vp->hw;
317
318 /* set reverb and pitch target */
319 temp = vp->reg.parm.reverb;
320 temp += (int)vp->chan->control[MIDI_CTL_E1_REVERB_DEPTH] * 9 / 10;
321 LIMITMAX(temp, 255);
322 temp = (temp << 8) | (vp->ptarget << 16) | vp->aaux;
323 EMU8000_PTRX_WRITE(hw, ch, temp);
324 EMU8000_CPF_WRITE(hw, ch, vp->ptarget << 16);
325 EMU8000_DCYSUSV_WRITE(hw, ch, vp->reg.parm.voldcysus);
326}
327
328/*
329 * reset voice parameters
330 */
331static void
332reset_voice(snd_emux_t *emu, int ch)
333{
334 emu8000_t *hw;
335
336 hw = emu->hw;
337 EMU8000_DCYSUSV_WRITE(hw, ch, 0x807F);
338 snd_emu8000_tweak_voice(hw, ch);
339}
340
341/*
342 * Set the pitch of a possibly playing note.
343 */
344static void
345set_pitch(emu8000_t *hw, snd_emux_voice_t *vp)
346{
347 EMU8000_IP_WRITE(hw, vp->ch, vp->apitch);
348}
349
350/*
351 * Set the volume of a possibly already playing note
352 */
353static void
354set_volume(emu8000_t *hw, snd_emux_voice_t *vp)
355{
356 int ifatn;
357
358 ifatn = (unsigned char)vp->acutoff;
359 ifatn = (ifatn << 8);
360 ifatn |= (unsigned char)vp->avol;
361 EMU8000_IFATN_WRITE(hw, vp->ch, ifatn);
362}
363
364/*
365 * Set pan and loop start address.
366 */
367static void
368set_pan(emu8000_t *hw, snd_emux_voice_t *vp)
369{
370 unsigned int temp;
371
372 temp = ((unsigned int)vp->apan<<24) | ((unsigned int)vp->reg.loopstart - 1);
373 EMU8000_PSST_WRITE(hw, vp->ch, temp);
374}
375
376#define MOD_SENSE 18
377
378static void
379set_fmmod(emu8000_t *hw, snd_emux_voice_t *vp)
380{
381 unsigned short fmmod;
382 short pitch;
383 unsigned char cutoff;
384 int modulation;
385
386 pitch = (char)(vp->reg.parm.fmmod>>8);
387 cutoff = (vp->reg.parm.fmmod & 0xff);
388 modulation = vp->chan->gm_modulation + vp->chan->midi_pressure;
389 pitch += (MOD_SENSE * modulation) / 1200;
390 LIMITVALUE(pitch, -128, 127);
391 fmmod = ((unsigned char)pitch<<8) | cutoff;
392 EMU8000_FMMOD_WRITE(hw, vp->ch, fmmod);
393}
394
395/* set tremolo (lfo1) volume & frequency */
396static void
397set_tremfreq(emu8000_t *hw, snd_emux_voice_t *vp)
398{
399 EMU8000_TREMFRQ_WRITE(hw, vp->ch, vp->reg.parm.tremfrq);
400}
401
402/* set lfo2 pitch & frequency */
403static void
404set_fm2frq2(emu8000_t *hw, snd_emux_voice_t *vp)
405{
406 unsigned short fm2frq2;
407 short pitch;
408 unsigned char freq;
409 int modulation;
410
411 pitch = (char)(vp->reg.parm.fm2frq2>>8);
412 freq = vp->reg.parm.fm2frq2 & 0xff;
413 modulation = vp->chan->gm_modulation + vp->chan->midi_pressure;
414 pitch += (MOD_SENSE * modulation) / 1200;
415 LIMITVALUE(pitch, -128, 127);
416 fm2frq2 = ((unsigned char)pitch<<8) | freq;
417 EMU8000_FM2FRQ2_WRITE(hw, vp->ch, fm2frq2);
418}
419
420/* set filterQ */
421static void
422set_filterQ(emu8000_t *hw, snd_emux_voice_t *vp)
423{
424 unsigned int addr;
425 addr = EMU8000_CCCA_READ(hw, vp->ch) & 0xffffff;
426 addr |= (vp->reg.parm.filterQ << 28);
427 EMU8000_CCCA_WRITE(hw, vp->ch, addr);
428}
429
430/*
431 * set the envelope & LFO parameters to the default values
432 */
433static void
434snd_emu8000_tweak_voice(emu8000_t *emu, int i)
435{
436 /* set all mod/vol envelope shape to minimum */
437 EMU8000_ENVVOL_WRITE(emu, i, 0x8000);
438 EMU8000_ENVVAL_WRITE(emu, i, 0x8000);
439 EMU8000_DCYSUS_WRITE(emu, i, 0x7F7F);
440 EMU8000_ATKHLDV_WRITE(emu, i, 0x7F7F);
441 EMU8000_ATKHLD_WRITE(emu, i, 0x7F7F);
442 EMU8000_PEFE_WRITE(emu, i, 0); /* mod envelope height to zero */
443 EMU8000_LFO1VAL_WRITE(emu, i, 0x8000); /* no delay for LFO1 */
444 EMU8000_LFO2VAL_WRITE(emu, i, 0x8000);
445 EMU8000_IP_WRITE(emu, i, 0xE000); /* no pitch shift */
446 EMU8000_IFATN_WRITE(emu, i, 0xFF00); /* volume to minimum */
447 EMU8000_FMMOD_WRITE(emu, i, 0);
448 EMU8000_TREMFRQ_WRITE(emu, i, 0);
449 EMU8000_FM2FRQ2_WRITE(emu, i, 0);
450}
451
452/*
453 * sysex callback
454 */
455static void
456sysex(snd_emux_t *emu, char *buf, int len, int parsed, snd_midi_channel_set_t *chset)
457{
458 emu8000_t *hw;
459
460 hw = emu->hw;
461
462 switch (parsed) {
463 case SNDRV_MIDI_SYSEX_GS_CHORUS_MODE:
464 hw->chorus_mode = chset->gs_chorus_mode;
465 snd_emu8000_update_chorus_mode(hw);
466 break;
467
468 case SNDRV_MIDI_SYSEX_GS_REVERB_MODE:
469 hw->reverb_mode = chset->gs_reverb_mode;
470 snd_emu8000_update_reverb_mode(hw);
471 break;
472 }
473}
474
475
476#ifdef CONFIG_SND_SEQUENCER_OSS
477/*
478 * OSS ioctl callback
479 */
480static int
481oss_ioctl(snd_emux_t *emu, int cmd, int p1, int p2)
482{
483 emu8000_t *hw;
484
485 hw = emu->hw;
486
487 switch (cmd) {
488 case _EMUX_OSS_REVERB_MODE:
489 hw->reverb_mode = p1;
490 snd_emu8000_update_reverb_mode(hw);
491 break;
492
493 case _EMUX_OSS_CHORUS_MODE:
494 hw->chorus_mode = p1;
495 snd_emu8000_update_chorus_mode(hw);
496 break;
497
498 case _EMUX_OSS_INITIALIZE_CHIP:
499 /* snd_emu8000_init(hw); */ /*ignored*/
500 break;
501
502 case _EMUX_OSS_EQUALIZER:
503 hw->bass_level = p1;
504 hw->treble_level = p2;
505 snd_emu8000_update_equalizer(hw);
506 break;
507 }
508 return 0;
509}
510#endif
511
512
513/*
514 * additional patch keys
515 */
516
517#define SNDRV_EMU8000_LOAD_CHORUS_FX 0x10 /* optarg=mode */
518#define SNDRV_EMU8000_LOAD_REVERB_FX 0x11 /* optarg=mode */
519
520
521/*
522 * callback routine
523 */
524
525static int
526load_fx(snd_emux_t *emu, int type, int mode, const void __user *buf, long len)
527{
528 emu8000_t *hw;
529 hw = emu->hw;
530
531 /* skip header */
532 buf += 16;
533 len -= 16;
534
535 switch (type) {
536 case SNDRV_EMU8000_LOAD_CHORUS_FX:
537 return snd_emu8000_load_chorus_fx(hw, mode, buf, len);
538 case SNDRV_EMU8000_LOAD_REVERB_FX:
539 return snd_emu8000_load_reverb_fx(hw, mode, buf, len);
540 }
541 return -EINVAL;
542}
543
diff --git a/sound/isa/sb/emu8000_local.h b/sound/isa/sb/emu8000_local.h
new file mode 100644
index 000000000000..ea4996a895fc
--- /dev/null
+++ b/sound/isa/sb/emu8000_local.h
@@ -0,0 +1,43 @@
1#ifndef __EMU8000_LOCAL_H
2#define __EMU8000_LOCAL_H
3/*
4 * Local defininitons for the emu8000 (AWE32/64)
5 *
6 * Copyright (C) 1999 Steve Ratcliffe
7 * Copyright (C) 1999-2000 Takashi Iwai <tiwai@suse.de>
8 *
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
13 *
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22 */
23
24#include <sound/driver.h>
25#include <linux/wait.h>
26#include <linux/sched.h>
27#include <linux/slab.h>
28#include <sound/core.h>
29#include <sound/emu8000.h>
30#include <sound/emu8000_reg.h>
31
32/* emu8000_patch.c */
33int snd_emu8000_sample_new(snd_emux_t *rec, snd_sf_sample_t *sp, snd_util_memhdr_t *hdr, const void __user *data, long count);
34int snd_emu8000_sample_free(snd_emux_t *rec, snd_sf_sample_t *sp, snd_util_memhdr_t *hdr);
35void snd_emu8000_sample_reset(snd_emux_t *rec);
36
37/* emu8000_callback.c */
38void snd_emu8000_ops_setup(emu8000_t *emu);
39
40/* emu8000_pcm.c */
41int snd_emu8000_pcm_new(snd_card_t *card, emu8000_t *emu, int index);
42
43#endif /* __EMU8000_LOCAL_H */
diff --git a/sound/isa/sb/emu8000_patch.c b/sound/isa/sb/emu8000_patch.c
new file mode 100644
index 000000000000..4afc4a1bc140
--- /dev/null
+++ b/sound/isa/sb/emu8000_patch.c
@@ -0,0 +1,303 @@
1/*
2 * Patch routines for the emu8000 (AWE32/64)
3 *
4 * Copyright (C) 1999 Steve Ratcliffe
5 * Copyright (C) 1999-2000 Takashi Iwai <tiwai@suse.de>
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 */
21
22#include "emu8000_local.h"
23#include <asm/uaccess.h>
24#include <linux/moduleparam.h>
25
26static int emu8000_reset_addr = 0;
27module_param(emu8000_reset_addr, int, 0444);
28MODULE_PARM_DESC(emu8000_reset_addr, "reset write address at each time (makes slowdown)");
29
30
31/*
32 * Open up channels.
33 */
34static int
35snd_emu8000_open_dma(emu8000_t *emu, int write)
36{
37 int i;
38
39 /* reserve all 30 voices for loading */
40 for (i = 0; i < EMU8000_DRAM_VOICES; i++) {
41 snd_emux_lock_voice(emu->emu, i);
42 snd_emu8000_dma_chan(emu, i, write);
43 }
44
45 /* assign voice 31 and 32 to ROM */
46 EMU8000_VTFT_WRITE(emu, 30, 0);
47 EMU8000_PSST_WRITE(emu, 30, 0x1d8);
48 EMU8000_CSL_WRITE(emu, 30, 0x1e0);
49 EMU8000_CCCA_WRITE(emu, 30, 0x1d8);
50 EMU8000_VTFT_WRITE(emu, 31, 0);
51 EMU8000_PSST_WRITE(emu, 31, 0x1d8);
52 EMU8000_CSL_WRITE(emu, 31, 0x1e0);
53 EMU8000_CCCA_WRITE(emu, 31, 0x1d8);
54
55 return 0;
56}
57
58/*
59 * Close all dram channels.
60 */
61static void
62snd_emu8000_close_dma(emu8000_t *emu)
63{
64 int i;
65
66 for (i = 0; i < EMU8000_DRAM_VOICES; i++) {
67 snd_emu8000_dma_chan(emu, i, EMU8000_RAM_CLOSE);
68 snd_emux_unlock_voice(emu->emu, i);
69 }
70}
71
72/*
73 */
74
75#define BLANK_LOOP_START 4
76#define BLANK_LOOP_END 8
77#define BLANK_LOOP_SIZE 12
78#define BLANK_HEAD_SIZE 48
79
80/*
81 * Read a word from userland, taking care of conversions from
82 * 8bit samples etc.
83 */
84static unsigned short
85read_word(const void __user *buf, int offset, int mode)
86{
87 unsigned short c;
88 if (mode & SNDRV_SFNT_SAMPLE_8BITS) {
89 unsigned char cc;
90 get_user(cc, (unsigned char __user *)buf + offset);
91 c = cc << 8; /* convert 8bit -> 16bit */
92 } else {
93#ifdef SNDRV_LITTLE_ENDIAN
94 get_user(c, (unsigned short __user *)buf + offset);
95#else
96 unsigned short cc;
97 get_user(cc, (unsigned short __user *)buf + offset);
98 c = swab16(cc);
99#endif
100 }
101 if (mode & SNDRV_SFNT_SAMPLE_UNSIGNED)
102 c ^= 0x8000; /* unsigned -> signed */
103 return c;
104}
105
106/*
107 */
108static void
109snd_emu8000_write_wait(emu8000_t *emu)
110{
111 while ((EMU8000_SMALW_READ(emu) & 0x80000000) != 0) {
112 set_current_state(TASK_INTERRUPTIBLE);
113 schedule_timeout(1);
114 if (signal_pending(current))
115 break;
116 }
117}
118
119/*
120 * write sample word data
121 *
122 * You should not have to keep resetting the address each time
123 * as the chip is supposed to step on the next address automatically.
124 * It mostly does, but during writes of some samples at random it
125 * completely loses words (every one in 16 roughly but with no
126 * obvious pattern).
127 *
128 * This is therefore much slower than need be, but is at least
129 * working.
130 */
131inline static void
132write_word(emu8000_t *emu, int *offset, unsigned short data)
133{
134 if (emu8000_reset_addr) {
135 if (emu8000_reset_addr > 1)
136 snd_emu8000_write_wait(emu);
137 EMU8000_SMALW_WRITE(emu, *offset);
138 }
139 EMU8000_SMLD_WRITE(emu, data);
140 *offset += 1;
141}
142
143/*
144 * Write the sample to EMU800 memory. This routine is invoked out of
145 * the generic soundfont routines as a callback.
146 */
147int
148snd_emu8000_sample_new(snd_emux_t *rec, snd_sf_sample_t *sp,
149 snd_util_memhdr_t *hdr, const void __user *data, long count)
150{
151 int i;
152 int rc;
153 int offset;
154 int truesize;
155 int dram_offset, dram_start;
156 emu8000_t *emu;
157
158 emu = rec->hw;
159 snd_assert(sp != NULL, return -EINVAL);
160
161 if (sp->v.size == 0)
162 return 0;
163
164 /* be sure loop points start < end */
165 if (sp->v.loopstart > sp->v.loopend) {
166 int tmp = sp->v.loopstart;
167 sp->v.loopstart = sp->v.loopend;
168 sp->v.loopend = tmp;
169 }
170
171 /* compute true data size to be loaded */
172 truesize = sp->v.size;
173 if (sp->v.mode_flags & (SNDRV_SFNT_SAMPLE_BIDIR_LOOP|SNDRV_SFNT_SAMPLE_REVERSE_LOOP))
174 truesize += sp->v.loopend - sp->v.loopstart;
175 if (sp->v.mode_flags & SNDRV_SFNT_SAMPLE_NO_BLANK)
176 truesize += BLANK_LOOP_SIZE;
177
178 sp->block = snd_util_mem_alloc(hdr, truesize * 2);
179 if (sp->block == NULL) {
180 /*snd_printd("EMU8000: out of memory\n");*/
181 /* not ENOMEM (for compatibility) */
182 return -ENOSPC;
183 }
184
185 if (sp->v.mode_flags & SNDRV_SFNT_SAMPLE_8BITS) {
186 if (!access_ok(VERIFY_READ, data, sp->v.size))
187 return -EFAULT;
188 } else {
189 if (!access_ok(VERIFY_READ, data, sp->v.size * 2))
190 return -EFAULT;
191 }
192
193 /* recalculate address offset */
194 sp->v.end -= sp->v.start;
195 sp->v.loopstart -= sp->v.start;
196 sp->v.loopend -= sp->v.start;
197 sp->v.start = 0;
198
199 /* dram position (in word) -- mem_offset is byte */
200 dram_offset = EMU8000_DRAM_OFFSET + (sp->block->offset >> 1);
201 dram_start = dram_offset;
202
203 /* set the total size (store onto obsolete checksum value) */
204 sp->v.truesize = truesize * 2; /* in bytes */
205
206 snd_emux_terminate_all(emu->emu);
207 if ((rc = snd_emu8000_open_dma(emu, EMU8000_RAM_WRITE)) != 0)
208 return rc;
209
210 /* Set the address to start writing at */
211 snd_emu8000_write_wait(emu);
212 EMU8000_SMALW_WRITE(emu, dram_offset);
213
214 /*snd_emu8000_init_fm(emu);*/
215
216#if 0
217 /* first block - write 48 samples for silence */
218 if (! sp->block->offset) {
219 for (i = 0; i < BLANK_HEAD_SIZE; i++) {
220 write_word(emu, &dram_offset, 0);
221 }
222 }
223#endif
224
225 offset = 0;
226 for (i = 0; i < sp->v.size; i++) {
227 unsigned short s;
228
229 s = read_word(data, offset, sp->v.mode_flags);
230 offset++;
231 write_word(emu, &dram_offset, s);
232
233 /* we may take too long time in this loop.
234 * so give controls back to kernel if needed.
235 */
236 cond_resched();
237
238 if (i == sp->v.loopend &&
239 (sp->v.mode_flags & (SNDRV_SFNT_SAMPLE_BIDIR_LOOP|SNDRV_SFNT_SAMPLE_REVERSE_LOOP)))
240 {
241 int looplen = sp->v.loopend - sp->v.loopstart;
242 int k;
243
244 /* copy reverse loop */
245 for (k = 1; k <= looplen; k++) {
246 s = read_word(data, offset - k, sp->v.mode_flags);
247 write_word(emu, &dram_offset, s);
248 }
249 if (sp->v.mode_flags & SNDRV_SFNT_SAMPLE_BIDIR_LOOP) {
250 sp->v.loopend += looplen;
251 } else {
252 sp->v.loopstart += looplen;
253 sp->v.loopend += looplen;
254 }
255 sp->v.end += looplen;
256 }
257 }
258
259 /* if no blank loop is attached in the sample, add it */
260 if (sp->v.mode_flags & SNDRV_SFNT_SAMPLE_NO_BLANK) {
261 for (i = 0; i < BLANK_LOOP_SIZE; i++) {
262 write_word(emu, &dram_offset, 0);
263 }
264 if (sp->v.mode_flags & SNDRV_SFNT_SAMPLE_SINGLESHOT) {
265 sp->v.loopstart = sp->v.end + BLANK_LOOP_START;
266 sp->v.loopend = sp->v.end + BLANK_LOOP_END;
267 }
268 }
269
270 /* add dram offset */
271 sp->v.start += dram_start;
272 sp->v.end += dram_start;
273 sp->v.loopstart += dram_start;
274 sp->v.loopend += dram_start;
275
276 snd_emu8000_close_dma(emu);
277 snd_emu8000_init_fm(emu);
278
279 return 0;
280}
281
282/*
283 * free a sample block
284 */
285int
286snd_emu8000_sample_free(snd_emux_t *rec, snd_sf_sample_t *sp, snd_util_memhdr_t *hdr)
287{
288 if (sp->block) {
289 snd_util_mem_free(hdr, sp->block);
290 sp->block = NULL;
291 }
292 return 0;
293}
294
295
296/*
297 * sample_reset callback - terminate voices
298 */
299void
300snd_emu8000_sample_reset(snd_emux_t *rec)
301{
302 snd_emux_terminate_all(rec);
303}
diff --git a/sound/isa/sb/emu8000_pcm.c b/sound/isa/sb/emu8000_pcm.c
new file mode 100644
index 000000000000..db5eb8b55058
--- /dev/null
+++ b/sound/isa/sb/emu8000_pcm.c
@@ -0,0 +1,704 @@
1/*
2 * pcm emulation on emu8000 wavetable
3 *
4 * Copyright (C) 2002 Takashi Iwai <tiwai@suse.de>
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 */
20
21#include "emu8000_local.h"
22#include <linux/init.h>
23#include <sound/initval.h>
24#include <sound/pcm.h>
25
26/*
27 * define the following if you want to use this pcm with non-interleaved mode
28 */
29/* #define USE_NONINTERLEAVE */
30
31/* NOTE: for using the non-interleaved mode with alsa-lib, you have to set
32 * mmap_emulation flag to 1 in your .asoundrc, such like
33 *
34 * pcm.emu8k {
35 * type plug
36 * slave.pcm {
37 * type hw
38 * card 0
39 * device 1
40 * mmap_emulation 1
41 * }
42 * }
43 *
44 * besides, for the time being, the non-interleaved mode doesn't work well on
45 * alsa-lib...
46 */
47
48
49typedef struct snd_emu8k_pcm emu8k_pcm_t;
50
51struct snd_emu8k_pcm {
52 emu8000_t *emu;
53 snd_pcm_substream_t *substream;
54
55 unsigned int allocated_bytes;
56 snd_util_memblk_t *block;
57 unsigned int offset;
58 unsigned int buf_size;
59 unsigned int period_size;
60 unsigned int loop_start[2];
61 unsigned int pitch;
62 int panning[2];
63 int last_ptr;
64 int period_pos;
65 int voices;
66 unsigned int dram_opened: 1;
67 unsigned int running: 1;
68 unsigned int timer_running: 1;
69 struct timer_list timer;
70 spinlock_t timer_lock;
71};
72
73#define LOOP_BLANK_SIZE 8
74
75
76/*
77 * open up channels for the simultaneous data transfer and playback
78 */
79static int
80emu8k_open_dram_for_pcm(emu8000_t *emu, int channels)
81{
82 int i;
83
84 /* reserve up to 2 voices for playback */
85 snd_emux_lock_voice(emu->emu, 0);
86 if (channels > 1)
87 snd_emux_lock_voice(emu->emu, 1);
88
89 /* reserve 28 voices for loading */
90 for (i = channels + 1; i < EMU8000_DRAM_VOICES; i++) {
91 unsigned int mode = EMU8000_RAM_WRITE;
92 snd_emux_lock_voice(emu->emu, i);
93#ifndef USE_NONINTERLEAVE
94 if (channels > 1 && (i & 1) != 0)
95 mode |= EMU8000_RAM_RIGHT;
96#endif
97 snd_emu8000_dma_chan(emu, i, mode);
98 }
99
100 /* assign voice 31 and 32 to ROM */
101 EMU8000_VTFT_WRITE(emu, 30, 0);
102 EMU8000_PSST_WRITE(emu, 30, 0x1d8);
103 EMU8000_CSL_WRITE(emu, 30, 0x1e0);
104 EMU8000_CCCA_WRITE(emu, 30, 0x1d8);
105 EMU8000_VTFT_WRITE(emu, 31, 0);
106 EMU8000_PSST_WRITE(emu, 31, 0x1d8);
107 EMU8000_CSL_WRITE(emu, 31, 0x1e0);
108 EMU8000_CCCA_WRITE(emu, 31, 0x1d8);
109
110 return 0;
111}
112
113/*
114 */
115static void
116snd_emu8000_write_wait(emu8000_t *emu, int can_schedule)
117{
118 while ((EMU8000_SMALW_READ(emu) & 0x80000000) != 0) {
119 if (can_schedule) {
120 set_current_state(TASK_INTERRUPTIBLE);
121 schedule_timeout(1);
122 if (signal_pending(current))
123 break;
124 }
125 }
126}
127
128/*
129 * close all channels
130 */
131static void
132emu8k_close_dram(emu8000_t *emu)
133{
134 int i;
135
136 for (i = 0; i < 2; i++)
137 snd_emux_unlock_voice(emu->emu, i);
138 for (; i < EMU8000_DRAM_VOICES; i++) {
139 snd_emu8000_dma_chan(emu, i, EMU8000_RAM_CLOSE);
140 snd_emux_unlock_voice(emu->emu, i);
141 }
142}
143
144/*
145 * convert Hz to AWE32 rate offset (see emux/soundfont.c)
146 */
147
148#define OFFSET_SAMPLERATE 1011119 /* base = 44100 */
149#define SAMPLERATE_RATIO 4096
150
151static int calc_rate_offset(int hz)
152{
153 return snd_sf_linear_to_log(hz, OFFSET_SAMPLERATE, SAMPLERATE_RATIO);
154}
155
156
157/*
158 */
159
160static snd_pcm_hardware_t emu8k_pcm_hw = {
161#ifdef USE_NONINTERLEAVE
162 .info = SNDRV_PCM_INFO_NONINTERLEAVED,
163#else
164 .info = SNDRV_PCM_INFO_INTERLEAVED,
165#endif
166 .formats = SNDRV_PCM_FMTBIT_S16_LE,
167 .rates = SNDRV_PCM_RATE_CONTINUOUS | SNDRV_PCM_RATE_8000_48000,
168 .rate_min = 4000,
169 .rate_max = 48000,
170 .channels_min = 1,
171 .channels_max = 2,
172 .buffer_bytes_max = (128*1024),
173 .period_bytes_min = 1024,
174 .period_bytes_max = (128*1024),
175 .periods_min = 2,
176 .periods_max = 1024,
177 .fifo_size = 0,
178
179};
180
181/*
182 * get the current position at the given channel from CCCA register
183 */
184static inline int emu8k_get_curpos(emu8k_pcm_t *rec, int ch)
185{
186 int val = EMU8000_CCCA_READ(rec->emu, ch) & 0xfffffff;
187 val -= rec->loop_start[ch] - 1;
188 return val;
189}
190
191
192/*
193 * timer interrupt handler
194 * check the current position and update the period if necessary.
195 */
196static void emu8k_pcm_timer_func(unsigned long data)
197{
198 emu8k_pcm_t *rec = (emu8k_pcm_t *)data;
199 int ptr, delta;
200
201 spin_lock(&rec->timer_lock);
202 /* update the current pointer */
203 ptr = emu8k_get_curpos(rec, 0);
204 if (ptr < rec->last_ptr)
205 delta = ptr + rec->buf_size - rec->last_ptr;
206 else
207 delta = ptr - rec->last_ptr;
208 rec->period_pos += delta;
209 rec->last_ptr = ptr;
210
211 /* reprogram timer */
212 rec->timer.expires = jiffies + 1;
213 add_timer(&rec->timer);
214
215 /* update period */
216 if (rec->period_pos >= (int)rec->period_size) {
217 rec->period_pos %= rec->period_size;
218 spin_unlock(&rec->timer_lock);
219 snd_pcm_period_elapsed(rec->substream);
220 return;
221 }
222 spin_unlock(&rec->timer_lock);
223}
224
225
226/*
227 * open pcm
228 * creating an instance here
229 */
230static int emu8k_pcm_open(snd_pcm_substream_t *subs)
231{
232 emu8000_t *emu = snd_pcm_substream_chip(subs);
233 emu8k_pcm_t *rec;
234 snd_pcm_runtime_t *runtime = subs->runtime;
235
236 rec = kcalloc(1, sizeof(*rec), GFP_KERNEL);
237 if (! rec)
238 return -ENOMEM;
239
240 rec->emu = emu;
241 rec->substream = subs;
242 runtime->private_data = rec;
243
244 spin_lock_init(&rec->timer_lock);
245 init_timer(&rec->timer);
246 rec->timer.function = emu8k_pcm_timer_func;
247 rec->timer.data = (unsigned long)rec;
248
249 runtime->hw = emu8k_pcm_hw;
250 runtime->hw.buffer_bytes_max = emu->mem_size - LOOP_BLANK_SIZE * 3;
251 runtime->hw.period_bytes_max = runtime->hw.buffer_bytes_max / 2;
252
253 /* use timer to update periods.. (specified in msec) */
254 snd_pcm_hw_constraint_minmax(runtime, SNDRV_PCM_HW_PARAM_PERIOD_TIME,
255 (1000000 + HZ - 1) / HZ, UINT_MAX);
256
257 return 0;
258}
259
260static int emu8k_pcm_close(snd_pcm_substream_t *subs)
261{
262 emu8k_pcm_t *rec = subs->runtime->private_data;
263 kfree(rec);
264 subs->runtime->private_data = NULL;
265 return 0;
266}
267
268/*
269 * calculate pitch target
270 */
271static int calc_pitch_target(int pitch)
272{
273 int ptarget = 1 << (pitch >> 12);
274 if (pitch & 0x800) ptarget += (ptarget * 0x102e) / 0x2710;
275 if (pitch & 0x400) ptarget += (ptarget * 0x764) / 0x2710;
276 if (pitch & 0x200) ptarget += (ptarget * 0x389) / 0x2710;
277 ptarget += (ptarget >> 1);
278 if (ptarget > 0xffff) ptarget = 0xffff;
279 return ptarget;
280}
281
282/*
283 * set up the voice
284 */
285static void setup_voice(emu8k_pcm_t *rec, int ch)
286{
287 emu8000_t *hw = rec->emu;
288 unsigned int temp;
289
290 /* channel to be silent and idle */
291 EMU8000_DCYSUSV_WRITE(hw, ch, 0x0080);
292 EMU8000_VTFT_WRITE(hw, ch, 0x0000FFFF);
293 EMU8000_CVCF_WRITE(hw, ch, 0x0000FFFF);
294 EMU8000_PTRX_WRITE(hw, ch, 0);
295 EMU8000_CPF_WRITE(hw, ch, 0);
296
297 /* pitch offset */
298 EMU8000_IP_WRITE(hw, ch, rec->pitch);
299 /* set envelope parameters */
300 EMU8000_ENVVAL_WRITE(hw, ch, 0x8000);
301 EMU8000_ATKHLD_WRITE(hw, ch, 0x7f7f);
302 EMU8000_DCYSUS_WRITE(hw, ch, 0x7f7f);
303 EMU8000_ENVVOL_WRITE(hw, ch, 0x8000);
304 EMU8000_ATKHLDV_WRITE(hw, ch, 0x7f7f);
305 /* decay/sustain parameter for volume envelope is used
306 for triggerg the voice */
307 /* modulation envelope heights */
308 EMU8000_PEFE_WRITE(hw, ch, 0x0);
309 /* lfo1/2 delay */
310 EMU8000_LFO1VAL_WRITE(hw, ch, 0x8000);
311 EMU8000_LFO2VAL_WRITE(hw, ch, 0x8000);
312 /* lfo1 pitch & cutoff shift */
313 EMU8000_FMMOD_WRITE(hw, ch, 0);
314 /* lfo1 volume & freq */
315 EMU8000_TREMFRQ_WRITE(hw, ch, 0);
316 /* lfo2 pitch & freq */
317 EMU8000_FM2FRQ2_WRITE(hw, ch, 0);
318 /* pan & loop start */
319 temp = rec->panning[ch];
320 temp = (temp <<24) | ((unsigned int)rec->loop_start[ch] - 1);
321 EMU8000_PSST_WRITE(hw, ch, temp);
322 /* chorus & loop end (chorus 8bit, MSB) */
323 temp = 0; // chorus
324 temp = (temp << 24) | ((unsigned int)rec->loop_start[ch] + rec->buf_size - 1);
325 EMU8000_CSL_WRITE(hw, ch, temp);
326 /* Q & current address (Q 4bit value, MSB) */
327 temp = 0; // filterQ
328 temp = (temp << 28) | ((unsigned int)rec->loop_start[ch] - 1);
329 EMU8000_CCCA_WRITE(hw, ch, temp);
330 /* clear unknown registers */
331 EMU8000_00A0_WRITE(hw, ch, 0);
332 EMU8000_0080_WRITE(hw, ch, 0);
333}
334
335/*
336 * trigger the voice
337 */
338static void start_voice(emu8k_pcm_t *rec, int ch)
339{
340 unsigned long flags;
341 emu8000_t *hw = rec->emu;
342 unsigned int temp, aux;
343 int pt = calc_pitch_target(rec->pitch);
344
345 /* cutoff and volume */
346 EMU8000_IFATN_WRITE(hw, ch, 0xff00);
347 EMU8000_VTFT_WRITE(hw, ch, 0xffff);
348 EMU8000_CVCF_WRITE(hw, ch, 0xffff);
349 /* trigger envelope */
350 EMU8000_DCYSUSV_WRITE(hw, ch, 0x7f7f);
351 /* set reverb and pitch target */
352 temp = 0; // reverb
353 if (rec->panning[ch] == 0)
354 aux = 0xff;
355 else
356 aux = (-rec->panning[ch]) & 0xff;
357 temp = (temp << 8) | (pt << 16) | aux;
358 EMU8000_PTRX_WRITE(hw, ch, temp);
359 EMU8000_CPF_WRITE(hw, ch, pt << 16);
360
361 /* start timer */
362 spin_lock_irqsave(&rec->timer_lock, flags);
363 if (! rec->timer_running) {
364 rec->timer.expires = jiffies + 1;
365 add_timer(&rec->timer);
366 rec->timer_running = 1;
367 }
368 spin_unlock_irqrestore(&rec->timer_lock, flags);
369}
370
371/*
372 * stop the voice immediately
373 */
374static void stop_voice(emu8k_pcm_t *rec, int ch)
375{
376 unsigned long flags;
377 emu8000_t *hw = rec->emu;
378
379 EMU8000_DCYSUSV_WRITE(hw, ch, 0x807F);
380
381 /* stop timer */
382 spin_lock_irqsave(&rec->timer_lock, flags);
383 if (rec->timer_running) {
384 del_timer(&rec->timer);
385 rec->timer_running = 0;
386 }
387 spin_unlock_irqrestore(&rec->timer_lock, flags);
388}
389
390static int emu8k_pcm_trigger(snd_pcm_substream_t *subs, int cmd)
391{
392 emu8k_pcm_t *rec = subs->runtime->private_data;
393 int ch;
394
395 switch (cmd) {
396 case SNDRV_PCM_TRIGGER_START:
397 for (ch = 0; ch < rec->voices; ch++)
398 start_voice(rec, ch);
399 rec->running = 1;
400 break;
401 case SNDRV_PCM_TRIGGER_STOP:
402 rec->running = 0;
403 for (ch = 0; ch < rec->voices; ch++)
404 stop_voice(rec, ch);
405 break;
406 default:
407 return -EINVAL;
408 }
409 return 0;
410}
411
412
413/*
414 * copy / silence ops
415 */
416
417/*
418 * this macro should be inserted in the copy/silence loops
419 * to reduce the latency. without this, the system will hang up
420 * during the whole loop.
421 */
422#define CHECK_SCHEDULER() \
423do { \
424 cond_resched();\
425 if (signal_pending(current))\
426 return -EAGAIN;\
427} while (0)
428
429
430#ifdef USE_NONINTERLEAVE
431/* copy one channel block */
432static int emu8k_transfer_block(emu8000_t *emu, int offset, unsigned short *buf, int count)
433{
434 EMU8000_SMALW_WRITE(emu, offset);
435 while (count > 0) {
436 unsigned short sval;
437 CHECK_SCHEDULER();
438 get_user(sval, buf);
439 EMU8000_SMLD_WRITE(emu, sval);
440 buf++;
441 count--;
442 }
443 return 0;
444}
445
446static int emu8k_pcm_copy(snd_pcm_substream_t *subs,
447 int voice,
448 snd_pcm_uframes_t pos,
449 void *src,
450 snd_pcm_uframes_t count)
451{
452 emu8k_pcm_t *rec = subs->runtime->private_data;
453 emu8000_t *emu = rec->emu;
454
455 snd_emu8000_write_wait(emu, 1);
456 if (voice == -1) {
457 unsigned short *buf = src;
458 int i, err;
459 count /= rec->voices;
460 for (i = 0; i < rec->voices; i++) {
461 err = emu8k_transfer_block(emu, pos + rec->loop_start[i], buf, count);
462 if (err < 0)
463 return err;
464 buf += count;
465 }
466 return 0;
467 } else {
468 return emu8k_transfer_block(emu, pos + rec->loop_start[voice], src, count);
469 }
470}
471
472/* make a channel block silence */
473static int emu8k_silence_block(emu8000_t *emu, int offset, int count)
474{
475 EMU8000_SMALW_WRITE(emu, offset);
476 while (count > 0) {
477 CHECK_SCHEDULER();
478 EMU8000_SMLD_WRITE(emu, 0);
479 count--;
480 }
481 return 0;
482}
483
484static int emu8k_pcm_silence(snd_pcm_substream_t *subs,
485 int voice,
486 snd_pcm_uframes_t pos,
487 snd_pcm_uframes_t count)
488{
489 emu8k_pcm_t *rec = subs->runtime->private_data;
490 emu8000_t *emu = rec->emu;
491
492 snd_emu8000_write_wait(emu, 1);
493 if (voice == -1 && rec->voices == 1)
494 voice = 0;
495 if (voice == -1) {
496 int err;
497 err = emu8k_silence_block(emu, pos + rec->loop_start[0], count / 2);
498 if (err < 0)
499 return err;
500 return emu8k_silence_block(emu, pos + rec->loop_start[1], count / 2);
501 } else {
502 return emu8k_silence_block(emu, pos + rec->loop_start[voice], count);
503 }
504}
505
506#else /* interleave */
507
508/*
509 * copy the interleaved data can be done easily by using
510 * DMA "left" and "right" channels on emu8k engine.
511 */
512static int emu8k_pcm_copy(snd_pcm_substream_t *subs,
513 int voice,
514 snd_pcm_uframes_t pos,
515 void __user *src,
516 snd_pcm_uframes_t count)
517{
518 emu8k_pcm_t *rec = subs->runtime->private_data;
519 emu8000_t *emu = rec->emu;
520 unsigned short __user *buf = src;
521
522 snd_emu8000_write_wait(emu, 1);
523 EMU8000_SMALW_WRITE(emu, pos + rec->loop_start[0]);
524 if (rec->voices > 1)
525 EMU8000_SMARW_WRITE(emu, pos + rec->loop_start[1]);
526
527 while (count-- > 0) {
528 unsigned short sval;
529 CHECK_SCHEDULER();
530 get_user(sval, buf);
531 EMU8000_SMLD_WRITE(emu, sval);
532 buf++;
533 if (rec->voices > 1) {
534 CHECK_SCHEDULER();
535 get_user(sval, buf);
536 EMU8000_SMRD_WRITE(emu, sval);
537 buf++;
538 }
539 }
540 return 0;
541}
542
543static int emu8k_pcm_silence(snd_pcm_substream_t *subs,
544 int voice,
545 snd_pcm_uframes_t pos,
546 snd_pcm_uframes_t count)
547{
548 emu8k_pcm_t *rec = subs->runtime->private_data;
549 emu8000_t *emu = rec->emu;
550
551 snd_emu8000_write_wait(emu, 1);
552 EMU8000_SMALW_WRITE(emu, rec->loop_start[0] + pos);
553 if (rec->voices > 1)
554 EMU8000_SMARW_WRITE(emu, rec->loop_start[1] + pos);
555 while (count-- > 0) {
556 CHECK_SCHEDULER();
557 EMU8000_SMLD_WRITE(emu, 0);
558 if (rec->voices > 1) {
559 CHECK_SCHEDULER();
560 EMU8000_SMRD_WRITE(emu, 0);
561 }
562 }
563 return 0;
564}
565#endif
566
567
568/*
569 * allocate a memory block
570 */
571static int emu8k_pcm_hw_params(snd_pcm_substream_t *subs,
572 snd_pcm_hw_params_t *hw_params)
573{
574 emu8k_pcm_t *rec = subs->runtime->private_data;
575
576 if (rec->block) {
577 /* reallocation - release the old block */
578 snd_util_mem_free(rec->emu->memhdr, rec->block);
579 rec->block = NULL;
580 }
581
582 rec->allocated_bytes = params_buffer_bytes(hw_params) + LOOP_BLANK_SIZE * 4;
583 rec->block = snd_util_mem_alloc(rec->emu->memhdr, rec->allocated_bytes);
584 if (! rec->block)
585 return -ENOMEM;
586 rec->offset = EMU8000_DRAM_OFFSET + (rec->block->offset >> 1); /* in word */
587 /* at least dma_bytes must be set for non-interleaved mode */
588 subs->dma_buffer.bytes = params_buffer_bytes(hw_params);
589
590 return 0;
591}
592
593/*
594 * free the memory block
595 */
596static int emu8k_pcm_hw_free(snd_pcm_substream_t *subs)
597{
598 emu8k_pcm_t *rec = subs->runtime->private_data;
599
600 if (rec->block) {
601 int ch;
602 for (ch = 0; ch < rec->voices; ch++)
603 stop_voice(rec, ch); // to be sure
604 if (rec->dram_opened)
605 emu8k_close_dram(rec->emu);
606 snd_util_mem_free(rec->emu->memhdr, rec->block);
607 rec->block = NULL;
608 }
609 return 0;
610}
611
612/*
613 */
614static int emu8k_pcm_prepare(snd_pcm_substream_t *subs)
615{
616 emu8k_pcm_t *rec = subs->runtime->private_data;
617
618 rec->pitch = 0xe000 + calc_rate_offset(subs->runtime->rate);
619 rec->last_ptr = 0;
620 rec->period_pos = 0;
621
622 rec->buf_size = subs->runtime->buffer_size;
623 rec->period_size = subs->runtime->period_size;
624 rec->voices = subs->runtime->channels;
625 rec->loop_start[0] = rec->offset + LOOP_BLANK_SIZE;
626 if (rec->voices > 1)
627 rec->loop_start[1] = rec->loop_start[0] + rec->buf_size + LOOP_BLANK_SIZE;
628 if (rec->voices > 1) {
629 rec->panning[0] = 0xff;
630 rec->panning[1] = 0x00;
631 } else
632 rec->panning[0] = 0x80;
633
634 if (! rec->dram_opened) {
635 int err, i, ch;
636
637 snd_emux_terminate_all(rec->emu->emu);
638 if ((err = emu8k_open_dram_for_pcm(rec->emu, rec->voices)) != 0)
639 return err;
640 rec->dram_opened = 1;
641
642 /* clear loop blanks */
643 snd_emu8000_write_wait(rec->emu, 0);
644 EMU8000_SMALW_WRITE(rec->emu, rec->offset);
645 for (i = 0; i < LOOP_BLANK_SIZE; i++)
646 EMU8000_SMLD_WRITE(rec->emu, 0);
647 for (ch = 0; ch < rec->voices; ch++) {
648 EMU8000_SMALW_WRITE(rec->emu, rec->loop_start[ch] + rec->buf_size);
649 for (i = 0; i < LOOP_BLANK_SIZE; i++)
650 EMU8000_SMLD_WRITE(rec->emu, 0);
651 }
652 }
653
654 setup_voice(rec, 0);
655 if (rec->voices > 1)
656 setup_voice(rec, 1);
657 return 0;
658}
659
660static snd_pcm_uframes_t emu8k_pcm_pointer(snd_pcm_substream_t *subs)
661{
662 emu8k_pcm_t *rec = subs->runtime->private_data;
663 if (rec->running)
664 return emu8k_get_curpos(rec, 0);
665 return 0;
666}
667
668
669static snd_pcm_ops_t emu8k_pcm_ops = {
670 .open = emu8k_pcm_open,
671 .close = emu8k_pcm_close,
672 .ioctl = snd_pcm_lib_ioctl,
673 .hw_params = emu8k_pcm_hw_params,
674 .hw_free = emu8k_pcm_hw_free,
675 .prepare = emu8k_pcm_prepare,
676 .trigger = emu8k_pcm_trigger,
677 .pointer = emu8k_pcm_pointer,
678 .copy = emu8k_pcm_copy,
679 .silence = emu8k_pcm_silence,
680};
681
682
683static void snd_emu8000_pcm_free(snd_pcm_t *pcm)
684{
685 emu8000_t *emu = pcm->private_data;
686 emu->pcm = NULL;
687}
688
689int snd_emu8000_pcm_new(snd_card_t *card, emu8000_t *emu, int index)
690{
691 snd_pcm_t *pcm;
692 int err;
693
694 if ((err = snd_pcm_new(card, "Emu8000 PCM", index, 1, 0, &pcm)) < 0)
695 return err;
696 pcm->private_data = emu;
697 pcm->private_free = snd_emu8000_pcm_free;
698 snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &emu8k_pcm_ops);
699 emu->pcm = pcm;
700
701 snd_device_register(card, pcm);
702
703 return 0;
704}
diff --git a/sound/isa/sb/emu8000_synth.c b/sound/isa/sb/emu8000_synth.c
new file mode 100644
index 000000000000..1f63aa52d596
--- /dev/null
+++ b/sound/isa/sb/emu8000_synth.c
@@ -0,0 +1,134 @@
1/*
2 * Copyright (c) by Jaroslav Kysela <perex@suse.cz>
3 * and (c) 1999 Steve Ratcliffe <steve@parabola.demon.co.uk>
4 * Copyright (C) 1999-2000 Takashi Iwai <tiwai@suse.de>
5 *
6 * Emu8000 synth plug-in routine
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21 */
22
23#include "emu8000_local.h"
24#include <linux/init.h>
25#include <sound/initval.h>
26
27MODULE_AUTHOR("Takashi Iwai, Steve Ratcliffe");
28MODULE_DESCRIPTION("Emu8000 synth plug-in routine");
29MODULE_LICENSE("GPL");
30
31/*----------------------------------------------------------------*/
32
33/*
34 * create a new hardware dependent device for Emu8000
35 */
36static int snd_emu8000_new_device(snd_seq_device_t *dev)
37{
38 emu8000_t *hw;
39 snd_emux_t *emu;
40
41 hw = *(emu8000_t**)SNDRV_SEQ_DEVICE_ARGPTR(dev);
42 if (hw == NULL)
43 return -EINVAL;
44
45 if (hw->emu)
46 return -EBUSY; /* already exists..? */
47
48 if (snd_emux_new(&emu) < 0)
49 return -ENOMEM;
50
51 hw->emu = emu;
52 snd_emu8000_ops_setup(hw);
53
54 emu->hw = hw;
55 emu->max_voices = EMU8000_DRAM_VOICES;
56 emu->num_ports = hw->seq_ports;
57
58 if (hw->memhdr) {
59 snd_printk("memhdr is already initialized!?\n");
60 snd_util_memhdr_free(hw->memhdr);
61 }
62 hw->memhdr = snd_util_memhdr_new(hw->mem_size);
63 if (hw->memhdr == NULL) {
64 snd_emux_free(emu);
65 hw->emu = NULL;
66 return -ENOMEM;
67 }
68
69 emu->memhdr = hw->memhdr;
70 emu->midi_ports = hw->seq_ports < 2 ? hw->seq_ports : 2; /* number of virmidi ports */
71 emu->midi_devidx = 1;
72 emu->linear_panning = 1;
73 emu->hwdep_idx = 2; /* FIXED */
74
75 if (snd_emux_register(emu, dev->card, hw->index, "Emu8000") < 0) {
76 snd_emux_free(emu);
77 snd_util_memhdr_free(hw->memhdr);
78 hw->emu = NULL;
79 hw->memhdr = NULL;
80 return -ENOMEM;
81 }
82
83 if (hw->mem_size > 0)
84 snd_emu8000_pcm_new(dev->card, hw, 1);
85
86 dev->driver_data = hw;
87
88 return 0;
89}
90
91
92/*
93 * free all resources
94 */
95static int snd_emu8000_delete_device(snd_seq_device_t *dev)
96{
97 emu8000_t *hw;
98
99 if (dev->driver_data == NULL)
100 return 0; /* no synth was allocated actually */
101
102 hw = dev->driver_data;
103 if (hw->pcm)
104 snd_device_free(dev->card, hw->pcm);
105 if (hw->emu)
106 snd_emux_free(hw->emu);
107 if (hw->memhdr)
108 snd_util_memhdr_free(hw->memhdr);
109 hw->emu = NULL;
110 hw->memhdr = NULL;
111 return 0;
112}
113
114/*
115 * INIT part
116 */
117
118static int __init alsa_emu8000_init(void)
119{
120
121 static snd_seq_dev_ops_t ops = {
122 snd_emu8000_new_device,
123 snd_emu8000_delete_device,
124 };
125 return snd_seq_device_register_driver(SNDRV_SEQ_DEV_ID_EMU8000, &ops, sizeof(emu8000_t*));
126}
127
128static void __exit alsa_emu8000_exit(void)
129{
130 snd_seq_device_unregister_driver(SNDRV_SEQ_DEV_ID_EMU8000);
131}
132
133module_init(alsa_emu8000_init)
134module_exit(alsa_emu8000_exit)
diff --git a/sound/isa/sb/es968.c b/sound/isa/sb/es968.c
new file mode 100644
index 000000000000..c859917c14db
--- /dev/null
+++ b/sound/isa/sb/es968.c
@@ -0,0 +1,235 @@
1
2/*
3 card-es968.c - driver for ESS AudioDrive ES968 based soundcards.
4 Copyright (C) 1999 by Massimo Piccioni <dafastidio@libero.it>
5
6 Thanks to Pierfrancesco 'qM2' Passerini.
7
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 2 of the License, or
11 (at your option) any later version.
12
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
17
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21*/
22
23#include <sound/driver.h>
24#include <linux/init.h>
25#include <linux/time.h>
26#include <linux/pnp.h>
27#include <linux/moduleparam.h>
28#include <sound/core.h>
29#include <sound/initval.h>
30#include <sound/sb.h>
31
32#define PFX "es968: "
33
34MODULE_AUTHOR("Massimo Piccioni <dafastidio@libero.it>");
35MODULE_DESCRIPTION("ESS AudioDrive ES968");
36MODULE_LICENSE("GPL");
37MODULE_SUPPORTED_DEVICE("{{ESS,AudioDrive ES968}}");
38
39static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-MAX */
40static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* ID for this card */
41static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_ISAPNP; /* Enable this card */
42static long port[SNDRV_CARDS] = SNDRV_DEFAULT_PORT; /* PnP setup */
43static int irq[SNDRV_CARDS] = SNDRV_DEFAULT_IRQ; /* Pnp setup */
44static int dma8[SNDRV_CARDS] = SNDRV_DEFAULT_DMA; /* PnP setup */
45
46module_param_array(index, int, NULL, 0444);
47MODULE_PARM_DESC(index, "Index value for es968 based soundcard.");
48module_param_array(id, charp, NULL, 0444);
49MODULE_PARM_DESC(id, "ID string for es968 based soundcard.");
50module_param_array(enable, bool, NULL, 0444);
51MODULE_PARM_DESC(enable, "Enable es968 based soundcard.");
52module_param_array(port, long, NULL, 0444);
53MODULE_PARM_DESC(port, "Port # for es968 driver.");
54module_param_array(irq, int, NULL, 0444);
55MODULE_PARM_DESC(irq, "IRQ # for es968 driver.");
56module_param_array(dma8, int, NULL, 0444);
57MODULE_PARM_DESC(dma8, "8-bit DMA # for es968 driver.");
58
59struct snd_card_es968 {
60 struct pnp_dev *dev;
61};
62
63static struct pnp_card_device_id snd_es968_pnpids[] = {
64 { .id = "ESS0968", .devs = { { "@@@0968" }, } },
65 { .id = "", } /* end */
66};
67
68MODULE_DEVICE_TABLE(pnp_card, snd_es968_pnpids);
69
70#define DRIVER_NAME "snd-card-es968"
71
72static irqreturn_t snd_card_es968_interrupt(int irq, void *dev_id,
73 struct pt_regs *regs)
74{
75 sb_t *chip = dev_id;
76
77 if (chip->open & SB_OPEN_PCM) {
78 return snd_sb8dsp_interrupt(chip);
79 } else {
80 return snd_sb8dsp_midi_interrupt(chip);
81 }
82}
83
84static int __devinit snd_card_es968_pnp(int dev, struct snd_card_es968 *acard,
85 struct pnp_card_link *card,
86 const struct pnp_card_device_id *id)
87{
88 struct pnp_dev *pdev;
89 struct pnp_resource_table *cfg = kmalloc(sizeof(*cfg), GFP_KERNEL);
90 int err;
91 if (!cfg)
92 return -ENOMEM;
93 acard->dev = pnp_request_card_device(card, id->devs[0].id, NULL);
94 if (acard->dev == NULL) {
95 kfree(cfg);
96 return -ENODEV;
97 }
98
99 pdev = acard->dev;
100
101 pnp_init_resource_table(cfg);
102
103 /* override resources */
104 if (port[dev] != SNDRV_AUTO_PORT)
105 pnp_resource_change(&cfg->port_resource[0], port[dev], 16);
106 if (dma8[dev] != SNDRV_AUTO_DMA)
107 pnp_resource_change(&cfg->dma_resource[0], dma8[dev], 1);
108 if (irq[dev] != SNDRV_AUTO_IRQ)
109 pnp_resource_change(&cfg->irq_resource[0], irq[dev], 1);
110 if ((pnp_manual_config_dev(pdev, cfg, 0)) < 0)
111 snd_printk(KERN_ERR PFX "AUDIO the requested resources are invalid, using auto config\n");
112 err = pnp_activate_dev(pdev);
113 if (err < 0) {
114 snd_printk(KERN_ERR PFX "AUDIO pnp configure failure\n");
115 kfree(cfg);
116 return err;
117 }
118 port[dev] = pnp_port_start(pdev, 0);
119 dma8[dev] = pnp_dma(pdev, 1);
120 irq[dev] = pnp_irq(pdev, 0);
121
122 kfree(cfg);
123 return 0;
124}
125
126static int __init snd_card_es968_probe(int dev,
127 struct pnp_card_link *pcard,
128 const struct pnp_card_device_id *pid)
129{
130 int error;
131 sb_t *chip;
132 snd_card_t *card;
133 struct snd_card_es968 *acard;
134
135 if ((card = snd_card_new(index[dev], id[dev], THIS_MODULE,
136 sizeof(struct snd_card_es968))) == NULL)
137 return -ENOMEM;
138 acard = (struct snd_card_es968 *)card->private_data;
139 if ((error = snd_card_es968_pnp(dev, acard, pcard, pid))) {
140 snd_card_free(card);
141 return error;
142 }
143 snd_card_set_dev(card, &pcard->card->dev);
144
145 if ((error = snd_sbdsp_create(card, port[dev],
146 irq[dev],
147 snd_card_es968_interrupt,
148 dma8[dev],
149 -1,
150 SB_HW_AUTO, &chip)) < 0) {
151 snd_card_free(card);
152 return error;
153 }
154
155 if ((error = snd_sb8dsp_pcm(chip, 0, NULL)) < 0) {
156 snd_card_free(card);
157 return error;
158 }
159
160 if ((error = snd_sbmixer_new(chip)) < 0) {
161 snd_card_free(card);
162 return error;
163 }
164
165 if ((error = snd_sb8dsp_midi(chip, 0, NULL)) < 0) {
166 snd_card_free(card);
167 return error;
168 }
169
170 strcpy(card->driver, "ES968");
171 strcpy(card->shortname, "ESS ES968");
172 sprintf(card->longname, "%s soundcard, %s at 0x%lx, irq %d, dma %d",
173 card->shortname, chip->name, chip->port, irq[dev], dma8[dev]);
174
175 if ((error = snd_card_register(card)) < 0) {
176 snd_card_free(card);
177 return error;
178 }
179 pnp_set_card_drvdata(pcard, card);
180 return 0;
181}
182
183static int __devinit snd_es968_pnp_detect(struct pnp_card_link *card,
184 const struct pnp_card_device_id *id)
185{
186 static int dev;
187 int res;
188
189 for ( ; dev < SNDRV_CARDS; dev++) {
190 if (!enable[dev])
191 continue;
192 res = snd_card_es968_probe(dev, card, id);
193 if (res < 0)
194 return res;
195 dev++;
196 return 0;
197 }
198 return -ENODEV;
199}
200
201static void __devexit snd_es968_pnp_remove(struct pnp_card_link * pcard)
202{
203 snd_card_t *card = (snd_card_t *) pnp_get_card_drvdata(pcard);
204
205 snd_card_disconnect(card);
206 snd_card_free_in_thread(card);
207}
208
209static struct pnp_card_driver es968_pnpc_driver = {
210 .flags = PNP_DRIVER_RES_DISABLE,
211 .name = "es968",
212 .id_table = snd_es968_pnpids,
213 .probe = snd_es968_pnp_detect,
214 .remove = __devexit_p(snd_es968_pnp_remove),
215};
216
217static int __init alsa_card_es968_init(void)
218{
219 int cards = pnp_register_card_driver(&es968_pnpc_driver);
220#ifdef MODULE
221 if (cards == 0) {
222 pnp_unregister_card_driver(&es968_pnpc_driver);
223 snd_printk(KERN_ERR "no ES968 based soundcards found\n");
224 }
225#endif
226 return cards ? 0 : -ENODEV;
227}
228
229static void __exit alsa_card_es968_exit(void)
230{
231 pnp_unregister_card_driver(&es968_pnpc_driver);
232}
233
234module_init(alsa_card_es968_init)
235module_exit(alsa_card_es968_exit)
diff --git a/sound/isa/sb/sb16.c b/sound/isa/sb/sb16.c
new file mode 100644
index 000000000000..60e2c53c49fc
--- /dev/null
+++ b/sound/isa/sb/sb16.c
@@ -0,0 +1,678 @@
1/*
2 * Driver for SoundBlaster 16/AWE32/AWE64 soundcards
3 * Copyright (c) by Jaroslav Kysela <perex@suse.cz>
4 *
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 *
20 */
21
22#include <sound/driver.h>
23#include <asm/dma.h>
24#include <linux/init.h>
25#include <linux/slab.h>
26#include <linux/pnp.h>
27#include <linux/moduleparam.h>
28#include <sound/core.h>
29#include <sound/sb.h>
30#include <sound/sb16_csp.h>
31#include <sound/mpu401.h>
32#include <sound/opl3.h>
33#include <sound/emu8000.h>
34#include <sound/seq_device.h>
35#define SNDRV_LEGACY_AUTO_PROBE
36#define SNDRV_LEGACY_FIND_FREE_IRQ
37#define SNDRV_LEGACY_FIND_FREE_DMA
38#include <sound/initval.h>
39
40#ifdef SNDRV_SBAWE
41#define PFX "sbawe: "
42#else
43#define PFX "sb16: "
44#endif
45
46MODULE_AUTHOR("Jaroslav Kysela <perex@suse.cz>");
47MODULE_LICENSE("GPL");
48#ifndef SNDRV_SBAWE
49MODULE_DESCRIPTION("Sound Blaster 16");
50MODULE_SUPPORTED_DEVICE("{{Creative Labs,SB 16},"
51 "{Creative Labs,SB Vibra16S},"
52 "{Creative Labs,SB Vibra16C},"
53 "{Creative Labs,SB Vibra16CL},"
54 "{Creative Labs,SB Vibra16X}}");
55#else
56MODULE_DESCRIPTION("Sound Blaster AWE");
57MODULE_SUPPORTED_DEVICE("{{Creative Labs,SB AWE 32},"
58 "{Creative Labs,SB AWE 64},"
59 "{Creative Labs,SB AWE 64 Gold}}");
60#endif
61
62#if 0
63#define SNDRV_DEBUG_IRQ
64#endif
65
66#if defined(SNDRV_SBAWE) && (defined(CONFIG_SND_SEQUENCER) || (defined(MODULE) && defined(CONFIG_SND_SEQUENCER_MODULE)))
67#define SNDRV_SBAWE_EMU8000
68#endif
69
70static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-MAX */
71static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* ID for this card */
72static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_ISAPNP; /* Enable this card */
73#ifdef CONFIG_PNP
74static int isapnp[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 1};
75#endif
76static long port[SNDRV_CARDS] = SNDRV_DEFAULT_PORT; /* 0x220,0x240,0x260,0x280 */
77static long mpu_port[SNDRV_CARDS] = SNDRV_DEFAULT_PORT; /* 0x330,0x300 */
78static long fm_port[SNDRV_CARDS] = SNDRV_DEFAULT_PORT;
79#ifdef SNDRV_SBAWE_EMU8000
80static long awe_port[SNDRV_CARDS] = SNDRV_DEFAULT_PORT;
81#endif
82static int irq[SNDRV_CARDS] = SNDRV_DEFAULT_IRQ; /* 5,7,9,10 */
83static int dma8[SNDRV_CARDS] = SNDRV_DEFAULT_DMA; /* 0,1,3 */
84static int dma16[SNDRV_CARDS] = SNDRV_DEFAULT_DMA; /* 5,6,7 */
85static int mic_agc[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 1};
86#ifdef CONFIG_SND_SB16_CSP
87static int csp[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 0};
88#endif
89#ifdef SNDRV_SBAWE_EMU8000
90static int seq_ports[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 4};
91#endif
92
93module_param_array(index, int, NULL, 0444);
94MODULE_PARM_DESC(index, "Index value for SoundBlaster 16 soundcard.");
95module_param_array(id, charp, NULL, 0444);
96MODULE_PARM_DESC(id, "ID string for SoundBlaster 16 soundcard.");
97module_param_array(enable, bool, NULL, 0444);
98MODULE_PARM_DESC(enable, "Enable SoundBlaster 16 soundcard.");
99#ifdef CONFIG_PNP
100module_param_array(isapnp, bool, NULL, 0444);
101MODULE_PARM_DESC(isapnp, "PnP detection for specified soundcard.");
102#endif
103module_param_array(port, long, NULL, 0444);
104MODULE_PARM_DESC(port, "Port # for SB16 driver.");
105module_param_array(mpu_port, long, NULL, 0444);
106MODULE_PARM_DESC(mpu_port, "MPU-401 port # for SB16 driver.");
107module_param_array(fm_port, long, NULL, 0444);
108MODULE_PARM_DESC(fm_port, "FM port # for SB16 PnP driver.");
109#ifdef SNDRV_SBAWE_EMU8000
110module_param_array(awe_port, long, NULL, 0444);
111MODULE_PARM_DESC(awe_port, "AWE port # for SB16 PnP driver.");
112#endif
113module_param_array(irq, int, NULL, 0444);
114MODULE_PARM_DESC(irq, "IRQ # for SB16 driver.");
115module_param_array(dma8, int, NULL, 0444);
116MODULE_PARM_DESC(dma8, "8-bit DMA # for SB16 driver.");
117module_param_array(dma16, int, NULL, 0444);
118MODULE_PARM_DESC(dma16, "16-bit DMA # for SB16 driver.");
119module_param_array(mic_agc, int, NULL, 0444);
120MODULE_PARM_DESC(mic_agc, "Mic Auto-Gain-Control switch.");
121#ifdef CONFIG_SND_SB16_CSP
122module_param_array(csp, int, NULL, 0444);
123MODULE_PARM_DESC(csp, "ASP/CSP chip support.");
124#endif
125#ifdef SNDRV_SBAWE_EMU8000
126module_param_array(seq_ports, int, NULL, 0444);
127MODULE_PARM_DESC(seq_ports, "Number of sequencer ports for WaveTable synth.");
128#endif
129
130struct snd_card_sb16 {
131 struct resource *fm_res; /* used to block FM i/o region for legacy cards */
132#ifdef CONFIG_PNP
133 int dev_no;
134 struct pnp_dev *dev;
135#ifdef SNDRV_SBAWE_EMU8000
136 struct pnp_dev *devwt;
137#endif
138#endif
139};
140
141static snd_card_t *snd_sb16_legacy[SNDRV_CARDS] = SNDRV_DEFAULT_PTR;
142
143#ifdef CONFIG_PNP
144
145static struct pnp_card_device_id snd_sb16_pnpids[] = {
146#ifndef SNDRV_SBAWE
147 /* Sound Blaster 16 PnP */
148 { .id = "CTL0024", .devs = { { "CTL0031" } } },
149 /* Sound Blaster 16 PnP */
150 { .id = "CTL0025", .devs = { { "CTL0031" } } },
151 /* Sound Blaster 16 PnP */
152 { .id = "CTL0026", .devs = { { "CTL0031" } } },
153 /* Sound Blaster 16 PnP */
154 { .id = "CTL0027", .devs = { { "CTL0031" } } },
155 /* Sound Blaster 16 PnP */
156 { .id = "CTL0028", .devs = { { "CTL0031" } } },
157 /* Sound Blaster 16 PnP */
158 { .id = "CTL0029", .devs = { { "CTL0031" } } },
159 /* Sound Blaster 16 PnP */
160 { .id = "CTL002a", .devs = { { "CTL0031" } } },
161 /* Sound Blaster 16 PnP */
162 /* Note: This card has also a CTL0051:StereoEnhance device!!! */
163 { .id = "CTL002b", .devs = { { "CTL0031" } } },
164 /* Sound Blaster 16 PnP */
165 { .id = "CTL002c", .devs = { { "CTL0031" } } },
166 /* Sound Blaster Vibra16S */
167 { .id = "CTL0051", .devs = { { "CTL0001" } } },
168 /* Sound Blaster Vibra16C */
169 { .id = "CTL0070", .devs = { { "CTL0001" } } },
170 /* Sound Blaster Vibra16CL - added by ctm@ardi.com */
171 { .id = "CTL0080", .devs = { { "CTL0041" } } },
172 /* Sound Blaster 16 'value' PnP. It says model ct4130 on the pcb, */
173 /* but ct4131 on a sticker on the board.. */
174 { .id = "CTL0086", .devs = { { "CTL0041" } } },
175 /* Sound Blaster Vibra16X */
176 { .id = "CTL00f0", .devs = { { "CTL0043" } } },
177#else /* SNDRV_SBAWE defined */
178 /* Sound Blaster AWE 32 PnP */
179 { .id = "CTL0035", .devs = { { "CTL0031" }, { "CTL0021" } } },
180 /* Sound Blaster AWE 32 PnP */
181 { .id = "CTL0039", .devs = { { "CTL0031" }, { "CTL0021" } } },
182 /* Sound Blaster AWE 32 PnP */
183 { .id = "CTL0042", .devs = { { "CTL0031" }, { "CTL0021" } } },
184 /* Sound Blaster AWE 32 PnP */
185 { .id = "CTL0043", .devs = { { "CTL0031" }, { "CTL0021" } } },
186 /* Sound Blaster AWE 32 PnP */
187 /* Note: This card has also a CTL0051:StereoEnhance device!!! */
188 { .id = "CTL0044", .devs = { { "CTL0031" }, { "CTL0021" } } },
189 /* Sound Blaster AWE 32 PnP */
190 /* Note: This card has also a CTL0051:StereoEnhance device!!! */
191 { .id = "CTL0045", .devs = { { "CTL0031" }, { "CTL0021" } } },
192 /* Sound Blaster AWE 32 PnP */
193 { .id = "CTL0046", .devs = { { "CTL0031" }, { "CTL0021" } } },
194 /* Sound Blaster AWE 32 PnP */
195 { .id = "CTL0047", .devs = { { "CTL0031" }, { "CTL0021" } } },
196 /* Sound Blaster AWE 32 PnP */
197 { .id = "CTL0048", .devs = { { "CTL0031" }, { "CTL0021" } } },
198 /* Sound Blaster AWE 32 PnP */
199 { .id = "CTL0054", .devs = { { "CTL0031" }, { "CTL0021" } } },
200 /* Sound Blaster AWE 32 PnP */
201 { .id = "CTL009a", .devs = { { "CTL0041" }, { "CTL0021" } } },
202 /* Sound Blaster AWE 32 PnP */
203 { .id = "CTL009c", .devs = { { "CTL0041" }, { "CTL0021" } } },
204 /* Sound Blaster 32 PnP */
205 { .id = "CTL009f", .devs = { { "CTL0041" }, { "CTL0021" } } },
206 /* Sound Blaster AWE 64 PnP */
207 { .id = "CTL009d", .devs = { { "CTL0042" }, { "CTL0022" } } },
208 /* Sound Blaster AWE 64 PnP Gold */
209 { .id = "CTL009e", .devs = { { "CTL0044" }, { "CTL0023" } } },
210 /* Sound Blaster AWE 64 PnP Gold */
211 { .id = "CTL00b2", .devs = { { "CTL0044" }, { "CTL0023" } } },
212 /* Sound Blaster AWE 64 PnP */
213 { .id = "CTL00c1", .devs = { { "CTL0042" }, { "CTL0022" } } },
214 /* Sound Blaster AWE 64 PnP */
215 { .id = "CTL00c3", .devs = { { "CTL0045" }, { "CTL0022" } } },
216 /* Sound Blaster AWE 64 PnP */
217 { .id = "CTL00c5", .devs = { { "CTL0045" }, { "CTL0022" } } },
218 /* Sound Blaster AWE 64 PnP */
219 { .id = "CTL00c7", .devs = { { "CTL0045" }, { "CTL0022" } } },
220 /* Sound Blaster AWE 64 PnP */
221 { .id = "CTL00e4", .devs = { { "CTL0045" }, { "CTL0022" } } },
222 /* Sound Blaster AWE 64 PnP */
223 { .id = "CTL00e9", .devs = { { "CTL0045" }, { "CTL0022" } } },
224 /* Sound Blaster 16 PnP (AWE) */
225 { .id = "CTL00ed", .devs = { { "CTL0041" }, { "CTL0070" } } },
226 /* Generic entries */
227 { .id = "CTLXXXX" , .devs = { { "CTL0031" }, { "CTL0021" } } },
228 { .id = "CTLXXXX" , .devs = { { "CTL0041" }, { "CTL0021" } } },
229 { .id = "CTLXXXX" , .devs = { { "CTL0042" }, { "CTL0022" } } },
230 { .id = "CTLXXXX" , .devs = { { "CTL0044" }, { "CTL0023" } } },
231 { .id = "CTLXXXX" , .devs = { { "CTL0045" }, { "CTL0022" } } },
232#endif /* SNDRV_SBAWE */
233 /* Sound Blaster 16 PnP (Virtual PC 2004)*/
234 { .id = "tBA03b0", .devs = { { "PNPb003" } } },
235 { .id = "", }
236};
237
238MODULE_DEVICE_TABLE(pnp_card, snd_sb16_pnpids);
239
240#endif /* CONFIG_PNP */
241
242#ifdef SNDRV_SBAWE_EMU8000
243#define DRIVER_NAME "snd-card-sbawe"
244#else
245#define DRIVER_NAME "snd-card-sb16"
246#endif
247
248#ifdef CONFIG_PNP
249
250static int __devinit snd_card_sb16_pnp(int dev, struct snd_card_sb16 *acard,
251 struct pnp_card_link *card,
252 const struct pnp_card_device_id *id)
253{
254 struct pnp_dev *pdev;
255 struct pnp_resource_table * cfg = kmalloc(sizeof(struct pnp_resource_table), GFP_KERNEL);
256 int err;
257
258 if (!cfg)
259 return -ENOMEM;
260 acard->dev = pnp_request_card_device(card, id->devs[0].id, NULL);
261 if (acard->dev == NULL) {
262 kfree(cfg);
263 return -ENODEV;
264 }
265#ifdef SNDRV_SBAWE_EMU8000
266 acard->devwt = pnp_request_card_device(card, id->devs[1].id, acard->dev);
267#endif
268 /* Audio initialization */
269 pdev = acard->dev;
270
271 pnp_init_resource_table(cfg);
272
273 /* override resources */
274
275 if (port[dev] != SNDRV_AUTO_PORT)
276 pnp_resource_change(&cfg->port_resource[0], port[dev], 16);
277 if (mpu_port[dev] != SNDRV_AUTO_PORT)
278 pnp_resource_change(&cfg->port_resource[1], mpu_port[dev], 2);
279 if (fm_port[dev] != SNDRV_AUTO_PORT)
280 pnp_resource_change(&cfg->port_resource[2], fm_port[dev], 4);
281 if (dma8[dev] != SNDRV_AUTO_DMA)
282 pnp_resource_change(&cfg->dma_resource[0], dma8[dev], 1);
283 if (dma16[dev] != SNDRV_AUTO_DMA)
284 pnp_resource_change(&cfg->dma_resource[1], dma16[dev], 1);
285 if (irq[dev] != SNDRV_AUTO_IRQ)
286 pnp_resource_change(&cfg->irq_resource[0], irq[dev], 1);
287 if (pnp_manual_config_dev(pdev, cfg, 0) < 0)
288 snd_printk(KERN_ERR PFX "AUDIO the requested resources are invalid, using auto config\n");
289 err = pnp_activate_dev(pdev);
290 if (err < 0) {
291 snd_printk(KERN_ERR PFX "AUDIO pnp configure failure\n");
292 kfree(cfg);
293 return err;
294 }
295 port[dev] = pnp_port_start(pdev, 0);
296 mpu_port[dev] = pnp_port_start(pdev, 1);
297 fm_port[dev] = pnp_port_start(pdev, 2);
298 dma8[dev] = pnp_dma(pdev, 0);
299 dma16[dev] = pnp_dma(pdev, 1);
300 irq[dev] = pnp_irq(pdev, 0);
301 snd_printdd("pnp SB16: port=0x%lx, mpu port=0x%lx, fm port=0x%lx\n",
302 port[dev], mpu_port[dev], fm_port[dev]);
303 snd_printdd("pnp SB16: dma1=%i, dma2=%i, irq=%i\n",
304 dma8[dev], dma16[dev], irq[dev]);
305#ifdef SNDRV_SBAWE_EMU8000
306 /* WaveTable initialization */
307 pdev = acard->devwt;
308 if (pdev != NULL) {
309 pnp_init_resource_table(cfg);
310
311 /* override resources */
312
313 if (awe_port[dev] != SNDRV_AUTO_PORT) {
314 pnp_resource_change(&cfg->port_resource[0], awe_port[dev], 4);
315 pnp_resource_change(&cfg->port_resource[1], awe_port[dev] + 0x400, 4);
316 pnp_resource_change(&cfg->port_resource[2], awe_port[dev] + 0x800, 4);
317 }
318 if ((pnp_manual_config_dev(pdev, cfg, 0)) < 0)
319 snd_printk(KERN_ERR PFX "WaveTable the requested resources are invalid, using auto config\n");
320 err = pnp_activate_dev(pdev);
321 if (err < 0) {
322 goto __wt_error;
323 }
324 awe_port[dev] = pnp_port_start(pdev, 0);
325 snd_printdd("pnp SB16: wavetable port=0x%lx\n", pnp_port_start(pdev, 0));
326 } else {
327__wt_error:
328 if (pdev) {
329 pnp_release_card_device(pdev);
330 snd_printk(KERN_ERR PFX "WaveTable pnp configure failure\n");
331 }
332 acard->devwt = NULL;
333 awe_port[dev] = -1;
334 }
335#endif
336 kfree(cfg);
337 return 0;
338}
339
340#endif /* CONFIG_PNP */
341
342static void snd_sb16_free(snd_card_t *card)
343{
344 struct snd_card_sb16 *acard = (struct snd_card_sb16 *)card->private_data;
345
346 if (acard == NULL)
347 return;
348 if (acard->fm_res) {
349 release_resource(acard->fm_res);
350 kfree_nocheck(acard->fm_res);
351 }
352}
353
354static int __init snd_sb16_probe(int dev,
355 struct pnp_card_link *pcard,
356 const struct pnp_card_device_id *pid)
357{
358 static int possible_irqs[] = {5, 9, 10, 7, -1};
359 static int possible_dmas8[] = {1, 3, 0, -1};
360 static int possible_dmas16[] = {5, 6, 7, -1};
361 int xirq, xdma8, xdma16;
362 sb_t *chip;
363 snd_card_t *card;
364 struct snd_card_sb16 *acard;
365 opl3_t *opl3;
366 snd_hwdep_t *synth = NULL;
367#ifdef CONFIG_SND_SB16_CSP
368 snd_hwdep_t *xcsp = NULL;
369#endif
370 unsigned long flags;
371 int err;
372
373 card = snd_card_new(index[dev], id[dev], THIS_MODULE,
374 sizeof(struct snd_card_sb16));
375 if (card == NULL)
376 return -ENOMEM;
377 acard = (struct snd_card_sb16 *) card->private_data;
378 card->private_free = snd_sb16_free;
379#ifdef CONFIG_PNP
380 if (isapnp[dev]) {
381 if ((err = snd_card_sb16_pnp(dev, acard, pcard, pid))) {
382 snd_card_free(card);
383 return err;
384 }
385 snd_card_set_dev(card, &pcard->card->dev);
386 }
387#endif
388
389 xirq = irq[dev];
390 xdma8 = dma8[dev];
391 xdma16 = dma16[dev];
392#ifdef CONFIG_PNP
393 if (!isapnp[dev]) {
394#endif
395 if (xirq == SNDRV_AUTO_IRQ) {
396 if ((xirq = snd_legacy_find_free_irq(possible_irqs)) < 0) {
397 snd_card_free(card);
398 snd_printk(KERN_ERR PFX "unable to find a free IRQ\n");
399 return -EBUSY;
400 }
401 }
402 if (xdma8 == SNDRV_AUTO_DMA) {
403 if ((xdma8 = snd_legacy_find_free_dma(possible_dmas8)) < 0) {
404 snd_card_free(card);
405 snd_printk(KERN_ERR PFX "unable to find a free 8-bit DMA\n");
406 return -EBUSY;
407 }
408 }
409 if (xdma16 == SNDRV_AUTO_DMA) {
410 if ((xdma16 = snd_legacy_find_free_dma(possible_dmas16)) < 0) {
411 snd_card_free(card);
412 snd_printk(KERN_ERR PFX "unable to find a free 16-bit DMA\n");
413 return -EBUSY;
414 }
415 }
416 /* non-PnP FM port address is hardwired with base port address */
417 fm_port[dev] = port[dev];
418 /* block the 0x388 port to avoid PnP conflicts */
419 acard->fm_res = request_region(0x388, 4, "SoundBlaster FM");
420#ifdef SNDRV_SBAWE_EMU8000
421 /* non-PnP AWE port address is hardwired with base port address */
422 awe_port[dev] = port[dev] + 0x400;
423#endif
424#ifdef CONFIG_PNP
425 }
426#endif
427
428 if ((err = snd_sbdsp_create(card,
429 port[dev],
430 xirq,
431 snd_sb16dsp_interrupt,
432 xdma8,
433 xdma16,
434 SB_HW_AUTO,
435 &chip)) < 0) {
436 snd_card_free(card);
437 return err;
438 }
439 if (chip->hardware != SB_HW_16) {
440 snd_card_free(card);
441 snd_printdd("SB 16 chip was not detected at 0x%lx\n", port[dev]);
442 return -ENODEV;
443 }
444 chip->mpu_port = mpu_port[dev];
445#ifdef CONFIG_PNP
446 if (!isapnp[dev] && (err = snd_sb16dsp_configure(chip)) < 0) {
447#else
448 if ((err = snd_sb16dsp_configure(chip)) < 0) {
449#endif
450 snd_card_free(card);
451 return -ENXIO;
452 }
453 if ((err = snd_sb16dsp_pcm(chip, 0, NULL)) < 0) {
454 snd_card_free(card);
455 return -ENXIO;
456 }
457
458 strcpy(card->driver,
459#ifdef SNDRV_SBAWE_EMU8000
460 awe_port[dev] > 0 ? "SB AWE" :
461#endif
462 "SB16");
463 strcpy(card->shortname, chip->name);
464 sprintf(card->longname, "%s at 0x%lx, irq %i, dma ",
465 chip->name,
466 chip->port,
467 xirq);
468 if (xdma8 >= 0)
469 sprintf(card->longname + strlen(card->longname), "%d", xdma8);
470 if (xdma16 >= 0)
471 sprintf(card->longname + strlen(card->longname), "%s%d",
472 xdma8 >= 0 ? "&" : "", xdma16);
473
474 if (chip->mpu_port > 0 && chip->mpu_port != SNDRV_AUTO_PORT) {
475 if ((err = snd_mpu401_uart_new(card, 0, MPU401_HW_SB,
476 chip->mpu_port, 0,
477 xirq, 0, &chip->rmidi)) < 0) {
478 snd_card_free(card);
479 return -ENXIO;
480 }
481 chip->rmidi_callback = snd_mpu401_uart_interrupt;
482 }
483
484#ifdef SNDRV_SBAWE_EMU8000
485 if (awe_port[dev] == SNDRV_AUTO_PORT)
486 awe_port[dev] = 0; /* disable */
487#endif
488
489 if (fm_port[dev] > 0 && fm_port[dev] != SNDRV_AUTO_PORT) {
490 if (snd_opl3_create(card, fm_port[dev], fm_port[dev] + 2,
491 OPL3_HW_OPL3,
492 acard->fm_res != NULL || fm_port[dev] == port[dev],
493 &opl3) < 0) {
494 snd_printk(KERN_ERR PFX "no OPL device at 0x%lx-0x%lx\n",
495 fm_port[dev], fm_port[dev] + 2);
496 } else {
497#ifdef SNDRV_SBAWE_EMU8000
498 int seqdev = awe_port[dev] > 0 ? 2 : 1;
499#else
500 int seqdev = 1;
501#endif
502 if ((err = snd_opl3_hwdep_new(opl3, 0, seqdev, &synth)) < 0) {
503 snd_card_free(card);
504 return -ENXIO;
505 }
506 }
507 }
508
509 if ((err = snd_sbmixer_new(chip)) < 0) {
510 snd_card_free(card);
511 return -ENXIO;
512 }
513
514#ifdef CONFIG_SND_SB16_CSP
515 /* CSP chip on SB16ASP/AWE32 */
516 if ((chip->hardware == SB_HW_16) && csp[dev]) {
517 snd_sb_csp_new(chip, synth != NULL ? 1 : 0, &xcsp);
518 if (xcsp) {
519 chip->csp = xcsp->private_data;
520 chip->hardware = SB_HW_16CSP;
521 } else {
522 snd_printk(KERN_INFO PFX "warning - CSP chip not detected on soundcard #%i\n", dev + 1);
523 }
524 }
525#endif
526#ifdef SNDRV_SBAWE_EMU8000
527 if (awe_port[dev] > 0) {
528 if (snd_emu8000_new(card, 1, awe_port[dev],
529 seq_ports[dev], NULL) < 0) {
530 snd_printk(KERN_ERR PFX "fatal error - EMU-8000 synthesizer not detected at 0x%lx\n", awe_port[dev]);
531 snd_card_free(card);
532 return -ENXIO;
533 }
534 }
535#endif
536
537 /* setup Mic AGC */
538 spin_lock_irqsave(&chip->mixer_lock, flags);
539 snd_sbmixer_write(chip, SB_DSP4_MIC_AGC,
540 (snd_sbmixer_read(chip, SB_DSP4_MIC_AGC) & 0x01) |
541 (mic_agc[dev] ? 0x00 : 0x01));
542 spin_unlock_irqrestore(&chip->mixer_lock, flags);
543
544 if ((err = snd_card_register(card)) < 0) {
545 snd_card_free(card);
546 return err;
547 }
548 if (pcard)
549 pnp_set_card_drvdata(pcard, card);
550 else
551 snd_sb16_legacy[dev] = card;
552 return 0;
553}
554
555static int __init snd_sb16_probe_legacy_port(unsigned long xport)
556{
557 static int dev;
558 int res;
559
560 for ( ; dev < SNDRV_CARDS; dev++) {
561 if (!enable[dev] || port[dev] != SNDRV_AUTO_PORT)
562 continue;
563#ifdef CONFIG_PNP
564 if (isapnp[dev])
565 continue;
566#endif
567 port[dev] = xport;
568 res = snd_sb16_probe(dev, NULL, NULL);
569 if (res < 0)
570 port[dev] = SNDRV_AUTO_PORT;
571 return res;
572 }
573 return -ENODEV;
574}
575
576#ifdef CONFIG_PNP
577
578static int __devinit snd_sb16_pnp_detect(struct pnp_card_link *card,
579 const struct pnp_card_device_id *id)
580{
581 static int dev;
582 int res;
583
584 for ( ; dev < SNDRV_CARDS; dev++) {
585 if (!enable[dev] || !isapnp[dev])
586 continue;
587 res = snd_sb16_probe(dev, card, id);
588 if (res < 0)
589 return res;
590 dev++;
591 return 0;
592 }
593
594 return -ENODEV;
595}
596
597static void __devexit snd_sb16_pnp_remove(struct pnp_card_link * pcard)
598{
599 snd_card_t *card = (snd_card_t *) pnp_get_card_drvdata(pcard);
600
601 snd_card_disconnect(card);
602 snd_card_free_in_thread(card);
603}
604
605static struct pnp_card_driver sb16_pnpc_driver = {
606 .flags = PNP_DRIVER_RES_DISABLE,
607 .name = "sb16",
608 .id_table = snd_sb16_pnpids,
609 .probe = snd_sb16_pnp_detect,
610 .remove = __devexit_p(snd_sb16_pnp_remove),
611};
612
613#endif /* CONFIG_PNP */
614
615static int __init alsa_card_sb16_init(void)
616{
617 int dev, cards = 0, i;
618 static unsigned long possible_ports[] = {0x220, 0x240, 0x260, 0x280, -1};
619
620 /* legacy non-auto cards at first */
621 for (dev = 0; dev < SNDRV_CARDS; dev++) {
622 if (!enable[dev] || port[dev] == SNDRV_AUTO_PORT)
623 continue;
624#ifdef CONFIG_PNP
625 if (isapnp[dev])
626 continue;
627#endif
628 if (!snd_sb16_probe(dev, NULL, NULL)) {
629 cards++;
630 continue;
631 }
632#ifdef MODULE
633 snd_printk(KERN_ERR "Sound Blaster 16+ soundcard #%i not found at 0x%lx or device busy\n", dev, port[dev]);
634#endif
635 }
636 /* legacy auto configured cards */
637 i = snd_legacy_auto_probe(possible_ports, snd_sb16_probe_legacy_port);
638 if (i > 0)
639 cards += i;
640
641#ifdef CONFIG_PNP
642 /* PnP cards at last */
643 i = pnp_register_card_driver(&sb16_pnpc_driver);
644 if (i >0)
645 cards += i;
646#endif
647
648 if (!cards) {
649#ifdef CONFIG_PNP
650 pnp_unregister_card_driver(&sb16_pnpc_driver);
651#endif
652#ifdef MODULE
653 snd_printk(KERN_ERR "Sound Blaster 16 soundcard not found or device busy\n");
654#ifdef SNDRV_SBAWE_EMU8000
655 snd_printk(KERN_ERR "In case, if you have non-AWE card, try snd-sb16 module\n");
656#else
657 snd_printk(KERN_ERR "In case, if you have AWE card, try snd-sbawe module\n");
658#endif
659#endif
660 return -ENODEV;
661 }
662 return 0;
663}
664
665static void __exit alsa_card_sb16_exit(void)
666{
667 int dev;
668
669#ifdef CONFIG_PNP
670 /* PnP cards first */
671 pnp_unregister_card_driver(&sb16_pnpc_driver);
672#endif
673 for (dev = 0; dev < SNDRV_CARDS; dev++)
674 snd_card_free(snd_sb16_legacy[dev]);
675}
676
677module_init(alsa_card_sb16_init)
678module_exit(alsa_card_sb16_exit)
diff --git a/sound/isa/sb/sb16_csp.c b/sound/isa/sb/sb16_csp.c
new file mode 100644
index 000000000000..b62920eead3d
--- /dev/null
+++ b/sound/isa/sb/sb16_csp.c
@@ -0,0 +1,1175 @@
1/*
2 * Copyright (c) 1999 by Uros Bizjak <uros@kss-loka.si>
3 * Takashi Iwai <tiwai@suse.de>
4 *
5 * SB16ASP/AWE32 CSP control
6 *
7 * CSP microcode loader:
8 * alsa-tools/sb16_csp/
9 *
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 2 of the License, or
13 * (at your option) any later version.
14 *
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
19 *
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
23 *
24 */
25
26#include <sound/driver.h>
27#include <linux/delay.h>
28#include <linux/init.h>
29#include <linux/slab.h>
30#include <sound/core.h>
31#include <sound/control.h>
32#include <sound/info.h>
33#include <sound/sb16_csp.h>
34#include <sound/initval.h>
35
36MODULE_AUTHOR("Uros Bizjak <uros@kss-loka.si>");
37MODULE_DESCRIPTION("ALSA driver for SB16 Creative Signal Processor");
38MODULE_LICENSE("GPL");
39
40#ifdef SNDRV_LITTLE_ENDIAN
41#define CSP_HDR_VALUE(a,b,c,d) ((a) | ((b)<<8) | ((c)<<16) | ((d)<<24))
42#else
43#define CSP_HDR_VALUE(a,b,c,d) ((d) | ((c)<<8) | ((b)<<16) | ((a)<<24))
44#endif
45#define LE_SHORT(v) le16_to_cpu(v)
46#define LE_INT(v) le32_to_cpu(v)
47
48#define RIFF_HEADER CSP_HDR_VALUE('R', 'I', 'F', 'F')
49#define CSP__HEADER CSP_HDR_VALUE('C', 'S', 'P', ' ')
50#define LIST_HEADER CSP_HDR_VALUE('L', 'I', 'S', 'T')
51#define FUNC_HEADER CSP_HDR_VALUE('f', 'u', 'n', 'c')
52#define CODE_HEADER CSP_HDR_VALUE('c', 'o', 'd', 'e')
53#define INIT_HEADER CSP_HDR_VALUE('i', 'n', 'i', 't')
54#define MAIN_HEADER CSP_HDR_VALUE('m', 'a', 'i', 'n')
55
56/*
57 * RIFF data format
58 */
59typedef struct riff_header {
60 __u32 name;
61 __u32 len;
62} riff_header_t;
63
64typedef struct desc_header {
65 riff_header_t info;
66 __u16 func_nr;
67 __u16 VOC_type;
68 __u16 flags_play_rec;
69 __u16 flags_16bit_8bit;
70 __u16 flags_stereo_mono;
71 __u16 flags_rates;
72} desc_header_t;
73
74/*
75 * prototypes
76 */
77static void snd_sb_csp_free(snd_hwdep_t *hw);
78static int snd_sb_csp_open(snd_hwdep_t * hw, struct file *file);
79static int snd_sb_csp_ioctl(snd_hwdep_t * hw, struct file *file, unsigned int cmd, unsigned long arg);
80static int snd_sb_csp_release(snd_hwdep_t * hw, struct file *file);
81
82static int csp_detect(sb_t *chip, int *version);
83static int set_codec_parameter(sb_t *chip, unsigned char par, unsigned char val);
84static int set_register(sb_t *chip, unsigned char reg, unsigned char val);
85static int read_register(sb_t *chip, unsigned char reg);
86static int set_mode_register(sb_t *chip, unsigned char mode);
87static int get_version(sb_t *chip);
88
89static int snd_sb_csp_riff_load(snd_sb_csp_t * p, snd_sb_csp_microcode_t __user * code);
90static int snd_sb_csp_unload(snd_sb_csp_t * p);
91static int snd_sb_csp_load_user(snd_sb_csp_t * p, const unsigned char __user *buf, int size, int load_flags);
92static int snd_sb_csp_autoload(snd_sb_csp_t * p, int pcm_sfmt, int play_rec_mode);
93static int snd_sb_csp_check_version(snd_sb_csp_t * p);
94
95static int snd_sb_csp_use(snd_sb_csp_t * p);
96static int snd_sb_csp_unuse(snd_sb_csp_t * p);
97static int snd_sb_csp_start(snd_sb_csp_t * p, int sample_width, int channels);
98static int snd_sb_csp_stop(snd_sb_csp_t * p);
99static int snd_sb_csp_pause(snd_sb_csp_t * p);
100static int snd_sb_csp_restart(snd_sb_csp_t * p);
101
102static int snd_sb_qsound_build(snd_sb_csp_t * p);
103static void snd_sb_qsound_destroy(snd_sb_csp_t * p);
104static int snd_sb_csp_qsound_transfer(snd_sb_csp_t * p);
105
106static int init_proc_entry(snd_sb_csp_t * p, int device);
107static void info_read(snd_info_entry_t *entry, snd_info_buffer_t * buffer);
108
109/*
110 * Detect CSP chip and create a new instance
111 */
112int snd_sb_csp_new(sb_t *chip, int device, snd_hwdep_t ** rhwdep)
113{
114 snd_sb_csp_t *p;
115 int version, err;
116 snd_hwdep_t *hw;
117
118 if (rhwdep)
119 *rhwdep = NULL;
120
121 if (csp_detect(chip, &version))
122 return -ENODEV;
123
124 if ((err = snd_hwdep_new(chip->card, "SB16-CSP", device, &hw)) < 0)
125 return err;
126
127 if ((p = kcalloc(1, sizeof(*p), GFP_KERNEL)) == NULL) {
128 snd_device_free(chip->card, hw);
129 return -ENOMEM;
130 }
131 p->chip = chip;
132 p->version = version;
133
134 /* CSP operators */
135 p->ops.csp_use = snd_sb_csp_use;
136 p->ops.csp_unuse = snd_sb_csp_unuse;
137 p->ops.csp_autoload = snd_sb_csp_autoload;
138 p->ops.csp_start = snd_sb_csp_start;
139 p->ops.csp_stop = snd_sb_csp_stop;
140 p->ops.csp_qsound_transfer = snd_sb_csp_qsound_transfer;
141
142 init_MUTEX(&p->access_mutex);
143 sprintf(hw->name, "CSP v%d.%d", (version >> 4), (version & 0x0f));
144 hw->iface = SNDRV_HWDEP_IFACE_SB16CSP;
145 hw->private_data = p;
146 hw->private_free = snd_sb_csp_free;
147
148 /* operators - only write/ioctl */
149 hw->ops.open = snd_sb_csp_open;
150 hw->ops.ioctl = snd_sb_csp_ioctl;
151 hw->ops.release = snd_sb_csp_release;
152
153 /* create a proc entry */
154 init_proc_entry(p, device);
155 if (rhwdep)
156 *rhwdep = hw;
157 return 0;
158}
159
160/*
161 * free_private for hwdep instance
162 */
163static void snd_sb_csp_free(snd_hwdep_t *hwdep)
164{
165 snd_sb_csp_t *p = hwdep->private_data;
166 if (p) {
167 if (p->running & SNDRV_SB_CSP_ST_RUNNING)
168 snd_sb_csp_stop(p);
169 kfree(p);
170 }
171}
172
173/* ------------------------------ */
174
175/*
176 * open the device exclusively
177 */
178static int snd_sb_csp_open(snd_hwdep_t * hw, struct file *file)
179{
180 snd_sb_csp_t *p = hw->private_data;
181 return (snd_sb_csp_use(p));
182}
183
184/*
185 * ioctl for hwdep device:
186 */
187static int snd_sb_csp_ioctl(snd_hwdep_t * hw, struct file *file, unsigned int cmd, unsigned long arg)
188{
189 snd_sb_csp_t *p = hw->private_data;
190 snd_sb_csp_info_t info;
191 snd_sb_csp_start_t start_info;
192 int err;
193
194 snd_assert(p != NULL, return -EINVAL);
195
196 if (snd_sb_csp_check_version(p))
197 return -ENODEV;
198
199 switch (cmd) {
200 /* get information */
201 case SNDRV_SB_CSP_IOCTL_INFO:
202 *info.codec_name = *p->codec_name;
203 info.func_nr = p->func_nr;
204 info.acc_format = p->acc_format;
205 info.acc_channels = p->acc_channels;
206 info.acc_width = p->acc_width;
207 info.acc_rates = p->acc_rates;
208 info.csp_mode = p->mode;
209 info.run_channels = p->run_channels;
210 info.run_width = p->run_width;
211 info.version = p->version;
212 info.state = p->running;
213 if (copy_to_user((void __user *)arg, &info, sizeof(info)))
214 err = -EFAULT;
215 else
216 err = 0;
217 break;
218
219 /* load CSP microcode */
220 case SNDRV_SB_CSP_IOCTL_LOAD_CODE:
221 err = (p->running & SNDRV_SB_CSP_ST_RUNNING ?
222 -EBUSY : snd_sb_csp_riff_load(p, (snd_sb_csp_microcode_t __user *) arg));
223 break;
224 case SNDRV_SB_CSP_IOCTL_UNLOAD_CODE:
225 err = (p->running & SNDRV_SB_CSP_ST_RUNNING ?
226 -EBUSY : snd_sb_csp_unload(p));
227 break;
228
229 /* change CSP running state */
230 case SNDRV_SB_CSP_IOCTL_START:
231 if (copy_from_user(&start_info, (void __user *) arg, sizeof(start_info)))
232 err = -EFAULT;
233 else
234 err = snd_sb_csp_start(p, start_info.sample_width, start_info.channels);
235 break;
236 case SNDRV_SB_CSP_IOCTL_STOP:
237 err = snd_sb_csp_stop(p);
238 break;
239 case SNDRV_SB_CSP_IOCTL_PAUSE:
240 err = snd_sb_csp_pause(p);
241 break;
242 case SNDRV_SB_CSP_IOCTL_RESTART:
243 err = snd_sb_csp_restart(p);
244 break;
245 default:
246 err = -ENOTTY;
247 break;
248 }
249
250 return err;
251}
252
253/*
254 * close the device
255 */
256static int snd_sb_csp_release(snd_hwdep_t * hw, struct file *file)
257{
258 snd_sb_csp_t *p = hw->private_data;
259 return (snd_sb_csp_unuse(p));
260}
261
262/* ------------------------------ */
263
264/*
265 * acquire device
266 */
267static int snd_sb_csp_use(snd_sb_csp_t * p)
268{
269 down(&p->access_mutex);
270 if (p->used) {
271 up(&p->access_mutex);
272 return -EAGAIN;
273 }
274 p->used++;
275 up(&p->access_mutex);
276
277 return 0;
278
279}
280
281/*
282 * release device
283 */
284static int snd_sb_csp_unuse(snd_sb_csp_t * p)
285{
286 down(&p->access_mutex);
287 p->used--;
288 up(&p->access_mutex);
289
290 return 0;
291}
292
293/*
294 * load microcode via ioctl:
295 * code is user-space pointer
296 */
297static int snd_sb_csp_riff_load(snd_sb_csp_t * p, snd_sb_csp_microcode_t __user * mcode)
298{
299 snd_sb_csp_mc_header_t info;
300
301 unsigned char __user *data_ptr;
302 unsigned char __user *data_end;
303 unsigned short func_nr = 0;
304
305 riff_header_t file_h, item_h, code_h;
306 __u32 item_type;
307 desc_header_t funcdesc_h;
308
309 unsigned long flags;
310 int err;
311
312 if (copy_from_user(&info, mcode, sizeof(info)))
313 return -EFAULT;
314 data_ptr = mcode->data;
315
316 if (copy_from_user(&file_h, data_ptr, sizeof(file_h)))
317 return -EFAULT;
318 if ((file_h.name != RIFF_HEADER) ||
319 (LE_INT(file_h.len) >= SNDRV_SB_CSP_MAX_MICROCODE_FILE_SIZE - sizeof(file_h))) {
320 snd_printd("%s: Invalid RIFF header\n", __FUNCTION__);
321 return -EINVAL;
322 }
323 data_ptr += sizeof(file_h);
324 data_end = data_ptr + LE_INT(file_h.len);
325
326 if (copy_from_user(&item_type, data_ptr, sizeof(item_type)))
327 return -EFAULT;
328 if (item_type != CSP__HEADER) {
329 snd_printd("%s: Invalid RIFF file type\n", __FUNCTION__);
330 return -EINVAL;
331 }
332 data_ptr += sizeof (item_type);
333
334 for (; data_ptr < data_end; data_ptr += LE_INT(item_h.len)) {
335 if (copy_from_user(&item_h, data_ptr, sizeof(item_h)))
336 return -EFAULT;
337 data_ptr += sizeof(item_h);
338 if (item_h.name != LIST_HEADER)
339 continue;
340
341 if (copy_from_user(&item_type, data_ptr, sizeof(item_type)))
342 return -EFAULT;
343 switch (item_type) {
344 case FUNC_HEADER:
345 if (copy_from_user(&funcdesc_h, data_ptr + sizeof(item_type), sizeof(funcdesc_h)))
346 return -EFAULT;
347 func_nr = LE_SHORT(funcdesc_h.func_nr);
348 break;
349 case CODE_HEADER:
350 if (func_nr != info.func_req)
351 break; /* not required function, try next */
352 data_ptr += sizeof(item_type);
353
354 /* destroy QSound mixer element */
355 if (p->mode == SNDRV_SB_CSP_MODE_QSOUND) {
356 snd_sb_qsound_destroy(p);
357 }
358 /* Clear all flags */
359 p->running = 0;
360 p->mode = 0;
361
362 /* load microcode blocks */
363 for (;;) {
364 if (data_ptr >= data_end)
365 return -EINVAL;
366 if (copy_from_user(&code_h, data_ptr, sizeof(code_h)))
367 return -EFAULT;
368
369 /* init microcode blocks */
370 if (code_h.name != INIT_HEADER)
371 break;
372 data_ptr += sizeof(code_h);
373 err = snd_sb_csp_load_user(p, data_ptr, LE_INT(code_h.len),
374 SNDRV_SB_CSP_LOAD_INITBLOCK);
375 if (err)
376 return err;
377 data_ptr += LE_INT(code_h.len);
378 }
379 /* main microcode block */
380 if (copy_from_user(&code_h, data_ptr, sizeof(code_h)))
381 return -EFAULT;
382
383 if (code_h.name != MAIN_HEADER) {
384 snd_printd("%s: Missing 'main' microcode\n", __FUNCTION__);
385 return -EINVAL;
386 }
387 data_ptr += sizeof(code_h);
388 err = snd_sb_csp_load_user(p, data_ptr,
389 LE_INT(code_h.len), 0);
390 if (err)
391 return err;
392
393 /* fill in codec header */
394 strlcpy(p->codec_name, info.codec_name, sizeof(p->codec_name));
395 p->func_nr = func_nr;
396 p->mode = LE_SHORT(funcdesc_h.flags_play_rec);
397 switch (LE_SHORT(funcdesc_h.VOC_type)) {
398 case 0x0001: /* QSound decoder */
399 if (LE_SHORT(funcdesc_h.flags_play_rec) == SNDRV_SB_CSP_MODE_DSP_WRITE) {
400 if (snd_sb_qsound_build(p) == 0)
401 /* set QSound flag and clear all other mode flags */
402 p->mode = SNDRV_SB_CSP_MODE_QSOUND;
403 }
404 p->acc_format = 0;
405 break;
406 case 0x0006: /* A Law codec */
407 p->acc_format = SNDRV_PCM_FMTBIT_A_LAW;
408 break;
409 case 0x0007: /* Mu Law codec */
410 p->acc_format = SNDRV_PCM_FMTBIT_MU_LAW;
411 break;
412 case 0x0011: /* what Creative thinks is IMA ADPCM codec */
413 case 0x0200: /* Creative ADPCM codec */
414 p->acc_format = SNDRV_PCM_FMTBIT_IMA_ADPCM;
415 break;
416 case 201: /* Text 2 Speech decoder */
417 /* TODO: Text2Speech handling routines */
418 p->acc_format = 0;
419 break;
420 case 0x0202: /* Fast Speech 8 codec */
421 case 0x0203: /* Fast Speech 10 codec */
422 p->acc_format = SNDRV_PCM_FMTBIT_SPECIAL;
423 break;
424 default: /* other codecs are unsupported */
425 p->acc_format = p->acc_width = p->acc_rates = 0;
426 p->mode = 0;
427 snd_printd("%s: Unsupported CSP codec type: 0x%04x\n",
428 __FUNCTION__,
429 LE_SHORT(funcdesc_h.VOC_type));
430 return -EINVAL;
431 }
432 p->acc_channels = LE_SHORT(funcdesc_h.flags_stereo_mono);
433 p->acc_width = LE_SHORT(funcdesc_h.flags_16bit_8bit);
434 p->acc_rates = LE_SHORT(funcdesc_h.flags_rates);
435
436 /* Decouple CSP from IRQ and DMAREQ lines */
437 spin_lock_irqsave(&p->chip->reg_lock, flags);
438 set_mode_register(p->chip, 0xfc);
439 set_mode_register(p->chip, 0x00);
440 spin_unlock_irqrestore(&p->chip->reg_lock, flags);
441
442 /* finished loading successfully */
443 p->running = SNDRV_SB_CSP_ST_LOADED; /* set LOADED flag */
444 return 0;
445 }
446 }
447 snd_printd("%s: Function #%d not found\n", __FUNCTION__, info.func_req);
448 return -EINVAL;
449}
450
451/*
452 * unload CSP microcode
453 */
454static int snd_sb_csp_unload(snd_sb_csp_t * p)
455{
456 if (p->running & SNDRV_SB_CSP_ST_RUNNING)
457 return -EBUSY;
458 if (!(p->running & SNDRV_SB_CSP_ST_LOADED))
459 return -ENXIO;
460
461 /* clear supported formats */
462 p->acc_format = 0;
463 p->acc_channels = p->acc_width = p->acc_rates = 0;
464 /* destroy QSound mixer element */
465 if (p->mode == SNDRV_SB_CSP_MODE_QSOUND) {
466 snd_sb_qsound_destroy(p);
467 }
468 /* clear all flags */
469 p->running = 0;
470 p->mode = 0;
471 return 0;
472}
473
474/*
475 * send command sequence to DSP
476 */
477static inline int command_seq(sb_t *chip, const unsigned char *seq, int size)
478{
479 int i;
480 for (i = 0; i < size; i++) {
481 if (!snd_sbdsp_command(chip, seq[i]))
482 return -EIO;
483 }
484 return 0;
485}
486
487/*
488 * set CSP codec parameter
489 */
490static int set_codec_parameter(sb_t *chip, unsigned char par, unsigned char val)
491{
492 unsigned char dsp_cmd[3];
493
494 dsp_cmd[0] = 0x05; /* CSP set codec parameter */
495 dsp_cmd[1] = val; /* Parameter value */
496 dsp_cmd[2] = par; /* Parameter */
497 command_seq(chip, dsp_cmd, 3);
498 snd_sbdsp_command(chip, 0x03); /* DSP read? */
499 if (snd_sbdsp_get_byte(chip) != par)
500 return -EIO;
501 return 0;
502}
503
504/*
505 * set CSP register
506 */
507static int set_register(sb_t *chip, unsigned char reg, unsigned char val)
508{
509 unsigned char dsp_cmd[3];
510
511 dsp_cmd[0] = 0x0e; /* CSP set register */
512 dsp_cmd[1] = reg; /* CSP Register */
513 dsp_cmd[2] = val; /* value */
514 return command_seq(chip, dsp_cmd, 3);
515}
516
517/*
518 * read CSP register
519 * return < 0 -> error
520 */
521static int read_register(sb_t *chip, unsigned char reg)
522{
523 unsigned char dsp_cmd[2];
524
525 dsp_cmd[0] = 0x0f; /* CSP read register */
526 dsp_cmd[1] = reg; /* CSP Register */
527 command_seq(chip, dsp_cmd, 2);
528 return snd_sbdsp_get_byte(chip); /* Read DSP value */
529}
530
531/*
532 * set CSP mode register
533 */
534static int set_mode_register(sb_t *chip, unsigned char mode)
535{
536 unsigned char dsp_cmd[2];
537
538 dsp_cmd[0] = 0x04; /* CSP set mode register */
539 dsp_cmd[1] = mode; /* mode */
540 return command_seq(chip, dsp_cmd, 2);
541}
542
543/*
544 * Detect CSP
545 * return 0 if CSP exists.
546 */
547static int csp_detect(sb_t *chip, int *version)
548{
549 unsigned char csp_test1, csp_test2;
550 unsigned long flags;
551 int result = -ENODEV;
552
553 spin_lock_irqsave(&chip->reg_lock, flags);
554
555 set_codec_parameter(chip, 0x00, 0x00);
556 set_mode_register(chip, 0xfc); /* 0xfc = ?? */
557
558 csp_test1 = read_register(chip, 0x83);
559 set_register(chip, 0x83, ~csp_test1);
560 csp_test2 = read_register(chip, 0x83);
561 if (csp_test2 != (csp_test1 ^ 0xff))
562 goto __fail;
563
564 set_register(chip, 0x83, csp_test1);
565 csp_test2 = read_register(chip, 0x83);
566 if (csp_test2 != csp_test1)
567 goto __fail;
568
569 set_mode_register(chip, 0x00); /* 0x00 = ? */
570
571 *version = get_version(chip);
572 snd_sbdsp_reset(chip); /* reset DSP after getversion! */
573 if (*version >= 0x10 && *version <= 0x1f)
574 result = 0; /* valid version id */
575
576 __fail:
577 spin_unlock_irqrestore(&chip->reg_lock, flags);
578 return result;
579}
580
581/*
582 * get CSP version number
583 */
584static int get_version(sb_t *chip)
585{
586 unsigned char dsp_cmd[2];
587
588 dsp_cmd[0] = 0x08; /* SB_DSP_!something! */
589 dsp_cmd[1] = 0x03; /* get chip version id? */
590 command_seq(chip, dsp_cmd, 2);
591
592 return (snd_sbdsp_get_byte(chip));
593}
594
595/*
596 * check if the CSP version is valid
597 */
598static int snd_sb_csp_check_version(snd_sb_csp_t * p)
599{
600 if (p->version < 0x10 || p->version > 0x1f) {
601 snd_printd("%s: Invalid CSP version: 0x%x\n", __FUNCTION__, p->version);
602 return 1;
603 }
604 return 0;
605}
606
607/*
608 * download microcode to CSP (microcode should have one "main" block).
609 */
610static int snd_sb_csp_load(snd_sb_csp_t * p, const unsigned char *buf, int size, int load_flags)
611{
612 int status, i;
613 int err;
614 int result = -EIO;
615 unsigned long flags;
616
617 spin_lock_irqsave(&p->chip->reg_lock, flags);
618 snd_sbdsp_command(p->chip, 0x01); /* CSP download command */
619 if (snd_sbdsp_get_byte(p->chip)) {
620 snd_printd("%s: Download command failed\n", __FUNCTION__);
621 goto __fail;
622 }
623 /* Send CSP low byte (size - 1) */
624 snd_sbdsp_command(p->chip, (unsigned char)(size - 1));
625 /* Send high byte */
626 snd_sbdsp_command(p->chip, (unsigned char)((size - 1) >> 8));
627 /* send microcode sequence */
628 /* load from kernel space */
629 while (size--) {
630 if (!snd_sbdsp_command(p->chip, *buf++))
631 goto __fail;
632 }
633 if (snd_sbdsp_get_byte(p->chip))
634 goto __fail;
635
636 if (load_flags & SNDRV_SB_CSP_LOAD_INITBLOCK) {
637 i = 0;
638 /* some codecs (FastSpeech) take some time to initialize */
639 while (1) {
640 snd_sbdsp_command(p->chip, 0x03);
641 status = snd_sbdsp_get_byte(p->chip);
642 if (status == 0x55 || ++i >= 10)
643 break;
644 udelay (10);
645 }
646 if (status != 0x55) {
647 snd_printd("%s: Microcode initialization failed\n", __FUNCTION__);
648 goto __fail;
649 }
650 } else {
651 /*
652 * Read mixer register SB_DSP4_DMASETUP after loading 'main' code.
653 * Start CSP chip if no 16bit DMA channel is set - some kind
654 * of autorun or perhaps a bugfix?
655 */
656 spin_lock(&p->chip->mixer_lock);
657 status = snd_sbmixer_read(p->chip, SB_DSP4_DMASETUP);
658 spin_unlock(&p->chip->mixer_lock);
659 if (!(status & (SB_DMASETUP_DMA7 | SB_DMASETUP_DMA6 | SB_DMASETUP_DMA5))) {
660 err = (set_codec_parameter(p->chip, 0xaa, 0x00) ||
661 set_codec_parameter(p->chip, 0xff, 0x00));
662 snd_sbdsp_reset(p->chip); /* really! */
663 if (err)
664 goto __fail;
665 set_mode_register(p->chip, 0xc0); /* c0 = STOP */
666 set_mode_register(p->chip, 0x70); /* 70 = RUN */
667 }
668 }
669 result = 0;
670
671 __fail:
672 spin_unlock_irqrestore(&p->chip->reg_lock, flags);
673 return result;
674}
675
676static int snd_sb_csp_load_user(snd_sb_csp_t * p, const unsigned char __user *buf, int size, int load_flags)
677{
678 int err = -ENOMEM;
679 unsigned char *kbuf = kmalloc(size, GFP_KERNEL);
680 if (kbuf) {
681 if (copy_from_user(kbuf, buf, size))
682 err = -EFAULT;
683 else
684 err = snd_sb_csp_load(p, kbuf, size, load_flags);
685 kfree(kbuf);
686 }
687 return err;
688}
689
690#include "sb16_csp_codecs.h"
691
692/*
693 * autoload hardware codec if necessary
694 * return 0 if CSP is loaded and ready to run (p->running != 0)
695 */
696static int snd_sb_csp_autoload(snd_sb_csp_t * p, int pcm_sfmt, int play_rec_mode)
697{
698 unsigned long flags;
699 int err = 0;
700
701 /* if CSP is running or manually loaded then exit */
702 if (p->running & (SNDRV_SB_CSP_ST_RUNNING | SNDRV_SB_CSP_ST_LOADED))
703 return -EBUSY;
704
705 /* autoload microcode only if requested hardware codec is not already loaded */
706 if (((1 << pcm_sfmt) & p->acc_format) && (play_rec_mode & p->mode)) {
707 p->running = SNDRV_SB_CSP_ST_AUTO;
708 } else {
709 switch (pcm_sfmt) {
710 case SNDRV_PCM_FORMAT_MU_LAW:
711 err = snd_sb_csp_load(p, &mulaw_main[0], sizeof(mulaw_main), 0);
712 p->acc_format = SNDRV_PCM_FMTBIT_MU_LAW;
713 p->mode = SNDRV_SB_CSP_MODE_DSP_READ | SNDRV_SB_CSP_MODE_DSP_WRITE;
714 break;
715 case SNDRV_PCM_FORMAT_A_LAW:
716 err = snd_sb_csp_load(p, &alaw_main[0], sizeof(alaw_main), 0);
717 p->acc_format = SNDRV_PCM_FMTBIT_A_LAW;
718 p->mode = SNDRV_SB_CSP_MODE_DSP_READ | SNDRV_SB_CSP_MODE_DSP_WRITE;
719 break;
720 case SNDRV_PCM_FORMAT_IMA_ADPCM:
721 err = snd_sb_csp_load(p, &ima_adpcm_init[0], sizeof(ima_adpcm_init),
722 SNDRV_SB_CSP_LOAD_INITBLOCK);
723 if (err)
724 break;
725 if (play_rec_mode == SNDRV_SB_CSP_MODE_DSP_WRITE) {
726 err = snd_sb_csp_load(p, &ima_adpcm_playback[0],
727 sizeof(ima_adpcm_playback), 0);
728 p->mode = SNDRV_SB_CSP_MODE_DSP_WRITE;
729 } else {
730 err = snd_sb_csp_load(p, &ima_adpcm_capture[0],
731 sizeof(ima_adpcm_capture), 0);
732 p->mode = SNDRV_SB_CSP_MODE_DSP_READ;
733 }
734 p->acc_format = SNDRV_PCM_FMTBIT_IMA_ADPCM;
735 break;
736 default:
737 /* Decouple CSP from IRQ and DMAREQ lines */
738 if (p->running & SNDRV_SB_CSP_ST_AUTO) {
739 spin_lock_irqsave(&p->chip->reg_lock, flags);
740 set_mode_register(p->chip, 0xfc);
741 set_mode_register(p->chip, 0x00);
742 spin_unlock_irqrestore(&p->chip->reg_lock, flags);
743 p->running = 0; /* clear autoloaded flag */
744 }
745 return -EINVAL;
746 }
747 if (err) {
748 p->acc_format = 0;
749 p->acc_channels = p->acc_width = p->acc_rates = 0;
750
751 p->running = 0; /* clear autoloaded flag */
752 p->mode = 0;
753 return (err);
754 } else {
755 p->running = SNDRV_SB_CSP_ST_AUTO; /* set autoloaded flag */
756 p->acc_width = SNDRV_SB_CSP_SAMPLE_16BIT; /* only 16 bit data */
757 p->acc_channels = SNDRV_SB_CSP_MONO | SNDRV_SB_CSP_STEREO;
758 p->acc_rates = SNDRV_SB_CSP_RATE_ALL; /* HW codecs accept all rates */
759 }
760
761 }
762 return (p->running & SNDRV_SB_CSP_ST_AUTO) ? 0 : -ENXIO;
763}
764
765/*
766 * start CSP
767 */
768static int snd_sb_csp_start(snd_sb_csp_t * p, int sample_width, int channels)
769{
770 unsigned char s_type; /* sample type */
771 unsigned char mixL, mixR;
772 int result = -EIO;
773 unsigned long flags;
774
775 if (!(p->running & (SNDRV_SB_CSP_ST_LOADED | SNDRV_SB_CSP_ST_AUTO))) {
776 snd_printd("%s: Microcode not loaded\n", __FUNCTION__);
777 return -ENXIO;
778 }
779 if (p->running & SNDRV_SB_CSP_ST_RUNNING) {
780 snd_printd("%s: CSP already running\n", __FUNCTION__);
781 return -EBUSY;
782 }
783 if (!(sample_width & p->acc_width)) {
784 snd_printd("%s: Unsupported PCM sample width\n", __FUNCTION__);
785 return -EINVAL;
786 }
787 if (!(channels & p->acc_channels)) {
788 snd_printd("%s: Invalid number of channels\n", __FUNCTION__);
789 return -EINVAL;
790 }
791
792 /* Mute PCM volume */
793 spin_lock_irqsave(&p->chip->mixer_lock, flags);
794 mixL = snd_sbmixer_read(p->chip, SB_DSP4_PCM_DEV);
795 mixR = snd_sbmixer_read(p->chip, SB_DSP4_PCM_DEV + 1);
796 snd_sbmixer_write(p->chip, SB_DSP4_PCM_DEV, mixL & 0x7);
797 snd_sbmixer_write(p->chip, SB_DSP4_PCM_DEV + 1, mixR & 0x7);
798
799 spin_lock(&p->chip->reg_lock);
800 set_mode_register(p->chip, 0xc0); /* c0 = STOP */
801 set_mode_register(p->chip, 0x70); /* 70 = RUN */
802
803 s_type = 0x00;
804 if (channels == SNDRV_SB_CSP_MONO)
805 s_type = 0x11; /* 000n 000n (n = 1 if mono) */
806 if (sample_width == SNDRV_SB_CSP_SAMPLE_8BIT)
807 s_type |= 0x22; /* 00dX 00dX (d = 1 if 8 bit samples) */
808
809 if (set_codec_parameter(p->chip, 0x81, s_type)) {
810 snd_printd("%s: Set sample type command failed\n", __FUNCTION__);
811 goto __fail;
812 }
813 if (set_codec_parameter(p->chip, 0x80, 0x00)) {
814 snd_printd("%s: Codec start command failed\n", __FUNCTION__);
815 goto __fail;
816 }
817 p->run_width = sample_width;
818 p->run_channels = channels;
819
820 p->running |= SNDRV_SB_CSP_ST_RUNNING;
821
822 if (p->mode & SNDRV_SB_CSP_MODE_QSOUND) {
823 set_codec_parameter(p->chip, 0xe0, 0x01);
824 /* enable QSound decoder */
825 set_codec_parameter(p->chip, 0x00, 0xff);
826 set_codec_parameter(p->chip, 0x01, 0xff);
827 p->running |= SNDRV_SB_CSP_ST_QSOUND;
828 /* set QSound startup value */
829 snd_sb_csp_qsound_transfer(p);
830 }
831 result = 0;
832
833 __fail:
834 spin_unlock(&p->chip->reg_lock);
835
836 /* restore PCM volume */
837 snd_sbmixer_write(p->chip, SB_DSP4_PCM_DEV, mixL);
838 snd_sbmixer_write(p->chip, SB_DSP4_PCM_DEV + 1, mixR);
839 spin_unlock_irqrestore(&p->chip->mixer_lock, flags);
840
841 return result;
842}
843
844/*
845 * stop CSP
846 */
847static int snd_sb_csp_stop(snd_sb_csp_t * p)
848{
849 int result;
850 unsigned char mixL, mixR;
851 unsigned long flags;
852
853 if (!(p->running & SNDRV_SB_CSP_ST_RUNNING))
854 return 0;
855
856 /* Mute PCM volume */
857 spin_lock_irqsave(&p->chip->mixer_lock, flags);
858 mixL = snd_sbmixer_read(p->chip, SB_DSP4_PCM_DEV);
859 mixR = snd_sbmixer_read(p->chip, SB_DSP4_PCM_DEV + 1);
860 snd_sbmixer_write(p->chip, SB_DSP4_PCM_DEV, mixL & 0x7);
861 snd_sbmixer_write(p->chip, SB_DSP4_PCM_DEV + 1, mixR & 0x7);
862
863 spin_lock(&p->chip->reg_lock);
864 if (p->running & SNDRV_SB_CSP_ST_QSOUND) {
865 set_codec_parameter(p->chip, 0xe0, 0x01);
866 /* disable QSound decoder */
867 set_codec_parameter(p->chip, 0x00, 0x00);
868 set_codec_parameter(p->chip, 0x01, 0x00);
869
870 p->running &= ~SNDRV_SB_CSP_ST_QSOUND;
871 }
872 result = set_mode_register(p->chip, 0xc0); /* c0 = STOP */
873 spin_unlock(&p->chip->reg_lock);
874
875 /* restore PCM volume */
876 snd_sbmixer_write(p->chip, SB_DSP4_PCM_DEV, mixL);
877 snd_sbmixer_write(p->chip, SB_DSP4_PCM_DEV + 1, mixR);
878 spin_unlock_irqrestore(&p->chip->mixer_lock, flags);
879
880 if (!(result))
881 p->running &= ~(SNDRV_SB_CSP_ST_PAUSED | SNDRV_SB_CSP_ST_RUNNING);
882 return result;
883}
884
885/*
886 * pause CSP codec and hold DMA transfer
887 */
888static int snd_sb_csp_pause(snd_sb_csp_t * p)
889{
890 int result;
891 unsigned long flags;
892
893 if (!(p->running & SNDRV_SB_CSP_ST_RUNNING))
894 return -EBUSY;
895
896 spin_lock_irqsave(&p->chip->reg_lock, flags);
897 result = set_codec_parameter(p->chip, 0x80, 0xff);
898 spin_unlock_irqrestore(&p->chip->reg_lock, flags);
899 if (!(result))
900 p->running |= SNDRV_SB_CSP_ST_PAUSED;
901
902 return result;
903}
904
905/*
906 * restart CSP codec and resume DMA transfer
907 */
908static int snd_sb_csp_restart(snd_sb_csp_t * p)
909{
910 int result;
911 unsigned long flags;
912
913 if (!(p->running & SNDRV_SB_CSP_ST_PAUSED))
914 return -EBUSY;
915
916 spin_lock_irqsave(&p->chip->reg_lock, flags);
917 result = set_codec_parameter(p->chip, 0x80, 0x00);
918 spin_unlock_irqrestore(&p->chip->reg_lock, flags);
919 if (!(result))
920 p->running &= ~SNDRV_SB_CSP_ST_PAUSED;
921
922 return result;
923}
924
925/* ------------------------------ */
926
927/*
928 * QSound mixer control for PCM
929 */
930
931static int snd_sb_qsound_switch_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
932{
933 uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
934 uinfo->count = 1;
935 uinfo->value.integer.min = 0;
936 uinfo->value.integer.max = 1;
937 return 0;
938}
939
940static int snd_sb_qsound_switch_get(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
941{
942 snd_sb_csp_t *p = snd_kcontrol_chip(kcontrol);
943
944 ucontrol->value.integer.value[0] = p->q_enabled ? 1 : 0;
945 return 0;
946}
947
948static int snd_sb_qsound_switch_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
949{
950 snd_sb_csp_t *p = snd_kcontrol_chip(kcontrol);
951 unsigned long flags;
952 int change;
953 unsigned char nval;
954
955 nval = ucontrol->value.integer.value[0] & 0x01;
956 spin_lock_irqsave(&p->q_lock, flags);
957 change = p->q_enabled != nval;
958 p->q_enabled = nval;
959 spin_unlock_irqrestore(&p->q_lock, flags);
960 return change;
961}
962
963static int snd_sb_qsound_space_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
964{
965 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
966 uinfo->count = 2;
967 uinfo->value.integer.min = 0;
968 uinfo->value.integer.max = SNDRV_SB_CSP_QSOUND_MAX_RIGHT;
969 return 0;
970}
971
972static int snd_sb_qsound_space_get(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
973{
974 snd_sb_csp_t *p = snd_kcontrol_chip(kcontrol);
975 unsigned long flags;
976
977 spin_lock_irqsave(&p->q_lock, flags);
978 ucontrol->value.integer.value[0] = p->qpos_left;
979 ucontrol->value.integer.value[1] = p->qpos_right;
980 spin_unlock_irqrestore(&p->q_lock, flags);
981 return 0;
982}
983
984static int snd_sb_qsound_space_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
985{
986 snd_sb_csp_t *p = snd_kcontrol_chip(kcontrol);
987 unsigned long flags;
988 int change;
989 unsigned char nval1, nval2;
990
991 nval1 = ucontrol->value.integer.value[0];
992 if (nval1 > SNDRV_SB_CSP_QSOUND_MAX_RIGHT)
993 nval1 = SNDRV_SB_CSP_QSOUND_MAX_RIGHT;
994 nval2 = ucontrol->value.integer.value[1];
995 if (nval2 > SNDRV_SB_CSP_QSOUND_MAX_RIGHT)
996 nval2 = SNDRV_SB_CSP_QSOUND_MAX_RIGHT;
997 spin_lock_irqsave(&p->q_lock, flags);
998 change = p->qpos_left != nval1 || p->qpos_right != nval2;
999 p->qpos_left = nval1;
1000 p->qpos_right = nval2;
1001 p->qpos_changed = change;
1002 spin_unlock_irqrestore(&p->q_lock, flags);
1003 return change;
1004}
1005
1006static snd_kcontrol_new_t snd_sb_qsound_switch = {
1007 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1008 .name = "3D Control - Switch",
1009 .info = snd_sb_qsound_switch_info,
1010 .get = snd_sb_qsound_switch_get,
1011 .put = snd_sb_qsound_switch_put
1012};
1013
1014static snd_kcontrol_new_t snd_sb_qsound_space = {
1015 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1016 .name = "3D Control - Space",
1017 .info = snd_sb_qsound_space_info,
1018 .get = snd_sb_qsound_space_get,
1019 .put = snd_sb_qsound_space_put
1020};
1021
1022static int snd_sb_qsound_build(snd_sb_csp_t * p)
1023{
1024 snd_card_t * card;
1025 int err;
1026
1027 snd_assert(p != NULL, return -EINVAL);
1028
1029 card = p->chip->card;
1030 p->qpos_left = p->qpos_right = SNDRV_SB_CSP_QSOUND_MAX_RIGHT / 2;
1031 p->qpos_changed = 0;
1032
1033 spin_lock_init(&p->q_lock);
1034
1035 if ((err = snd_ctl_add(card, p->qsound_switch = snd_ctl_new1(&snd_sb_qsound_switch, p))) < 0)
1036 goto __error;
1037 if ((err = snd_ctl_add(card, p->qsound_space = snd_ctl_new1(&snd_sb_qsound_space, p))) < 0)
1038 goto __error;
1039
1040 return 0;
1041
1042 __error:
1043 snd_sb_qsound_destroy(p);
1044 return err;
1045}
1046
1047static void snd_sb_qsound_destroy(snd_sb_csp_t * p)
1048{
1049 snd_card_t * card;
1050 unsigned long flags;
1051
1052 snd_assert(p != NULL, return);
1053
1054 card = p->chip->card;
1055
1056 down_write(&card->controls_rwsem);
1057 if (p->qsound_switch)
1058 snd_ctl_remove(card, p->qsound_switch);
1059 if (p->qsound_space)
1060 snd_ctl_remove(card, p->qsound_space);
1061 up_write(&card->controls_rwsem);
1062
1063 /* cancel pending transfer of QSound parameters */
1064 spin_lock_irqsave (&p->q_lock, flags);
1065 p->qpos_changed = 0;
1066 spin_unlock_irqrestore (&p->q_lock, flags);
1067}
1068
1069/*
1070 * Transfer qsound parameters to CSP,
1071 * function should be called from interrupt routine
1072 */
1073static int snd_sb_csp_qsound_transfer(snd_sb_csp_t * p)
1074{
1075 int err = -ENXIO;
1076
1077 spin_lock(&p->q_lock);
1078 if (p->running & SNDRV_SB_CSP_ST_QSOUND) {
1079 set_codec_parameter(p->chip, 0xe0, 0x01);
1080 /* left channel */
1081 set_codec_parameter(p->chip, 0x00, p->qpos_left);
1082 set_codec_parameter(p->chip, 0x02, 0x00);
1083 /* right channel */
1084 set_codec_parameter(p->chip, 0x00, p->qpos_right);
1085 set_codec_parameter(p->chip, 0x03, 0x00);
1086 err = 0;
1087 }
1088 p->qpos_changed = 0;
1089 spin_unlock(&p->q_lock);
1090 return err;
1091}
1092
1093/* ------------------------------ */
1094
1095/*
1096 * proc interface
1097 */
1098static int init_proc_entry(snd_sb_csp_t * p, int device)
1099{
1100 char name[16];
1101 snd_info_entry_t *entry;
1102 sprintf(name, "cspD%d", device);
1103 if (! snd_card_proc_new(p->chip->card, name, &entry))
1104 snd_info_set_text_ops(entry, p, 1024, info_read);
1105 return 0;
1106}
1107
1108static void info_read(snd_info_entry_t *entry, snd_info_buffer_t * buffer)
1109{
1110 snd_sb_csp_t *p = entry->private_data;
1111
1112 snd_iprintf(buffer, "Creative Signal Processor [v%d.%d]\n", (p->version >> 4), (p->version & 0x0f));
1113 snd_iprintf(buffer, "State: %cx%c%c%c\n", ((p->running & SNDRV_SB_CSP_ST_QSOUND) ? 'Q' : '-'),
1114 ((p->running & SNDRV_SB_CSP_ST_PAUSED) ? 'P' : '-'),
1115 ((p->running & SNDRV_SB_CSP_ST_RUNNING) ? 'R' : '-'),
1116 ((p->running & SNDRV_SB_CSP_ST_LOADED) ? 'L' : '-'));
1117 if (p->running & SNDRV_SB_CSP_ST_LOADED) {
1118 snd_iprintf(buffer, "Codec: %s [func #%d]\n", p->codec_name, p->func_nr);
1119 snd_iprintf(buffer, "Sample rates: ");
1120 if (p->acc_rates == SNDRV_SB_CSP_RATE_ALL) {
1121 snd_iprintf(buffer, "All\n");
1122 } else {
1123 snd_iprintf(buffer, "%s%s%s%s\n",
1124 ((p->acc_rates & SNDRV_SB_CSP_RATE_8000) ? "8000Hz " : ""),
1125 ((p->acc_rates & SNDRV_SB_CSP_RATE_11025) ? "11025Hz " : ""),
1126 ((p->acc_rates & SNDRV_SB_CSP_RATE_22050) ? "22050Hz " : ""),
1127 ((p->acc_rates & SNDRV_SB_CSP_RATE_44100) ? "44100Hz" : ""));
1128 }
1129 if (p->mode == SNDRV_SB_CSP_MODE_QSOUND) {
1130 snd_iprintf(buffer, "QSound decoder %sabled\n",
1131 p->q_enabled ? "en" : "dis");
1132 } else {
1133 snd_iprintf(buffer, "PCM format ID: 0x%x (%s/%s) [%s/%s] [%s/%s]\n",
1134 p->acc_format,
1135 ((p->acc_width & SNDRV_SB_CSP_SAMPLE_16BIT) ? "16bit" : "-"),
1136 ((p->acc_width & SNDRV_SB_CSP_SAMPLE_8BIT) ? "8bit" : "-"),
1137 ((p->acc_channels & SNDRV_SB_CSP_MONO) ? "mono" : "-"),
1138 ((p->acc_channels & SNDRV_SB_CSP_STEREO) ? "stereo" : "-"),
1139 ((p->mode & SNDRV_SB_CSP_MODE_DSP_WRITE) ? "playback" : "-"),
1140 ((p->mode & SNDRV_SB_CSP_MODE_DSP_READ) ? "capture" : "-"));
1141 }
1142 }
1143 if (p->running & SNDRV_SB_CSP_ST_AUTO) {
1144 snd_iprintf(buffer, "Autoloaded Mu-Law, A-Law or Ima-ADPCM hardware codec\n");
1145 }
1146 if (p->running & SNDRV_SB_CSP_ST_RUNNING) {
1147 snd_iprintf(buffer, "Processing %dbit %s PCM samples\n",
1148 ((p->run_width & SNDRV_SB_CSP_SAMPLE_16BIT) ? 16 : 8),
1149 ((p->run_channels & SNDRV_SB_CSP_MONO) ? "mono" : "stereo"));
1150 }
1151 if (p->running & SNDRV_SB_CSP_ST_QSOUND) {
1152 snd_iprintf(buffer, "Qsound position: left = 0x%x, right = 0x%x\n",
1153 p->qpos_left, p->qpos_right);
1154 }
1155}
1156
1157/* */
1158
1159EXPORT_SYMBOL(snd_sb_csp_new);
1160
1161/*
1162 * INIT part
1163 */
1164
1165static int __init alsa_sb_csp_init(void)
1166{
1167 return 0;
1168}
1169
1170static void __exit alsa_sb_csp_exit(void)
1171{
1172}
1173
1174module_init(alsa_sb_csp_init)
1175module_exit(alsa_sb_csp_exit)
diff --git a/sound/isa/sb/sb16_csp_codecs.h b/sound/isa/sb/sb16_csp_codecs.h
new file mode 100644
index 000000000000..f0e8b0dcb572
--- /dev/null
+++ b/sound/isa/sb/sb16_csp_codecs.h
@@ -0,0 +1,949 @@
1/*
2 * Copyright (c) 1994 Creative Technology Ltd.
3 * Microcode files for SB16 Advanced Signal Processor
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 *
19 */
20
21static unsigned char mulaw_main[] = {
22 0x00, 0x10, 0x00, 0x44, 0x08, 0x00, 0x00, 0x44,
23 0x00, 0xb1, 0x00, 0x44, 0x00, 0x61, 0x00, 0x44,
24 0x08, 0x50, 0x00, 0x44, 0x0d, 0xf2, 0x61, 0xa8,
25 0x44, 0x04, 0x04, 0x19, 0x00, 0x00, 0x40, 0x45,
26 0x40, 0x49, 0x39, 0xac, 0x55, 0x55, 0x71, 0x8b,
27 0x50, 0x05, 0x63, 0x80, 0x00, 0x00, 0x06, 0x39,
28 0xff, 0x2e, 0x21, 0x49, 0xff, 0x0f, 0xd4, 0x49,
29 0x20, 0x01, 0x09, 0x0e, 0x20, 0x00, 0x71, 0x8b,
30 0xa8, 0x01, 0xa8, 0x80, 0x88, 0x01, 0xa8, 0x80,
31 0xa8, 0x00, 0x00, 0x80, 0xd2, 0x00, 0x71, 0x8b,
32 0x88, 0x00, 0xa8, 0x80, 0xa8, 0x04, 0xb3, 0x80,
33 0x20, 0x07, 0xb3, 0x80, 0x88, 0x03, 0xb1, 0x80,
34 0xc0, 0x00, 0x09, 0x5c, 0xc2, 0x01, 0x00, 0x82,
35 0xa1, 0x00, 0x71, 0x8b, 0xcd, 0x00, 0x04, 0x19,
36 0xa2, 0x20, 0x71, 0x8b, 0xcf, 0x00, 0x04, 0x19,
37 0x00, 0x00, 0xb1, 0x80, 0xc2, 0x00, 0x04, 0x19,
38 0x00, 0x40, 0x00, 0x14, 0x08, 0x40, 0x04, 0x24,
39 0x00, 0x00, 0x34, 0x49, 0x0c, 0x40, 0x00, 0x44,
40 0x44, 0x04, 0x04, 0x39, 0x00, 0x00, 0x40, 0x45,
41 0x32, 0x00, 0x09, 0x5c, 0x00, 0x00, 0x0c, 0x39,
42 0x00, 0x00, 0x40, 0x45, 0x40, 0x40, 0x09, 0xef,
43 0xff, 0x20, 0x09, 0xcf, 0x00, 0x04, 0x63, 0xa1,
44 0x50, 0x03, 0x33, 0x80, 0x00, 0x04, 0xa3, 0x80,
45 0x00, 0xff, 0xc2, 0x8b, 0x00, 0xd0, 0x04, 0x54,
46 0x04, 0xe0, 0x00, 0xc4, 0x20, 0x03, 0x80, 0xc0,
47 0x30, 0x00, 0x00, 0x88, 0x00, 0x00, 0x7a, 0x0a,
48 0xd0, 0x01, 0x00, 0x82, 0x00, 0x60, 0x00, 0x44,
49 0xc0, 0x00, 0x00, 0x99, 0x00, 0x60, 0x00, 0x44,
50 0x00, 0xff, 0xc2, 0x8b, 0x20, 0x00, 0x00, 0x80,
51 0x00, 0x0d, 0x42, 0x8b, 0x08, 0x32, 0x00, 0xc4,
52 0x00, 0x0e, 0x42, 0x8b, 0x00, 0xa2, 0x00, 0xc4,
53 0x00, 0x1e, 0x42, 0x8b, 0x0c, 0xb2, 0x00, 0xc4,
54 0x00, 0x8e, 0x42, 0x8b, 0x00, 0x62, 0x00, 0xc4,
55 0x00, 0x9e, 0x42, 0x8b, 0x08, 0x52, 0x00, 0xc4,
56 0x00, 0xbe, 0x42, 0x8b, 0x08, 0x52, 0x00, 0xc4,
57 0x00, 0x04, 0x42, 0x8b, 0x04, 0x72, 0x00, 0xc4,
58 0x00, 0x24, 0x42, 0x8b, 0x00, 0xd2, 0x00, 0xc4,
59 0x00, 0x55, 0x42, 0x8b, 0x00, 0x60, 0x00, 0xc4,
60 0x00, 0x00, 0x40, 0x45, 0x20, 0x01, 0x79, 0x80,
61 0x00, 0x30, 0x42, 0x8b, 0x08, 0x82, 0x00, 0xc4,
62 0x00, 0x00, 0x40, 0x45, 0x00, 0x00, 0x71, 0x8b,
63 0x40, 0x01, 0x00, 0x80, 0x00, 0x60, 0x00, 0x44,
64 0xff, 0x00, 0xe2, 0xab, 0x00, 0xb2, 0x00, 0xc4,
65 0x0f, 0xf2, 0xa8, 0xa8, 0x20, 0x00, 0xb1, 0x88,
66 0x00, 0x00, 0x41, 0x02, 0x4d, 0xf2, 0x00, 0x39,
67 0xc0, 0x01, 0x00, 0x82, 0x00, 0x60, 0x00, 0x44,
68 0x0d, 0xf2, 0xa3, 0xa8, 0x4d, 0xf2, 0x00, 0x39,
69 0x00, 0x60, 0x00, 0x44, 0xff, 0x00, 0xe2, 0xab,
70 0x20, 0x00, 0x00, 0x88, 0x00, 0x00, 0x61, 0x02,
71 0x4d, 0xf2, 0x04, 0x19, 0x00, 0x60, 0x00, 0x44,
72 0xff, 0x00, 0xe2, 0xab, 0xa0, 0x00, 0x00, 0x88,
73 0x00, 0x00, 0x61, 0x10, 0x4d, 0xf2, 0x04, 0x19,
74 0x00, 0x60, 0x00, 0x44, 0xff, 0x20, 0xe2, 0xab,
75 0x60, 0x00, 0x00, 0x88, 0x00, 0x00, 0x71, 0xc0,
76 0x4d, 0xf2, 0x04, 0x19, 0x00, 0x60, 0x00, 0x44,
77 0x00, 0x00, 0x79, 0x80, 0x00, 0xe2, 0x00, 0x84,
78 0x03, 0x03, 0x04, 0x49, 0x08, 0xc2, 0x00, 0x54,
79 0x00, 0x60, 0x04, 0x64, 0x00, 0x60, 0x00, 0x44,
80 0x00, 0x00, 0x63, 0x80, 0x00, 0x00, 0x06, 0x19,
81 0x03, 0x00, 0x04, 0x49, 0x00, 0x60, 0x00, 0x44,
82 0x20, 0x01, 0x63, 0x80, 0x00, 0x00, 0x06, 0x19,
83 0x00, 0x20, 0xe2, 0x8b, 0x0c, 0xf2, 0x00, 0x84,
84 0x3e, 0x00, 0x51, 0x8b, 0xc0, 0x20, 0x00, 0x39,
85 0x08, 0x01, 0x00, 0x44, 0x6c, 0x00, 0x51, 0x8b,
86 0xc0, 0x20, 0x00, 0x39, 0x00, 0x02, 0xe2, 0x8b,
87 0x04, 0x21, 0x00, 0x84, 0xfd, 0x00, 0x51, 0x8b,
88 0xc2, 0x20, 0x00, 0x39, 0x00, 0x11, 0x00, 0x44,
89 0xfe, 0x00, 0x51, 0x8b, 0xc2, 0x20, 0x00, 0x39,
90 0xe5, 0x00, 0x71, 0x8b, 0xcd, 0x00, 0x00, 0x39,
91 0x00, 0x00, 0xb1, 0x80, 0xc9, 0x20, 0x04, 0x19,
92 0xcb, 0x20, 0x04, 0x19, 0xc1, 0x20, 0x04, 0x19,
93 0xc3, 0x20, 0x04, 0x19, 0x10, 0x00, 0x71, 0x8b,
94 0xc7, 0x20, 0x04, 0x19, 0x5e, 0x00, 0x71, 0x8b,
95 0xcf, 0x00, 0x00, 0x39, 0x00, 0x00, 0xb1, 0x80,
96 0xc4, 0x20, 0x04, 0x19, 0xc6, 0x20, 0x04, 0x19,
97 0xc8, 0x20, 0x04, 0x19, 0xca, 0x20, 0x04, 0x19,
98 0x20, 0x00, 0x71, 0x8b, 0xcc, 0x20, 0x04, 0x19,
99 0x03, 0x00, 0x04, 0x49, 0x00, 0x60, 0x00, 0x44,
100 0x09, 0x04, 0x61, 0xa8, 0xc1, 0x00, 0x04, 0x19,
101 0x0b, 0x04, 0x61, 0xa8, 0xca, 0x00, 0x04, 0x19,
102 0x04, 0x60, 0x00, 0xd4, 0x0d, 0x00, 0x61, 0x0a,
103 0x90, 0x40, 0x09, 0x8f, 0x00, 0x01, 0x00, 0x45,
104 0x0f, 0x00, 0x61, 0x0a, 0x00, 0x40, 0x09, 0x8f,
105 0x00, 0x01, 0x00, 0x45, 0x82, 0x00, 0x09, 0x2e,
106 0x80, 0x40, 0x09, 0xcf, 0x02, 0x00, 0x61, 0x22,
107 0x43, 0x25, 0x61, 0x22, 0x40, 0x33, 0x00, 0x80,
108 0x08, 0xa8, 0x00, 0x44, 0x20, 0x31, 0x49, 0x5c,
109 0x92, 0x00, 0x09, 0x4e, 0x02, 0x03, 0x09, 0x2e,
110 0x00, 0x00, 0xa3, 0x02, 0xc0, 0x00, 0x71, 0xc0,
111 0x20, 0x00, 0xeb, 0x80, 0x00, 0x04, 0xc2, 0x8b,
112 0x20, 0x04, 0x61, 0x80, 0x00, 0x04, 0x7a, 0x02,
113 0xcb, 0x00, 0xa8, 0x58, 0xb0, 0x05, 0xf3, 0x80,
114 0x20, 0x04, 0xa8, 0x10, 0x00, 0x00, 0x10, 0x39,
115 0xb0, 0x00, 0xe0, 0x8b, 0x20, 0x01, 0x00, 0x80,
116 0x00, 0x00, 0x63, 0xcb, 0x00, 0x00, 0x7a, 0x02,
117 0x40, 0x00, 0x01, 0x5b, 0x20, 0x00, 0x00, 0x80,
118 0x00, 0x00, 0x4a, 0xcb, 0x20, 0x00, 0x13, 0x80,
119 0x20, 0x00, 0x7a, 0x80, 0xe0, 0x21, 0x00, 0xc0,
120 0x08, 0x00, 0x08, 0x49, 0x10, 0x41, 0x09, 0x8e,
121 0xff, 0xff, 0x62, 0x8b, 0x00, 0x04, 0x61, 0x22,
122 0x00, 0x03, 0x00, 0x45, 0x22, 0x01, 0x33, 0x80,
123 0x20, 0x01, 0xa3, 0x02, 0x00, 0x00, 0x7a, 0x80,
124 0xc0, 0x00, 0x00, 0x82, 0x07, 0x20, 0x40, 0x0a,
125 0x08, 0x83, 0x00, 0x84, 0x40, 0x21, 0x00, 0x80,
126 0x40, 0x05, 0x93, 0x10, 0xc7, 0x20, 0x00, 0x39,
127 0x00, 0x00, 0x40, 0x45, 0x07, 0x20, 0x40, 0x0a,
128 0x0c, 0xa3, 0x00, 0x84, 0x08, 0x00, 0x00, 0x82,
129 0x0c, 0x24, 0x61, 0x50, 0x40, 0x01, 0x00, 0x80,
130 0xc7, 0x20, 0x00, 0x39, 0x00, 0x00, 0x40, 0x45,
131 0x00, 0x04, 0x63, 0x80, 0x00, 0x00, 0x06, 0x39,
132 0x42, 0x01, 0x09, 0x0e, 0x02, 0x20, 0x61, 0x0a,
133 0x00, 0x01, 0x00, 0x45, 0x0c, 0x20, 0x60, 0x0a,
134 0x00, 0x73, 0x00, 0x84, 0x00, 0x04, 0xb1, 0x80,
135 0x00, 0x00, 0x06, 0x39, 0x0c, 0x61, 0x04, 0xd4,
136 0x00, 0x24, 0x71, 0xc0, 0x20, 0x33, 0x33, 0xc0,
137 0xe0, 0x01, 0xa3, 0x82, 0x22, 0x03, 0x7a, 0x02,
138 0xc3, 0x01, 0xa3, 0x82, 0x20, 0x01, 0x33, 0x80,
139 0x00, 0x00, 0x7a, 0x80, 0xc2, 0x01, 0xb3, 0x50,
140 0xcc, 0x20, 0x00, 0x39, 0x00, 0x00, 0x71, 0x80,
141 0x00, 0xf3, 0x00, 0x44, 0x0c, 0x20, 0x60, 0x0a,
142 0x00, 0xd3, 0x00, 0x84, 0x00, 0x04, 0xb1, 0x80,
143 0x00, 0x00, 0x06, 0x39, 0x0c, 0x61, 0x04, 0xd4,
144 0x00, 0x00, 0xb3, 0x10, 0xcc, 0x20, 0x00, 0x39,
145 0x00, 0x00, 0x71, 0xc0, 0x00, 0xf3, 0x00, 0x44,
146 0xcc, 0x20, 0x00, 0x39, 0x00, 0x20, 0x71, 0xc0,
147 0x00, 0x30, 0x71, 0xc0, 0x00, 0xf3, 0x00, 0x44,
148 0x20, 0x01, 0x00, 0x80, 0xff, 0xff, 0x62, 0x8b,
149 0x20, 0x01, 0x33, 0x80, 0x00, 0x00, 0x83, 0x80,
150 0x20, 0x00, 0x7a, 0x80, 0x20, 0xe1, 0x09, 0x5c,
151 0x82, 0x00, 0x09, 0x2f, 0x80, 0x4a, 0x09, 0x8e,
152 0xe0, 0x01, 0xb3, 0x82, 0x20, 0x04, 0xa3, 0x80,
153 0x00, 0x00, 0x7a, 0xcb, 0x03, 0x00, 0xa8, 0x18,
154 0x00, 0x00, 0x10, 0x39, 0x08, 0x04, 0xea, 0x10,
155 0x08, 0x04, 0x7a, 0x10, 0x20, 0x00, 0x00, 0x80,
156 0x40, 0x00, 0x21, 0xcb, 0x0c, 0x00, 0xe8, 0x10,
157 0x00, 0x00, 0x41, 0x02, 0x0c, 0x00, 0xeb, 0x10,
158 0xf2, 0x01, 0x00, 0x82, 0x40, 0x21, 0x33, 0x02,
159 0x08, 0x20, 0x61, 0x0a, 0xc4, 0x00, 0x04, 0x19,
160 0xc7, 0x00, 0x00, 0x99, 0x02, 0x00, 0x61, 0x0a,
161 0x0c, 0xe8, 0x04, 0x14, 0x01, 0x00, 0x61, 0x0a,
162 0x03, 0x00, 0x48, 0x0a, 0x00, 0xb8, 0x04, 0x54,
163 0xc3, 0x00, 0x04, 0x19, 0x0c, 0xb8, 0x00, 0x44,
164 0x08, 0x00, 0xc8, 0x0a, 0x0c, 0xb8, 0x04, 0x54,
165 0xc8, 0x00, 0x04, 0x19, 0x0a, 0x00, 0x61, 0x0a,
166 0x09, 0x00, 0x48, 0x0a, 0x00, 0x68, 0x04, 0x54,
167 0xc9, 0x00, 0x04, 0x19, 0x0c, 0x68, 0x00, 0x44,
168 0x0b, 0x00, 0xc8, 0x0a, 0x0c, 0x68, 0x04, 0x54,
169 0xcb, 0x00, 0x04, 0x19, 0x04, 0x00, 0x61, 0x0a,
170 0x06, 0x00, 0x48, 0x0a, 0x00, 0x78, 0x04, 0x54,
171 0xc6, 0x00, 0x04, 0x19, 0x0c, 0x78, 0x00, 0x44,
172 0x05, 0x00, 0xc8, 0x0a, 0x0c, 0x78, 0x04, 0x54,
173 0xc5, 0x00, 0x04, 0x19, 0x07, 0x00, 0x61, 0x0a,
174 0x0c, 0x00, 0x48, 0x0a, 0x00, 0xe8, 0x04, 0x54,
175 0xcc, 0x00, 0x04, 0x19, 0x0c, 0xe8, 0x00, 0x44,
176 0x0e, 0x00, 0xc8, 0x0a, 0x0c, 0xe8, 0x04, 0x54,
177 0xce, 0x00, 0x04, 0x19, 0x00, 0x00, 0x40, 0x45,
178 0x20, 0x10, 0x71, 0x8b, 0x09, 0x3f, 0x07, 0x00
179};
180
181static unsigned char alaw_main[] = {
182 0x00, 0x10, 0x00, 0x44, 0x08, 0x00, 0x00, 0x44,
183 0x00, 0xb1, 0x00, 0x44, 0x00, 0x61, 0x00, 0x44,
184 0x08, 0x50, 0x00, 0x44, 0x0d, 0xf2, 0x61, 0xa8,
185 0x44, 0x04, 0x04, 0x19, 0x00, 0x00, 0x40, 0x45,
186 0x40, 0x49, 0x39, 0xac, 0x55, 0x55, 0x71, 0x8b,
187 0x50, 0x05, 0x63, 0x80, 0x00, 0x00, 0x06, 0x39,
188 0xff, 0x2e, 0x21, 0x49, 0xff, 0x0f, 0xd4, 0x49,
189 0x20, 0x01, 0x09, 0x0e, 0x20, 0x00, 0x71, 0x8b,
190 0xa8, 0x01, 0xa8, 0x80, 0x88, 0x01, 0xa8, 0x80,
191 0xa8, 0x00, 0x00, 0x80, 0xd2, 0x00, 0x71, 0x8b,
192 0x88, 0x00, 0xa8, 0x80, 0xa8, 0x04, 0xb3, 0x80,
193 0x20, 0x07, 0xb3, 0x80, 0x88, 0x03, 0xb1, 0x80,
194 0xc0, 0x00, 0x09, 0x5c, 0xc2, 0x01, 0x00, 0x82,
195 0xa1, 0x00, 0x71, 0x8b, 0xcd, 0x00, 0x04, 0x19,
196 0x21, 0x20, 0x71, 0x8b, 0xcf, 0x00, 0x04, 0x19,
197 0x00, 0x00, 0xb1, 0x80, 0xc2, 0x00, 0x04, 0x19,
198 0x00, 0x40, 0x00, 0x14, 0x08, 0x40, 0x04, 0x24,
199 0x00, 0x00, 0x34, 0x49, 0x0c, 0x40, 0x00, 0x44,
200 0x44, 0x04, 0x04, 0x39, 0x00, 0x00, 0x40, 0x45,
201 0x32, 0x00, 0x09, 0x5c, 0x00, 0x00, 0x0c, 0x39,
202 0x00, 0x00, 0x40, 0x45, 0x40, 0x40, 0x09, 0xef,
203 0xff, 0x20, 0x09, 0xcf, 0x00, 0x04, 0x63, 0xa1,
204 0x50, 0x03, 0x33, 0x80, 0x00, 0x04, 0xa3, 0x80,
205 0x00, 0xff, 0xc2, 0x8b, 0x00, 0xd0, 0x04, 0x54,
206 0x04, 0xe0, 0x00, 0xc4, 0x20, 0x03, 0x80, 0xc0,
207 0x30, 0x00, 0x00, 0x88, 0x00, 0x00, 0x7a, 0x0a,
208 0xd0, 0x01, 0x00, 0x82, 0x00, 0x60, 0x00, 0x44,
209 0xc0, 0x00, 0x00, 0x99, 0x00, 0x60, 0x00, 0x44,
210 0x00, 0xff, 0xc2, 0x8b, 0x20, 0x00, 0x00, 0x80,
211 0x00, 0x0d, 0x42, 0x8b, 0x08, 0x32, 0x00, 0xc4,
212 0x00, 0x0e, 0x42, 0x8b, 0x00, 0xa2, 0x00, 0xc4,
213 0x00, 0x1e, 0x42, 0x8b, 0x0c, 0xb2, 0x00, 0xc4,
214 0x00, 0x8e, 0x42, 0x8b, 0x00, 0x62, 0x00, 0xc4,
215 0x00, 0x9e, 0x42, 0x8b, 0x08, 0x52, 0x00, 0xc4,
216 0x00, 0xbe, 0x42, 0x8b, 0x08, 0x52, 0x00, 0xc4,
217 0x00, 0x04, 0x42, 0x8b, 0x04, 0x72, 0x00, 0xc4,
218 0x00, 0x24, 0x42, 0x8b, 0x00, 0xd2, 0x00, 0xc4,
219 0x00, 0x55, 0x42, 0x8b, 0x00, 0x60, 0x00, 0xc4,
220 0x00, 0x00, 0x40, 0x45, 0x20, 0x01, 0x79, 0x80,
221 0x00, 0x30, 0x42, 0x8b, 0x08, 0x82, 0x00, 0xc4,
222 0x00, 0x00, 0x40, 0x45, 0x00, 0x00, 0x71, 0x8b,
223 0x40, 0x01, 0x00, 0x80, 0x00, 0x60, 0x00, 0x44,
224 0xff, 0x00, 0xe2, 0xab, 0x00, 0xb2, 0x00, 0xc4,
225 0x0f, 0xf2, 0xa8, 0xa8, 0x20, 0x00, 0xb1, 0x88,
226 0x00, 0x00, 0x41, 0x02, 0x4d, 0xf2, 0x00, 0x39,
227 0xc0, 0x01, 0x00, 0x82, 0x00, 0x60, 0x00, 0x44,
228 0x0d, 0xf2, 0xa3, 0xa8, 0x4d, 0xf2, 0x00, 0x39,
229 0x00, 0x60, 0x00, 0x44, 0xff, 0x00, 0xe2, 0xab,
230 0x20, 0x00, 0x00, 0x88, 0x00, 0x00, 0x61, 0x02,
231 0x4d, 0xf2, 0x04, 0x19, 0x00, 0x60, 0x00, 0x44,
232 0xff, 0x00, 0xe2, 0xab, 0xa0, 0x00, 0x00, 0x88,
233 0x00, 0x00, 0x61, 0x10, 0x4d, 0xf2, 0x04, 0x19,
234 0x00, 0x60, 0x00, 0x44, 0xff, 0x20, 0xe2, 0xab,
235 0x60, 0x00, 0x00, 0x88, 0x00, 0x00, 0x71, 0xc0,
236 0x4d, 0xf2, 0x04, 0x19, 0x00, 0x60, 0x00, 0x44,
237 0x00, 0x00, 0x79, 0x80, 0x00, 0xe2, 0x00, 0x84,
238 0x03, 0x03, 0x04, 0x49, 0x04, 0xc2, 0x00, 0x54,
239 0x00, 0x60, 0x04, 0x64, 0x00, 0x60, 0x00, 0x44,
240 0x00, 0x00, 0x63, 0x80, 0x00, 0x00, 0x06, 0x19,
241 0x03, 0x00, 0x04, 0x49, 0x00, 0x60, 0x00, 0x44,
242 0x20, 0x01, 0x63, 0x80, 0x00, 0x00, 0x06, 0x19,
243 0x00, 0x20, 0xe2, 0x8b, 0x0c, 0xf2, 0x00, 0x84,
244 0xbe, 0x00, 0x51, 0x8b, 0xc0, 0x20, 0x00, 0x39,
245 0x08, 0x01, 0x00, 0x44, 0xec, 0x00, 0x51, 0x8b,
246 0xc0, 0x20, 0x00, 0x39, 0x00, 0x02, 0xe2, 0x8b,
247 0x04, 0x21, 0x00, 0x84, 0x3f, 0x00, 0x51, 0x8b,
248 0xc2, 0x20, 0x00, 0x39, 0x00, 0x11, 0x00, 0x44,
249 0x3d, 0x00, 0x51, 0x8b, 0xc2, 0x20, 0x00, 0x39,
250 0xe5, 0x00, 0x71, 0x8b, 0xcd, 0x00, 0x00, 0x39,
251 0x00, 0x00, 0xb1, 0x80, 0xc9, 0x20, 0x04, 0x19,
252 0xcb, 0x20, 0x04, 0x19, 0xc1, 0x20, 0x04, 0x19,
253 0xc3, 0x20, 0x04, 0x19, 0x10, 0x00, 0x71, 0x8b,
254 0xc7, 0x20, 0x04, 0x19, 0xde, 0x00, 0x51, 0x8b,
255 0xcf, 0x00, 0x00, 0x39, 0x00, 0x01, 0xb1, 0x80,
256 0xc4, 0x20, 0x04, 0x19, 0xc6, 0x20, 0x04, 0x19,
257 0xc8, 0x20, 0x04, 0x19, 0xca, 0x20, 0x04, 0x19,
258 0x20, 0x00, 0x71, 0x8b, 0xcc, 0x20, 0x04, 0x19,
259 0x03, 0x00, 0x04, 0x49, 0x00, 0x60, 0x00, 0x44,
260 0x09, 0x04, 0x61, 0xa8, 0xc1, 0x00, 0x04, 0x19,
261 0x0b, 0x04, 0x61, 0xa8, 0xca, 0x00, 0x04, 0x19,
262 0x04, 0x60, 0x00, 0xd4, 0x0d, 0x00, 0x61, 0x0a,
263 0x90, 0x40, 0x09, 0x8f, 0x00, 0x01, 0x00, 0x45,
264 0x0f, 0x00, 0x61, 0x0a, 0x00, 0x40, 0x09, 0x8f,
265 0x00, 0x01, 0x00, 0x45, 0x82, 0x00, 0x09, 0x2e,
266 0x80, 0x40, 0x09, 0xcf, 0x02, 0x00, 0x61, 0x22,
267 0x43, 0x25, 0x61, 0x22, 0x40, 0x33, 0x00, 0x80,
268 0x08, 0x48, 0x00, 0x44, 0x20, 0xb1, 0x49, 0x5c,
269 0x92, 0x00, 0x09, 0x4e, 0x02, 0x03, 0x09, 0x2e,
270 0x00, 0x00, 0xa3, 0x02, 0xc0, 0x00, 0x71, 0xc0,
271 0x20, 0x00, 0xeb, 0x80, 0x00, 0x04, 0xc2, 0x8b,
272 0x20, 0x04, 0x61, 0x80, 0x00, 0x04, 0x7a, 0x02,
273 0xc0, 0x00, 0x00, 0x82, 0x0c, 0xc3, 0x08, 0x49,
274 0xb0, 0x01, 0xf3, 0x80, 0x00, 0x00, 0x10, 0x39,
275 0x20, 0x00, 0x0c, 0x89, 0x0c, 0x88, 0x08, 0x49,
276 0x03, 0x00, 0xa8, 0x18, 0x00, 0x00, 0x10, 0x39,
277 0xbd, 0xff, 0x62, 0x8b, 0x20, 0x01, 0x00, 0x80,
278 0x00, 0x00, 0x63, 0xcb, 0x00, 0x00, 0x7a, 0x02,
279 0x40, 0x00, 0x01, 0x5b, 0x20, 0x00, 0x00, 0x80,
280 0x00, 0x00, 0x4a, 0xcb, 0x20, 0x00, 0x13, 0x80,
281 0x20, 0x00, 0x7a, 0x80, 0xe0, 0x21, 0x00, 0xc0,
282 0x08, 0x00, 0x08, 0x49, 0x10, 0x41, 0x09, 0x8e,
283 0xae, 0xae, 0x62, 0x8b, 0x00, 0x04, 0x61, 0x22,
284 0x00, 0x03, 0x00, 0x45, 0x22, 0x01, 0x33, 0x80,
285 0x20, 0x01, 0xa3, 0x02, 0x00, 0x00, 0x7a, 0x80,
286 0xc0, 0x00, 0x00, 0x82, 0x07, 0x20, 0x40, 0x0a,
287 0x08, 0xa3, 0x00, 0x84, 0x40, 0x21, 0x00, 0x80,
288 0x40, 0x05, 0x93, 0x10, 0xc7, 0x20, 0x00, 0x39,
289 0x00, 0x00, 0x40, 0x45, 0x07, 0x20, 0x40, 0x0a,
290 0x0c, 0x93, 0x00, 0x84, 0x08, 0x00, 0x00, 0x82,
291 0x0c, 0x24, 0x61, 0x50, 0x40, 0x01, 0x00, 0x80,
292 0xc7, 0x20, 0x00, 0x39, 0x00, 0x00, 0x40, 0x45,
293 0x00, 0x04, 0x63, 0x80, 0x00, 0x00, 0x06, 0x39,
294 0x42, 0x01, 0x09, 0x0e, 0x02, 0x20, 0x61, 0x0a,
295 0x00, 0x01, 0x00, 0x45, 0x0c, 0x20, 0x60, 0x0a,
296 0x00, 0xc3, 0x00, 0x84, 0x00, 0x04, 0xb1, 0x80,
297 0x00, 0x00, 0x06, 0x39, 0x0c, 0x61, 0x04, 0xd4,
298 0x00, 0x24, 0x71, 0xc0, 0x20, 0x33, 0x33, 0xc0,
299 0xe0, 0x01, 0xa3, 0x82, 0x22, 0x03, 0x7a, 0x02,
300 0xc3, 0x01, 0xa3, 0x82, 0x20, 0x01, 0x33, 0x80,
301 0x00, 0x00, 0x7a, 0x80, 0xc2, 0x01, 0xb3, 0x50,
302 0xcc, 0x20, 0x00, 0x39, 0x00, 0x00, 0x71, 0x80,
303 0x00, 0x08, 0x00, 0x44, 0x0c, 0x20, 0x60, 0x0a,
304 0x00, 0xf3, 0x00, 0x84, 0x00, 0x04, 0xb1, 0x80,
305 0x00, 0x00, 0x06, 0x39, 0x0c, 0x61, 0x04, 0xd4,
306 0x00, 0x00, 0x71, 0xc0, 0x00, 0x00, 0x93, 0x10,
307 0xcc, 0x20, 0x00, 0x39, 0x00, 0x08, 0x00, 0x44,
308 0xcc, 0x20, 0x00, 0x39, 0x00, 0x20, 0x00, 0xc0,
309 0x00, 0x30, 0x71, 0xc0, 0x00, 0x08, 0x00, 0x44,
310 0x20, 0x01, 0x00, 0x80, 0xae, 0xae, 0x62, 0x8b,
311 0x20, 0x01, 0x33, 0x80, 0x00, 0x00, 0x83, 0x80,
312 0x20, 0x00, 0x7a, 0x80, 0x20, 0xa1, 0x49, 0x5c,
313 0x82, 0x00, 0x09, 0x6e, 0x80, 0x4a, 0x09, 0x8e,
314 0xe0, 0x01, 0xb3, 0x82, 0x20, 0x04, 0xa3, 0x80,
315 0x00, 0x00, 0x7a, 0xcb, 0x28, 0x04, 0xea, 0x10,
316 0x0c, 0x04, 0x7a, 0x10, 0x70, 0x00, 0xc0, 0x8b,
317 0x00, 0x00, 0x10, 0x39, 0x90, 0x03, 0x00, 0x80,
318 0x40, 0x00, 0x21, 0x5b, 0x90, 0x00, 0x61, 0x80,
319 0x0c, 0x8a, 0x08, 0x49, 0x00, 0x00, 0x1c, 0x19,
320 0x40, 0x00, 0x08, 0x5b, 0x08, 0x00, 0x08, 0x49,
321 0x20, 0x02, 0x00, 0x80, 0x03, 0x00, 0xa8, 0x18,
322 0x00, 0x00, 0x14, 0x19, 0x40, 0x00, 0x21, 0xcb,
323 0x00, 0x00, 0x41, 0x02, 0x00, 0x00, 0xeb, 0x80,
324 0xf2, 0x01, 0x00, 0x82, 0x40, 0x21, 0x33, 0x02,
325 0x08, 0x20, 0x61, 0x0a, 0xc4, 0x00, 0x04, 0x19,
326 0xc7, 0x00, 0x00, 0x99, 0x02, 0x00, 0x61, 0x0a,
327 0x0c, 0x0a, 0x04, 0x14, 0x01, 0x00, 0x61, 0x0a,
328 0x03, 0x00, 0x48, 0x0a, 0x00, 0x58, 0x04, 0x54,
329 0xc3, 0x00, 0x04, 0x19, 0x0c, 0x58, 0x00, 0x44,
330 0x08, 0x00, 0xc8, 0x0a, 0x0c, 0x58, 0x04, 0x54,
331 0xc8, 0x00, 0x04, 0x19, 0x0a, 0x00, 0x61, 0x0a,
332 0x09, 0x00, 0x48, 0x0a, 0x00, 0xc8, 0x04, 0x54,
333 0xc9, 0x00, 0x04, 0x19, 0x0c, 0xc8, 0x00, 0x44,
334 0x0b, 0x00, 0xc8, 0x0a, 0x0c, 0xc8, 0x04, 0x54,
335 0xcb, 0x00, 0x04, 0x19, 0x04, 0x00, 0x61, 0x0a,
336 0x06, 0x00, 0x48, 0x0a, 0x00, 0xd8, 0x04, 0x54,
337 0xc6, 0x00, 0x04, 0x19, 0x0c, 0xd8, 0x00, 0x44,
338 0x05, 0x00, 0xc8, 0x0a, 0x0c, 0xd8, 0x04, 0x54,
339 0xc5, 0x00, 0x04, 0x19, 0x07, 0x00, 0x61, 0x0a,
340 0x0c, 0x00, 0x48, 0x0a, 0x00, 0x0a, 0x04, 0x54,
341 0xcc, 0x00, 0x04, 0x19, 0x0c, 0x0a, 0x00, 0x44,
342 0x0e, 0x00, 0xc8, 0x0a, 0x0c, 0x0a, 0x04, 0x54,
343 0xce, 0x00, 0x04, 0x19, 0x00, 0x00, 0x40, 0x45,
344 0x20, 0x10, 0x71, 0x8b, 0x08, 0x42, 0x06, 0x00
345};
346
347
348static unsigned char ima_adpcm_init[] = {
349 0x00, 0x10, 0x00, 0x44, 0x00, 0x00, 0x40, 0x45,
350 0x00, 0x00, 0x40, 0x45, 0x00, 0x00, 0x40, 0x45,
351 0x00, 0x00, 0x40, 0x45, 0xaa, 0xaa, 0x71, 0x8b,
352 0x44, 0x04, 0x04, 0x19, 0x00, 0x00, 0x40, 0x45,
353 0xff, 0x6e, 0x21, 0x49, 0xff, 0x0f, 0xd4, 0x49,
354 0x40, 0x49, 0x39, 0xac, 0x55, 0x55, 0x71, 0x8b,
355 0x50, 0x05, 0xb1, 0x80, 0x62, 0x00, 0x19, 0x0e,
356 0x21, 0x00, 0x71, 0x8b, 0x88, 0x00, 0x00, 0x80,
357 0xb0, 0x00, 0x71, 0x8b, 0x88, 0x00, 0x00, 0x80,
358 0x40, 0x00, 0x71, 0x8b, 0x88, 0x00, 0x00, 0x80,
359 0x60, 0x00, 0x71, 0x8b, 0x88, 0x00, 0x00, 0x80,
360 0x50, 0x00, 0x71, 0x8b, 0x88, 0x00, 0x00, 0x80,
361 0x70, 0x00, 0x71, 0x8b, 0x88, 0x00, 0x00, 0x80,
362 0xc0, 0x00, 0x71, 0x8b, 0x88, 0x00, 0x00, 0x80,
363 0xe0, 0x00, 0x71, 0x8b, 0x88, 0x00, 0x00, 0x80,
364 0xd0, 0x00, 0x71, 0x8b, 0x88, 0x00, 0x00, 0x80,
365 0x02, 0x00, 0x71, 0x8b, 0x88, 0x00, 0x00, 0x80,
366 0x22, 0x00, 0x71, 0x8b, 0x88, 0x00, 0x00, 0x80,
367 0x32, 0x00, 0x71, 0x8b, 0x88, 0x00, 0x00, 0x80,
368 0xa2, 0x00, 0x71, 0x8b, 0x88, 0x00, 0x00, 0x80,
369 0xb2, 0x00, 0x71, 0x8b, 0x88, 0x00, 0x00, 0x80,
370 0x62, 0x00, 0x71, 0x8b, 0x88, 0x00, 0x00, 0x80,
371 0xc2, 0x00, 0x71, 0x8b, 0x88, 0x00, 0x00, 0x80,
372 0xf2, 0x00, 0x71, 0x8b, 0x88, 0x00, 0x00, 0x80,
373 0x11, 0x00, 0x71, 0x8b, 0x88, 0x00, 0x00, 0x80,
374 0xa1, 0x00, 0x71, 0x8b, 0x88, 0x00, 0x00, 0x80,
375 0x61, 0x00, 0x71, 0x8b, 0x88, 0x00, 0x00, 0x80,
376 0xe1, 0x00, 0x71, 0x8b, 0x88, 0x00, 0x00, 0x80,
377 0x13, 0x00, 0x71, 0x8b, 0x88, 0x00, 0x00, 0x80,
378 0xb3, 0x00, 0x71, 0x8b, 0x88, 0x00, 0x00, 0x80,
379 0xc3, 0x00, 0x71, 0x8b, 0x88, 0x00, 0x00, 0x80,
380 0x18, 0x00, 0x71, 0x8b, 0x88, 0x00, 0x00, 0x80,
381 0x68, 0x00, 0x71, 0x8b, 0x88, 0x00, 0x00, 0x80,
382 0x0a, 0x00, 0x71, 0x8b, 0x88, 0x00, 0x00, 0x80,
383 0x4a, 0x00, 0x71, 0x8b, 0x88, 0x00, 0x00, 0x80,
384 0x29, 0x00, 0x71, 0x8b, 0x88, 0x00, 0x00, 0x80,
385 0x79, 0x00, 0x71, 0x8b, 0x88, 0x00, 0x00, 0x80,
386 0x9b, 0x00, 0x71, 0x8b, 0x88, 0x00, 0x00, 0x80,
387 0x14, 0x00, 0x71, 0x8b, 0x88, 0x00, 0x00, 0x80,
388 0xf4, 0x00, 0x71, 0x8b, 0x88, 0x00, 0x00, 0x80,
389 0xe6, 0x00, 0x71, 0x8b, 0x88, 0x00, 0x00, 0x80,
390 0xe5, 0x00, 0x71, 0x8b, 0x88, 0x00, 0x00, 0x80,
391 0xd7, 0x00, 0x71, 0x8b, 0x88, 0x00, 0x00, 0x80,
392 0x2e, 0x00, 0x71, 0x8b, 0x88, 0x00, 0x00, 0x80,
393 0x9d, 0x00, 0x71, 0x8b, 0x88, 0x00, 0x00, 0x80,
394 0xef, 0x00, 0x71, 0x8b, 0x88, 0x00, 0x00, 0x80,
395 0xb2, 0x20, 0x71, 0x8b, 0x88, 0x00, 0x00, 0x80,
396 0x33, 0x20, 0x71, 0x8b, 0x88, 0x00, 0x00, 0x80,
397 0x2a, 0x20, 0x71, 0x8b, 0x88, 0x00, 0x00, 0x80,
398 0x3b, 0x20, 0x71, 0x8b, 0x88, 0x00, 0x00, 0x80,
399 0x46, 0x20, 0x71, 0x8b, 0x88, 0x00, 0x00, 0x80,
400 0x2c, 0x20, 0x71, 0x8b, 0x88, 0x00, 0x00, 0x80,
401 0xdd, 0x20, 0x71, 0x8b, 0x88, 0x00, 0x00, 0x80,
402 0x01, 0x10, 0x71, 0x8b, 0x88, 0x00, 0x00, 0x80,
403 0x9a, 0x10, 0x71, 0x8b, 0x88, 0x00, 0x00, 0x80,
404 0x16, 0x10, 0x71, 0x8b, 0x88, 0x00, 0x00, 0x80,
405 0x8e, 0x10, 0x71, 0x8b, 0x88, 0x00, 0x00, 0x80,
406 0xc2, 0x30, 0x71, 0x8b, 0x88, 0x00, 0x00, 0x80,
407 0xc9, 0x30, 0x71, 0x8b, 0x88, 0x00, 0x00, 0x80,
408 0x3c, 0x30, 0x71, 0x8b, 0x88, 0x00, 0x00, 0x80,
409 0x81, 0x80, 0x71, 0x8b, 0x88, 0x00, 0x00, 0x80,
410 0xd4, 0x80, 0x71, 0x8b, 0x88, 0x00, 0x00, 0x80,
411 0x10, 0xa0, 0x71, 0x8b, 0x88, 0x00, 0x00, 0x80,
412 0x34, 0xa0, 0x71, 0x8b, 0x88, 0x00, 0x00, 0x80,
413 0x02, 0x90, 0x71, 0x8b, 0x88, 0x00, 0x00, 0x80,
414 0x75, 0x90, 0x71, 0x8b, 0x88, 0x00, 0x00, 0x80,
415 0x9a, 0xb0, 0x71, 0x8b, 0x88, 0x00, 0x00, 0x80,
416 0x12, 0x40, 0x71, 0x8b, 0x88, 0x00, 0x00, 0x80,
417 0x0d, 0x40, 0x71, 0x8b, 0x88, 0x00, 0x00, 0x80,
418 0x3c, 0x60, 0x71, 0x8b, 0x88, 0x00, 0x00, 0x80,
419 0xe7, 0x50, 0x71, 0x8b, 0x88, 0x00, 0x00, 0x80,
420 0x0e, 0x70, 0x71, 0x8b, 0x88, 0x00, 0x00, 0x80,
421 0xff, 0xc0, 0x71, 0x8b, 0x88, 0x00, 0x00, 0x80,
422 0xc8, 0xd0, 0x71, 0x8b, 0x88, 0x00, 0x00, 0x80,
423 0x57, 0xf0, 0x71, 0x8b, 0x88, 0x00, 0x00, 0x80,
424 0xc8, 0x22, 0x71, 0x8b, 0x88, 0x00, 0x00, 0x80,
425 0xb0, 0x32, 0x71, 0x8b, 0x88, 0x00, 0x00, 0x80,
426 0xdd, 0x82, 0x71, 0x8b, 0x88, 0x00, 0x00, 0x80,
427 0x90, 0xb2, 0x71, 0x8b, 0x88, 0x00, 0x00, 0x80,
428 0x8a, 0x62, 0x71, 0x8b, 0x88, 0x00, 0x00, 0x80,
429 0xce, 0x72, 0x71, 0x8b, 0x88, 0x00, 0x00, 0x80,
430 0xa5, 0xd2, 0x71, 0x8b, 0x88, 0x00, 0x00, 0x80,
431 0x97, 0x21, 0x71, 0x8b, 0x88, 0x00, 0x00, 0x80,
432 0xa2, 0xa1, 0x71, 0x8b, 0x88, 0x00, 0x00, 0x80,
433 0x5c, 0x41, 0x71, 0x8b, 0x88, 0x00, 0x00, 0x80,
434 0xfe, 0xc1, 0x71, 0x8b, 0x88, 0x00, 0x00, 0x80,
435 0x7a, 0x23, 0x71, 0x8b, 0x88, 0x00, 0x00, 0x80,
436 0x78, 0x93, 0x71, 0x8b, 0x88, 0x00, 0x00, 0x80,
437 0x67, 0x73, 0x71, 0x8b, 0x88, 0x00, 0x00, 0x80,
438 0x17, 0x28, 0x71, 0x8b, 0x88, 0x00, 0x00, 0x80,
439 0x88, 0x48, 0x71, 0x8b, 0x88, 0x00, 0x00, 0x80,
440 0xdb, 0xf8, 0x71, 0x8b, 0x88, 0x00, 0x00, 0x80,
441 0x2b, 0xba, 0x71, 0x8b, 0x88, 0x00, 0x00, 0x80,
442 0xf1, 0x09, 0x71, 0x8b, 0x88, 0x00, 0x00, 0x80,
443 0xdc, 0x69, 0x71, 0x8b, 0x88, 0x00, 0x00, 0x80,
444 0x19, 0x8b, 0x71, 0x8b, 0x88, 0x00, 0x00, 0x80,
445 0xff, 0xfb, 0x71, 0x8b, 0x88, 0x00, 0x00, 0x80,
446 0x20, 0x00, 0x71, 0x8b, 0x88, 0x00, 0x00, 0x80,
447 0x52, 0x00, 0x71, 0x8b, 0xc2, 0x00, 0x00, 0x82,
448 0xff, 0xff, 0x71, 0x8b, 0xc2, 0x00, 0x00, 0x82,
449 0xc2, 0x00, 0x00, 0x82, 0xc2, 0x00, 0x00, 0x82,
450 0xc2, 0x00, 0x00, 0x82, 0x10, 0x00, 0x71, 0x8b,
451 0xc2, 0x00, 0x00, 0x82, 0x80, 0x00, 0x71, 0x8b,
452 0xc2, 0x00, 0x00, 0x82, 0x90, 0x00, 0x71, 0x8b,
453 0xc2, 0x00, 0x00, 0x82, 0x40, 0x00, 0x71, 0x8b,
454 0xc2, 0x00, 0x00, 0x82, 0xff, 0xff, 0x71, 0x8b,
455 0xc2, 0x00, 0x00, 0x82, 0xc2, 0x00, 0x00, 0x82,
456 0xc2, 0x00, 0x00, 0x82, 0xc2, 0x00, 0x00, 0x82,
457 0x10, 0x00, 0x71, 0x8b, 0xc2, 0x00, 0x00, 0x82,
458 0x80, 0x00, 0x71, 0x8b, 0xc2, 0x00, 0x00, 0x82,
459 0x90, 0x00, 0x71, 0x8b, 0xc2, 0x00, 0x00, 0x82,
460 0x40, 0x00, 0x71, 0x8b, 0xc2, 0x00, 0x00, 0x82,
461 0xff, 0xfb, 0x71, 0x8b, 0xc2, 0x00, 0x00, 0x82,
462 0x00, 0x04, 0x71, 0x8b, 0xc2, 0x00, 0x00, 0x82,
463 0x4a, 0x00, 0x71, 0x8b, 0xc2, 0x00, 0x00, 0x82,
464 0x00, 0x00, 0x71, 0x8b, 0xc2, 0x00, 0x00, 0x82,
465 0x00, 0x00, 0x71, 0x8b, 0xc2, 0x00, 0x00, 0x82,
466 0xc2, 0x00, 0x00, 0x82, 0xc2, 0x30, 0x04, 0x19,
467 0x10, 0x00, 0x09, 0x4f, 0xc2, 0x01, 0x00, 0x82,
468 0xc2, 0x01, 0x00, 0x82, 0xc2, 0x01, 0x00, 0x82,
469 0xc2, 0x01, 0x00, 0x82, 0xc2, 0x01, 0x00, 0x82,
470 0xc2, 0x01, 0x00, 0x82, 0xc2, 0x01, 0x00, 0x82,
471 0xc2, 0x01, 0x00, 0x82, 0xc2, 0x01, 0x00, 0x82,
472 0xc2, 0x01, 0x00, 0x82, 0xc2, 0x01, 0x00, 0x82,
473 0xc2, 0x01, 0x00, 0x82, 0xc2, 0x01, 0x00, 0x82,
474 0x00, 0x10, 0x71, 0x8b, 0xc1, 0x30, 0x04, 0x19,
475 0x93, 0x00, 0x01, 0x4f, 0xcd, 0x30, 0x00, 0x09,
476 0xcf, 0x30, 0x00, 0x09, 0x00, 0x00, 0x34, 0x49,
477 0x00, 0x08, 0x00, 0x44, 0xc8, 0x54, 0x11, 0x00
478};
479
480static unsigned char ima_adpcm_playback[] = {
481 0x00, 0x10, 0x00, 0x44, 0x08, 0x00, 0x00, 0x44,
482 0x0c, 0x50, 0x00, 0x44, 0x00, 0x70, 0x00, 0x44,
483 0x04, 0x70, 0x00, 0x44, 0x0d, 0xf2, 0x61, 0xa8,
484 0x44, 0x04, 0x04, 0x19, 0x00, 0x00, 0x40, 0x45,
485 0x00, 0x04, 0x63, 0x80, 0x00, 0x00, 0x06, 0x39,
486 0xff, 0x2e, 0x21, 0x49, 0xff, 0x0d, 0xd4, 0x49,
487 0x40, 0x49, 0x39, 0xac, 0x55, 0x55, 0x71, 0x8b,
488 0x50, 0x01, 0xb1, 0x80, 0x00, 0x01, 0xb1, 0x80,
489 0xc9, 0x20, 0x04, 0x19, 0x51, 0x00, 0x71, 0x8b,
490 0xcd, 0x00, 0x04, 0x19, 0xe4, 0x20, 0x71, 0x8b,
491 0xcf, 0x00, 0x04, 0x19, 0x80, 0x00, 0x71, 0x8b,
492 0xcb, 0x20, 0x04, 0x19, 0x10, 0x00, 0x71, 0x8b,
493 0xc4, 0x20, 0x04, 0x19, 0x65, 0x00, 0x51, 0x8b,
494 0xc2, 0x20, 0x00, 0x39, 0x00, 0x00, 0xb1, 0x80,
495 0xc2, 0x30, 0x04, 0x19, 0x00, 0x00, 0x63, 0x80,
496 0xc1, 0xa0, 0x04, 0x19, 0x93, 0x00, 0x01, 0x4f,
497 0xcd, 0x30, 0x00, 0x09, 0xcf, 0x30, 0x00, 0x09,
498 0x04, 0x40, 0x00, 0x14, 0x0c, 0x40, 0x00, 0x14,
499 0x00, 0x04, 0x61, 0xa8, 0x02, 0x04, 0x61, 0xa8,
500 0x04, 0x60, 0x04, 0x24, 0x00, 0x00, 0x34, 0x49,
501 0x00, 0x50, 0x00, 0x44, 0x44, 0x04, 0x04, 0x39,
502 0x00, 0x00, 0x40, 0x45, 0x00, 0x00, 0x40, 0x45,
503 0x0f, 0x00, 0x61, 0x0a, 0x00, 0x01, 0x00, 0x45,
504 0x40, 0x40, 0x09, 0xef, 0xff, 0x20, 0x09, 0xcf,
505 0x00, 0x04, 0x63, 0xa1, 0x50, 0x03, 0x33, 0x80,
506 0x00, 0x04, 0xa3, 0x80, 0x00, 0xff, 0xc2, 0x8b,
507 0x08, 0xf0, 0x04, 0x54, 0x0c, 0xd0, 0x00, 0xc4,
508 0x20, 0x03, 0x80, 0xc0, 0x30, 0x00, 0x00, 0x88,
509 0x00, 0x00, 0x7a, 0x0a, 0xd0, 0x01, 0x00, 0x82,
510 0x08, 0x50, 0x00, 0x44, 0xc0, 0x00, 0x00, 0x99,
511 0x08, 0x50, 0x00, 0x44, 0x00, 0xff, 0xc2, 0x8b,
512 0x20, 0x00, 0x00, 0x80, 0x00, 0x0d, 0x42, 0x8b,
513 0x00, 0xa2, 0x00, 0xc4, 0x00, 0x0e, 0x42, 0x8b,
514 0x0c, 0x92, 0x00, 0xc4, 0x00, 0x1e, 0x42, 0x8b,
515 0x04, 0x62, 0x00, 0xc4, 0x00, 0x8e, 0x42, 0x8b,
516 0x0c, 0x52, 0x00, 0xc4, 0x00, 0x9e, 0x42, 0x8b,
517 0x00, 0xc2, 0x00, 0xc4, 0x00, 0xbe, 0x42, 0x8b,
518 0x00, 0xc2, 0x00, 0xc4, 0x00, 0x04, 0x42, 0x8b,
519 0x00, 0xf2, 0x00, 0xc4, 0x00, 0x24, 0x42, 0x8b,
520 0x00, 0x91, 0x00, 0xc4, 0x00, 0x55, 0x42, 0x8b,
521 0x08, 0x50, 0x00, 0xc4, 0x00, 0x3f, 0x42, 0x8b,
522 0x08, 0xe2, 0x00, 0xc4, 0x00, 0x00, 0x40, 0x45,
523 0x20, 0x01, 0x79, 0x80, 0x00, 0x30, 0x42, 0x8b,
524 0x00, 0x92, 0x00, 0xc4, 0x00, 0x00, 0x40, 0x45,
525 0x00, 0x00, 0x71, 0x8b, 0x40, 0x01, 0x00, 0x80,
526 0x08, 0x50, 0x00, 0x44, 0xff, 0x00, 0xe2, 0xab,
527 0x0c, 0x42, 0x00, 0xc4, 0x0f, 0xf2, 0xa8, 0xa8,
528 0x20, 0x00, 0xb1, 0x88, 0x00, 0x00, 0x41, 0x02,
529 0x4d, 0xf2, 0x00, 0x39, 0xc0, 0x01, 0x00, 0x82,
530 0x08, 0x50, 0x00, 0x44, 0x0d, 0xf2, 0xa3, 0xa8,
531 0x4d, 0xf2, 0x00, 0x39, 0x08, 0x50, 0x00, 0x44,
532 0xff, 0x00, 0xe2, 0xab, 0x20, 0x00, 0x00, 0x88,
533 0x00, 0x00, 0x61, 0x02, 0x4d, 0xf2, 0x04, 0x19,
534 0x08, 0x50, 0x00, 0x44, 0xff, 0x00, 0xe2, 0xab,
535 0xa0, 0x00, 0x00, 0x88, 0x00, 0x00, 0x61, 0x10,
536 0x4d, 0xf2, 0x04, 0x19, 0x08, 0x50, 0x00, 0x44,
537 0xff, 0x20, 0xe2, 0xab, 0x60, 0x00, 0x00, 0x88,
538 0x00, 0x00, 0x71, 0xc0, 0x4d, 0xf2, 0x04, 0x19,
539 0x08, 0x50, 0x00, 0x44, 0x00, 0x00, 0x7a, 0x0a,
540 0x20, 0x01, 0xf0, 0x80, 0x01, 0xa0, 0x41, 0x0a,
541 0x04, 0xd2, 0x00, 0xc4, 0x20, 0x01, 0xf0, 0x80,
542 0xc1, 0x30, 0x04, 0x19, 0x08, 0x50, 0x00, 0x44,
543 0x00, 0x00, 0x79, 0x80, 0x00, 0xa1, 0x00, 0x84,
544 0xb5, 0x00, 0x51, 0x8b, 0xcf, 0x00, 0x00, 0x39,
545 0x00, 0x01, 0xb1, 0x80, 0x88, 0x00, 0x04, 0x19,
546 0x8a, 0x00, 0x04, 0x19, 0xc8, 0x20, 0x04, 0x19,
547 0xca, 0x20, 0x04, 0x19, 0xc2, 0x30, 0x04, 0x19,
548 0xcd, 0x10, 0x04, 0x19, 0xcf, 0x10, 0x04, 0x19,
549 0xb0, 0x00, 0x71, 0x8b, 0x8c, 0x00, 0x04, 0x19,
550 0x8e, 0x00, 0x04, 0x19, 0x10, 0x00, 0x71, 0x8b,
551 0xc4, 0x20, 0x04, 0x19, 0x93, 0x00, 0x01, 0x4f,
552 0xcd, 0x30, 0x00, 0x09, 0xcf, 0x30, 0x00, 0x09,
553 0x03, 0x03, 0x04, 0x49, 0x04, 0x81, 0x00, 0x54,
554 0x08, 0x50, 0x04, 0x64, 0x08, 0x50, 0x00, 0x44,
555 0x00, 0x00, 0x63, 0x80, 0x00, 0x00, 0x06, 0x19,
556 0x03, 0x00, 0x04, 0x49, 0x08, 0x50, 0x00, 0x44,
557 0x20, 0x01, 0x63, 0x80, 0x00, 0x00, 0x06, 0x19,
558 0x00, 0x02, 0xe2, 0x8b, 0x08, 0x41, 0x00, 0x84,
559 0x65, 0x00, 0x51, 0x8b, 0xc2, 0x20, 0x00, 0x39,
560 0x00, 0x00, 0x63, 0x80, 0xc1, 0xa0, 0x04, 0x19,
561 0x08, 0x61, 0x00, 0x44, 0x2d, 0x00, 0x51, 0x8b,
562 0xc2, 0x20, 0x00, 0x39, 0x00, 0x00, 0xb1, 0x80,
563 0xc1, 0xa0, 0x04, 0x19, 0x03, 0x00, 0x04, 0x49,
564 0x08, 0x50, 0x00, 0x44, 0x02, 0x20, 0x61, 0x0a,
565 0x00, 0x01, 0x00, 0x45, 0x02, 0x30, 0x61, 0x0a,
566 0x04, 0x03, 0x00, 0xc4, 0x05, 0xb0, 0xc8, 0x18,
567 0x04, 0x71, 0x00, 0xc4, 0x00, 0x13, 0x00, 0x44,
568 0x00, 0x79, 0x08, 0x44, 0x00, 0x04, 0x79, 0x80,
569 0x00, 0x49, 0x00, 0xc4, 0xca, 0x20, 0x04, 0x19,
570 0x4a, 0x04, 0x04, 0x19, 0xff, 0x00, 0xe2, 0x8b,
571 0x0c, 0xf9, 0x08, 0x44, 0xcf, 0x10, 0x04, 0x19,
572 0x0c, 0x2b, 0x08, 0x44, 0x8e, 0x00, 0x04, 0x19,
573 0x03, 0x30, 0x61, 0x0a, 0xc8, 0x20, 0x00, 0x39,
574 0x48, 0x04, 0x00, 0x39, 0x0a, 0x30, 0x61, 0x0a,
575 0x0c, 0xf9, 0x08, 0x44, 0xcd, 0x10, 0x04, 0x19,
576 0x0c, 0x2b, 0x08, 0x44, 0x8c, 0x00, 0x04, 0x19,
577 0x0c, 0xd9, 0x08, 0x44, 0x0c, 0x5a, 0x00, 0x44,
578 0x00, 0x79, 0x08, 0x44, 0x00, 0x04, 0x79, 0x80,
579 0x00, 0x49, 0x00, 0xc4, 0xc3, 0x30, 0x04, 0x19,
580 0xca, 0x30, 0x00, 0x99, 0x0c, 0xd9, 0x08, 0x44,
581 0x42, 0x0a, 0x09, 0x0e, 0x00, 0x01, 0x33, 0x11,
582 0x8c, 0x01, 0xa3, 0x80, 0x00, 0x01, 0x7a, 0x10,
583 0x80, 0x05, 0xb1, 0x80, 0x05, 0xb0, 0xe0, 0x18,
584 0x00, 0x93, 0x00, 0x84, 0x00, 0x79, 0x08, 0x44,
585 0x00, 0x04, 0x79, 0x80, 0x00, 0x49, 0x00, 0xc4,
586 0x0c, 0x1b, 0x08, 0x44, 0x88, 0x00, 0x04, 0x19,
587 0x8a, 0x00, 0x00, 0x99, 0x0c, 0xd9, 0x08, 0x44,
588 0x42, 0x0a, 0x09, 0x0e, 0x80, 0x00, 0x71, 0x8b,
589 0xc0, 0x04, 0xb1, 0x82, 0x10, 0x00, 0xe0, 0x0b,
590 0x00, 0x43, 0x00, 0x84, 0x02, 0x30, 0x61, 0x0a,
591 0x01, 0x30, 0xc8, 0x0a, 0x00, 0x43, 0x00, 0x84,
592 0x00, 0x00, 0xb1, 0x80, 0xc2, 0x30, 0x04, 0x19,
593 0x0c, 0xa8, 0x00, 0x44, 0x02, 0x30, 0x61, 0x0a,
594 0x00, 0xd3, 0x00, 0xc4, 0x05, 0xb0, 0xc8, 0x18,
595 0x04, 0x63, 0x00, 0xc4, 0x08, 0xf3, 0x00, 0x44,
596 0x00, 0x79, 0x08, 0x44, 0x00, 0x04, 0x79, 0x80,
597 0x00, 0x49, 0x00, 0xc4, 0x20, 0x00, 0x04, 0x19,
598 0xff, 0x00, 0xe2, 0x8b, 0x0c, 0xf9, 0x08, 0x44,
599 0xcd, 0x10, 0x04, 0x19, 0xcf, 0x10, 0x04, 0x19,
600 0x0c, 0x2b, 0x08, 0x44, 0x8c, 0x00, 0x04, 0x19,
601 0x8e, 0x00, 0x04, 0x19, 0x03, 0x30, 0x61, 0x0a,
602 0xc8, 0x20, 0x00, 0x39, 0xca, 0x20, 0x00, 0x39,
603 0x48, 0x04, 0x00, 0x39, 0x4a, 0x04, 0x00, 0x39,
604 0x0c, 0xd9, 0x08, 0x44, 0x0c, 0x5a, 0x00, 0x44,
605 0x00, 0x79, 0x08, 0x44, 0x00, 0x04, 0x79, 0x80,
606 0x00, 0x49, 0x00, 0xc4, 0xc3, 0x30, 0x04, 0x19,
607 0x0c, 0xd9, 0x08, 0x44, 0x42, 0x0a, 0x09, 0x0e,
608 0x05, 0xb0, 0xe0, 0x18, 0x00, 0x18, 0x00, 0x84,
609 0x00, 0x79, 0x08, 0x44, 0x00, 0x04, 0x79, 0x80,
610 0x00, 0x49, 0x00, 0xc4, 0x0c, 0x1b, 0x08, 0x44,
611 0x80, 0x01, 0x00, 0x80, 0x0c, 0xd9, 0x08, 0x44,
612 0x42, 0x0a, 0x09, 0x0e, 0x80, 0x00, 0x71, 0x8b,
613 0xc0, 0x04, 0xb1, 0x82, 0x10, 0x00, 0xe0, 0x0b,
614 0x00, 0x88, 0x00, 0x84, 0x02, 0x30, 0x61, 0x0a,
615 0x01, 0x30, 0xc8, 0x0a, 0x00, 0x88, 0x00, 0x84,
616 0x00, 0x00, 0xb1, 0x80, 0xc2, 0x30, 0x04, 0x19,
617 0x00, 0x01, 0x00, 0x11, 0x00, 0x0f, 0xe2, 0x8b,
618 0x00, 0x00, 0x41, 0xcb, 0x8c, 0x00, 0x00, 0x80,
619 0x00, 0x00, 0x48, 0xcb, 0x20, 0x00, 0x7a, 0x80,
620 0x80, 0x01, 0x00, 0x80, 0x82, 0x0c, 0x09, 0x6e,
621 0x03, 0x08, 0x09, 0x0e, 0x80, 0x40, 0x09, 0xcf,
622 0x00, 0x01, 0x71, 0xc2, 0x00, 0x08, 0xc2, 0x1b,
623 0x04, 0xb8, 0x00, 0xc4, 0x20, 0x05, 0xa8, 0x80,
624 0x20, 0x01, 0xf0, 0x80, 0x00, 0x01, 0xc2, 0x1b,
625 0x04, 0x48, 0x00, 0xc4, 0x20, 0x05, 0xa8, 0x80,
626 0x20, 0x01, 0xf0, 0x80, 0x00, 0x02, 0xc2, 0x1b,
627 0x04, 0x68, 0x00, 0xc4, 0x20, 0x05, 0xa8, 0x80,
628 0x20, 0x01, 0xf0, 0x80, 0x20, 0x03, 0xa8, 0x80,
629 0x00, 0x01, 0x00, 0x11, 0x00, 0x04, 0xc2, 0x8b,
630 0x08, 0x78, 0x00, 0xc4, 0x00, 0x00, 0xe9, 0x80,
631 0x05, 0xb0, 0xa8, 0x18, 0x00, 0x00, 0x4a, 0xcb,
632 0x20, 0x00, 0xa8, 0x22, 0xd0, 0x01, 0x00, 0x82,
633 0x40, 0x01, 0x00, 0x80, 0xc4, 0x00, 0x04, 0x19,
634 0xb0, 0x00, 0xe2, 0x8b, 0x06, 0x20, 0xa8, 0x0a,
635 0x2d, 0x10, 0x61, 0x0a, 0xd1, 0x08, 0x09, 0x2e,
636 0x00, 0x01, 0xa8, 0x02, 0x0c, 0xf9, 0x08, 0x44,
637 0xcd, 0x10, 0x04, 0x19, 0x0c, 0x2b, 0x08, 0x44,
638 0x03, 0x08, 0x09, 0x0e, 0x9a, 0x25, 0xb1, 0x60,
639 0xa2, 0x0e, 0x09, 0x6e, 0x03, 0x00, 0x09, 0x0f,
640 0x00, 0x01, 0x71, 0x82, 0x20, 0x01, 0x00, 0x80,
641 0x00, 0x00, 0x61, 0xcb, 0x80, 0x01, 0x00, 0x80,
642 0x03, 0x00, 0x09, 0x0f, 0x00, 0x01, 0x71, 0xc2,
643 0x00, 0x08, 0xc2, 0x1b, 0x0c, 0x2a, 0x00, 0xc4,
644 0x20, 0x05, 0xa8, 0x80, 0x20, 0x01, 0xf0, 0x80,
645 0x00, 0x01, 0xc2, 0x1b, 0x0c, 0x1a, 0x00, 0xc4,
646 0x20, 0x05, 0xa8, 0x80, 0x20, 0x01, 0xf0, 0x80,
647 0x00, 0x02, 0xc2, 0x1b, 0x0c, 0x3a, 0x00, 0xc4,
648 0x20, 0x05, 0xa8, 0x80, 0x20, 0x01, 0xf0, 0x80,
649 0x20, 0x03, 0xa8, 0x80, 0x00, 0x01, 0x00, 0x11,
650 0x00, 0x04, 0xc2, 0x8b, 0x04, 0xaa, 0x00, 0xc4,
651 0x00, 0x00, 0xe9, 0x80, 0x05, 0xb0, 0xa8, 0x18,
652 0x00, 0x00, 0x4a, 0xcb, 0x20, 0x00, 0xa8, 0x22,
653 0xd0, 0x01, 0x00, 0x82, 0x40, 0x01, 0x00, 0x80,
654 0xc7, 0x00, 0x04, 0x19, 0xb0, 0x00, 0xe2, 0x8b,
655 0x06, 0x20, 0xa8, 0x0a, 0x2f, 0x10, 0x61, 0x0a,
656 0xf1, 0x08, 0x09, 0x2e, 0x00, 0x01, 0xa8, 0x02,
657 0x0c, 0xf9, 0x08, 0x44, 0xcf, 0x10, 0x04, 0x19,
658 0x0c, 0x2b, 0x08, 0x44, 0x9f, 0x35, 0xb1, 0x60,
659 0x03, 0x08, 0x09, 0x0e, 0x00, 0x01, 0x71, 0x82,
660 0x20, 0x01, 0x00, 0x80, 0x00, 0x00, 0x61, 0xcb,
661 0x80, 0x01, 0x00, 0x80, 0xe4, 0x20, 0x71, 0x8b,
662 0x00, 0x01, 0x00, 0x45, 0x90, 0x40, 0x09, 0x8f,
663 0x00, 0x05, 0x63, 0x80, 0x00, 0x00, 0x06, 0x39,
664 0x08, 0x19, 0x04, 0xd4, 0x93, 0x00, 0x01, 0x4f,
665 0xe7, 0x00, 0x01, 0x6f, 0x0d, 0x30, 0x61, 0x0a,
666 0x20, 0x04, 0x61, 0xa8, 0xc2, 0x00, 0x00, 0x82,
667 0x02, 0x04, 0x61, 0xa8, 0xc2, 0x00, 0x00, 0x82,
668 0xcd, 0x30, 0x00, 0x09, 0x02, 0x00, 0x00, 0x02,
669 0x02, 0x00, 0x00, 0x02, 0xc0, 0x80, 0x00, 0x09,
670 0x20, 0x00, 0x09, 0x49, 0x0f, 0x30, 0x61, 0x0a,
671 0x0d, 0x30, 0xc8, 0x0a, 0x00, 0x29, 0x00, 0xc4,
672 0x00, 0x80, 0xc8, 0x0a, 0x00, 0x29, 0x00, 0xc4,
673 0x00, 0x04, 0xb1, 0x80, 0x00, 0x00, 0x06, 0x39,
674 0xc9, 0x20, 0x04, 0x39, 0x00, 0x39, 0x00, 0x44,
675 0x00, 0x04, 0x63, 0x80, 0x00, 0x00, 0x06, 0x39,
676 0x00, 0x04, 0xb1, 0x80, 0xc9, 0x20, 0x04, 0x39,
677 0x00, 0x39, 0x00, 0x44, 0x09, 0x20, 0x23, 0x0a,
678 0x00, 0x00, 0x06, 0x19, 0xc9, 0x20, 0x04, 0x19,
679 0x00, 0x00, 0x40, 0x45, 0x02, 0x00, 0x61, 0x0a,
680 0x0c, 0xb9, 0x04, 0x14, 0x04, 0x00, 0x61, 0x0a,
681 0x06, 0x00, 0x48, 0x0a, 0x00, 0xa9, 0x04, 0x54,
682 0xc6, 0x00, 0x04, 0x19, 0x0c, 0xa9, 0x00, 0x44,
683 0x05, 0x00, 0xc8, 0x0a, 0x0c, 0xa9, 0x04, 0x54,
684 0xc5, 0x00, 0x04, 0x19, 0x07, 0x00, 0x61, 0x0a,
685 0x0c, 0x00, 0x48, 0x0a, 0x00, 0xb9, 0x04, 0x54,
686 0xcc, 0x00, 0x04, 0x19, 0x0c, 0xb9, 0x00, 0x44,
687 0x0e, 0x00, 0xc8, 0x0a, 0x0c, 0xb9, 0x04, 0x54,
688 0xce, 0x00, 0x04, 0x19, 0x0c, 0x5a, 0x00, 0x44,
689 0x82, 0x0d, 0x09, 0x2e, 0x80, 0x40, 0x09, 0xcf,
690 0x00, 0xdf, 0x71, 0x8b, 0x80, 0x01, 0x00, 0x80,
691 0x02, 0xc1, 0x00, 0x22, 0x03, 0xc1, 0x00, 0x22,
692 0x00, 0x01, 0x65, 0x80, 0xd2, 0x05, 0x65, 0x82,
693 0x40, 0x21, 0x00, 0x80, 0xd3, 0x03, 0x00, 0x82,
694 0x40, 0x33, 0x00, 0x80, 0x0c, 0x5a, 0x00, 0x44,
695 0x0f, 0x30, 0x61, 0x0a, 0x0d, 0x30, 0xc8, 0x0a,
696 0x08, 0xd9, 0x00, 0xc4, 0x93, 0x00, 0x01, 0x4f,
697 0xe7, 0x00, 0x01, 0x6f, 0x0f, 0x30, 0x61, 0x0a,
698 0x20, 0x00, 0x00, 0x88, 0x02, 0x00, 0x61, 0x02,
699 0x02, 0x00, 0x00, 0x03, 0xcf, 0x30, 0x00, 0x09,
700 0x20, 0x00, 0x09, 0x49, 0x00, 0x04, 0x63, 0x80,
701 0x04, 0xd9, 0x00, 0x44, 0x00, 0x04, 0xb1, 0x80,
702 0x00, 0x00, 0x00, 0x46, 0x02, 0x30, 0x61, 0x0a,
703 0x05, 0xb0, 0xa8, 0x18, 0xc2, 0x30, 0x04, 0x19,
704 0x00, 0x00, 0x00, 0x46, 0x0e, 0x10, 0xc8, 0x0a,
705 0x0c, 0x0b, 0x04, 0x14, 0x0e, 0x10, 0x61, 0x0a,
706 0x04, 0x2b, 0x00, 0x44, 0x0c, 0x10, 0xc8, 0x0a,
707 0x04, 0x2b, 0x04, 0x54, 0x0c, 0x10, 0x61, 0x0a,
708 0x00, 0x00, 0x00, 0x46, 0x00, 0x10, 0xa8, 0x18,
709 0xa0, 0x00, 0x00, 0x88, 0x00, 0x01, 0x71, 0x82,
710 0x00, 0x00, 0x00, 0x46, 0x00, 0x04, 0x33, 0x80,
711 0x00, 0x00, 0x83, 0x80, 0x20, 0x04, 0x7a, 0x80,
712 0x20, 0x01, 0x33, 0x80, 0x00, 0x00, 0x83, 0x80,
713 0x20, 0x00, 0x7a, 0x80, 0x20, 0x03, 0x00, 0x80,
714 0x00, 0x00, 0x00, 0x46, 0x16, 0xce, 0x11, 0x00
715};
716
717static unsigned char ima_adpcm_capture[] = {
718 0x00, 0x10, 0x00, 0x44, 0x08, 0x00, 0x00, 0x44,
719 0x00, 0x70, 0x00, 0x44, 0x08, 0xd0, 0x00, 0x44,
720 0x00, 0xf0, 0x00, 0x44, 0x0d, 0xf2, 0x61, 0xa8,
721 0x44, 0x04, 0x04, 0x19, 0x00, 0x00, 0x40, 0x45,
722 0x00, 0x04, 0x63, 0x80, 0x00, 0x00, 0x06, 0x39,
723 0xff, 0x2e, 0x21, 0x49, 0xff, 0x0c, 0xd4, 0x49,
724 0x40, 0x49, 0x39, 0xac, 0x55, 0x55, 0x71, 0x8b,
725 0x50, 0x01, 0xb1, 0x80, 0x00, 0x00, 0x71, 0x8b,
726 0xc2, 0x30, 0x04, 0x19, 0xc0, 0xa0, 0x04, 0x19,
727 0xc2, 0xa0, 0x04, 0x19, 0x89, 0x00, 0x71, 0x8b,
728 0xc8, 0x30, 0x04, 0x19, 0x71, 0x00, 0x71, 0x8b,
729 0xcd, 0x00, 0x04, 0x19, 0xcf, 0x00, 0x04, 0x19,
730 0x80, 0x00, 0x71, 0x8b, 0xcb, 0x20, 0x04, 0x19,
731 0x20, 0x00, 0x71, 0x8b, 0xc4, 0x20, 0x04, 0x19,
732 0x47, 0x00, 0x51, 0x8b, 0xc0, 0x20, 0x00, 0x39,
733 0x00, 0x00, 0x63, 0x80, 0xc1, 0xa0, 0x04, 0x19,
734 0x93, 0x00, 0x01, 0x4f, 0xcd, 0x30, 0x00, 0x09,
735 0xcf, 0x30, 0x00, 0x09, 0x0c, 0x40, 0x00, 0x14,
736 0x00, 0x60, 0x00, 0x14, 0x00, 0x04, 0x61, 0xa8,
737 0x02, 0x04, 0x61, 0xa8, 0x0c, 0x60, 0x04, 0x24,
738 0x00, 0x00, 0x34, 0x49, 0x08, 0x50, 0x00, 0x44,
739 0x44, 0x04, 0x04, 0x39, 0x00, 0x00, 0x40, 0x45,
740 0x08, 0x30, 0x61, 0x0a, 0x05, 0xb0, 0xe8, 0x18,
741 0x0c, 0xc0, 0x04, 0x54, 0xc8, 0x30, 0x04, 0x19,
742 0x09, 0x04, 0x00, 0xa8, 0x0b, 0x04, 0x00, 0xa8,
743 0x00, 0x00, 0x40, 0x45, 0x09, 0x04, 0x61, 0xa8,
744 0xc1, 0x00, 0x04, 0x19, 0x0b, 0x04, 0x61, 0xa8,
745 0xca, 0x00, 0x04, 0x19, 0x0d, 0x00, 0x61, 0x0a,
746 0x00, 0x01, 0x00, 0x45, 0x0f, 0x00, 0x61, 0x0a,
747 0x00, 0x40, 0x09, 0x8f, 0x00, 0x01, 0x00, 0x45,
748 0x40, 0x40, 0x09, 0xef, 0xff, 0x20, 0x09, 0xcf,
749 0x00, 0x04, 0x63, 0xa1, 0x50, 0x03, 0x33, 0x80,
750 0x00, 0x04, 0xa3, 0x80, 0x00, 0xff, 0xc2, 0x8b,
751 0x0c, 0x12, 0x04, 0x54, 0x08, 0x12, 0x00, 0xc4,
752 0x20, 0x03, 0x80, 0xc0, 0x30, 0x00, 0x00, 0x88,
753 0x00, 0x00, 0x7a, 0x0a, 0xd0, 0x01, 0x00, 0x82,
754 0x04, 0x50, 0x00, 0x44, 0xc0, 0x00, 0x00, 0x99,
755 0x04, 0x50, 0x00, 0x44, 0x00, 0xff, 0xc2, 0x8b,
756 0x20, 0x00, 0x00, 0x80, 0x00, 0x0d, 0x42, 0x8b,
757 0x04, 0x42, 0x00, 0xc4, 0x00, 0x0e, 0x42, 0x8b,
758 0x08, 0x52, 0x00, 0xc4, 0x00, 0x1e, 0x42, 0x8b,
759 0x00, 0xe2, 0x00, 0xc4, 0x00, 0x8e, 0x42, 0x8b,
760 0x08, 0xd2, 0x00, 0xc4, 0x00, 0x9e, 0x42, 0x8b,
761 0x04, 0xf2, 0x00, 0xc4, 0x00, 0xbe, 0x42, 0x8b,
762 0x04, 0xf2, 0x00, 0xc4, 0x00, 0x04, 0x42, 0x8b,
763 0x04, 0x11, 0x00, 0xc4, 0x00, 0x24, 0x42, 0x8b,
764 0x0c, 0x61, 0x00, 0xc4, 0x00, 0x55, 0x42, 0x8b,
765 0x04, 0x50, 0x00, 0xc4, 0x00, 0x3f, 0x42, 0x8b,
766 0x0c, 0x01, 0x00, 0xc4, 0x00, 0x00, 0x40, 0x45,
767 0x20, 0x01, 0x79, 0x80, 0x00, 0x30, 0x42, 0x8b,
768 0x04, 0x62, 0x00, 0xc4, 0x00, 0x00, 0x40, 0x45,
769 0x00, 0x00, 0x71, 0x8b, 0x40, 0x01, 0x00, 0x80,
770 0x04, 0x50, 0x00, 0x44, 0xff, 0x00, 0xe2, 0xab,
771 0x08, 0xc2, 0x00, 0xc4, 0x0f, 0xf2, 0xa8, 0xa8,
772 0x20, 0x00, 0xb1, 0x88, 0x00, 0x00, 0x41, 0x02,
773 0x4d, 0xf2, 0x00, 0x39, 0xc0, 0x01, 0x00, 0x82,
774 0x04, 0x50, 0x00, 0x44, 0x0d, 0xf2, 0xa3, 0xa8,
775 0x4d, 0xf2, 0x00, 0x39, 0x04, 0x50, 0x00, 0x44,
776 0xff, 0x00, 0xe2, 0xab, 0x20, 0x00, 0x00, 0x88,
777 0x00, 0x00, 0x61, 0x02, 0x4d, 0xf2, 0x04, 0x19,
778 0x04, 0x50, 0x00, 0x44, 0xff, 0x00, 0xe2, 0xab,
779 0xa0, 0x00, 0x00, 0x88, 0x00, 0x00, 0x61, 0x10,
780 0x4d, 0xf2, 0x04, 0x19, 0x04, 0x50, 0x00, 0x44,
781 0xff, 0x20, 0xe2, 0xab, 0x60, 0x00, 0x00, 0x88,
782 0x00, 0x00, 0x71, 0xc0, 0x4d, 0xf2, 0x04, 0x19,
783 0x04, 0x50, 0x00, 0x44, 0x00, 0x00, 0x7a, 0x0a,
784 0x20, 0x01, 0xf0, 0x80, 0x01, 0xa0, 0x41, 0x0a,
785 0x00, 0x11, 0x00, 0xc4, 0x20, 0x01, 0xf0, 0x80,
786 0xc1, 0x30, 0x04, 0x19, 0x04, 0x50, 0x00, 0x44,
787 0x00, 0x00, 0x79, 0x80, 0x0c, 0x41, 0x00, 0x84,
788 0x89, 0x00, 0x71, 0x8b, 0xc8, 0x30, 0x04, 0x19,
789 0x97, 0x00, 0x71, 0x8b, 0xcd, 0x00, 0x00, 0x39,
790 0x00, 0x01, 0xb1, 0x80, 0x80, 0x00, 0x04, 0x19,
791 0x82, 0x00, 0x04, 0x19, 0xc1, 0x20, 0x04, 0x19,
792 0xc3, 0x20, 0x04, 0x19, 0xc2, 0x30, 0x04, 0x19,
793 0xcd, 0x10, 0x04, 0x19, 0xcf, 0x10, 0x04, 0x19,
794 0xb0, 0x00, 0x71, 0x8b, 0x84, 0x00, 0x04, 0x19,
795 0x86, 0x00, 0x04, 0x19, 0x80, 0x00, 0x71, 0x8b,
796 0xcb, 0x20, 0x04, 0x19, 0x93, 0x00, 0x01, 0x4f,
797 0xcd, 0x30, 0x00, 0x09, 0xcf, 0x30, 0x00, 0x09,
798 0x03, 0x02, 0x04, 0x49, 0x08, 0x41, 0x00, 0x14,
799 0x04, 0x50, 0x00, 0x44, 0x00, 0x00, 0x63, 0x80,
800 0x00, 0x00, 0x06, 0x19, 0x03, 0x00, 0x04, 0x49,
801 0x04, 0x50, 0x00, 0x44, 0x20, 0x01, 0x63, 0x80,
802 0x00, 0x00, 0x06, 0x19, 0x00, 0x20, 0xe2, 0x8b,
803 0x00, 0xc1, 0x00, 0x84, 0x47, 0x00, 0x51, 0x8b,
804 0xc0, 0x20, 0x00, 0x39, 0x00, 0x00, 0x63, 0x80,
805 0xc1, 0xa0, 0x04, 0x19, 0x00, 0xe1, 0x00, 0x44,
806 0xbd, 0x00, 0x51, 0x8b, 0xc0, 0x20, 0x00, 0x39,
807 0x00, 0x00, 0xb1, 0x80, 0xc1, 0xa0, 0x04, 0x19,
808 0x03, 0x00, 0x04, 0x49, 0x04, 0x50, 0x00, 0x44,
809 0x00, 0x20, 0x61, 0x0a, 0x00, 0x01, 0x00, 0x45,
810 0x02, 0x30, 0x61, 0x0a, 0x0c, 0x83, 0x00, 0xc4,
811 0x0c, 0x78, 0x08, 0x44, 0x04, 0x5a, 0x08, 0x44,
812 0xb2, 0x00, 0x09, 0x4f, 0x10, 0x42, 0x09, 0x8e,
813 0x05, 0xb0, 0xe0, 0x18, 0x04, 0x23, 0x00, 0x84,
814 0x0c, 0x01, 0x00, 0x11, 0x08, 0x05, 0x61, 0x10,
815 0x00, 0x49, 0x08, 0x44, 0x00, 0x48, 0x08, 0x44,
816 0xb2, 0x00, 0x09, 0x4f, 0x80, 0x00, 0x71, 0x8b,
817 0xc0, 0x00, 0x00, 0x82, 0x0c, 0x01, 0x33, 0x10,
818 0x28, 0x01, 0xa3, 0x10, 0x00, 0x01, 0x7a, 0x80,
819 0x8c, 0x01, 0x00, 0x80, 0x02, 0x30, 0x61, 0x0a,
820 0x20, 0x00, 0x04, 0x19, 0x0c, 0x83, 0x00, 0xc4,
821 0x05, 0xb0, 0xc8, 0x18, 0x08, 0x43, 0x00, 0xc4,
822 0x01, 0x30, 0xc8, 0x0a, 0x0c, 0x38, 0x00, 0xc4,
823 0x08, 0x88, 0x00, 0x44, 0x0c, 0x78, 0x08, 0x44,
824 0x04, 0x5a, 0x08, 0x44, 0x00, 0x00, 0xa3, 0x18,
825 0x80, 0x00, 0x04, 0x19, 0x0b, 0x04, 0x61, 0xa8,
826 0xc3, 0x20, 0x00, 0x39, 0xc3, 0x30, 0x04, 0x19,
827 0x0f, 0x10, 0x61, 0x0a, 0xca, 0x30, 0x04, 0x19,
828 0x09, 0x04, 0x41, 0xa8, 0xe1, 0x20, 0x00, 0x39,
829 0xd1, 0x00, 0x09, 0x4f, 0x00, 0x04, 0x61, 0x02,
830 0x08, 0x63, 0x00, 0x44, 0x03, 0x30, 0x41, 0x0a,
831 0x20, 0x00, 0x00, 0x39, 0xa3, 0x00, 0x09, 0x4f,
832 0x00, 0x04, 0x61, 0x02, 0x00, 0x48, 0x08, 0x44,
833 0x08, 0x88, 0x00, 0x44, 0x02, 0x30, 0x61, 0x0a,
834 0x00, 0x08, 0x00, 0xc4, 0x0c, 0x78, 0x08, 0x44,
835 0x04, 0x5a, 0x08, 0x44, 0xb2, 0x00, 0x09, 0x0f,
836 0x10, 0x40, 0x09, 0x8e, 0x00, 0x00, 0x68, 0x5b,
837 0x20, 0x04, 0xb1, 0x80, 0x02, 0x00, 0x61, 0x5b,
838 0x88, 0x03, 0x7a, 0x80, 0xac, 0x01, 0x00, 0x80,
839 0x05, 0xb0, 0xe0, 0x18, 0x00, 0xd3, 0x00, 0x84,
840 0x00, 0x49, 0x08, 0x44, 0x00, 0x48, 0x08, 0x44,
841 0xb2, 0x00, 0x09, 0x0f, 0x80, 0x00, 0x71, 0x8b,
842 0xc0, 0x00, 0x00, 0x82, 0x02, 0x30, 0x61, 0x0a,
843 0x00, 0x08, 0x00, 0xc4, 0x05, 0xb0, 0xc8, 0x18,
844 0x0c, 0x18, 0x00, 0xc4, 0x01, 0x30, 0xc8, 0x0a,
845 0x0c, 0x38, 0x00, 0xc4, 0x08, 0x88, 0x00, 0x44,
846 0x0c, 0x78, 0x08, 0x44, 0x00, 0x00, 0x61, 0x18,
847 0x20, 0x05, 0xb1, 0x80, 0x00, 0x00, 0x68, 0xcb,
848 0x80, 0x00, 0x04, 0x19, 0x0d, 0x10, 0x61, 0x0a,
849 0xc3, 0x30, 0x04, 0x19, 0x0b, 0x04, 0x41, 0xa8,
850 0x09, 0x04, 0x41, 0xa8, 0xe1, 0x20, 0x00, 0x39,
851 0x08, 0x38, 0x00, 0x44, 0x03, 0x30, 0x41, 0x0a,
852 0x20, 0x04, 0xb1, 0x80, 0x00, 0x48, 0x08, 0x44,
853 0x08, 0x88, 0x00, 0x44, 0x00, 0x00, 0xb1, 0x80,
854 0xc2, 0x30, 0x04, 0x19, 0x0c, 0xb8, 0x00, 0xd4,
855 0x0f, 0x30, 0x61, 0x0a, 0x0d, 0x30, 0xc8, 0x0a,
856 0x0c, 0xb8, 0x00, 0xc4, 0x93, 0x00, 0x01, 0x4f,
857 0xe7, 0x00, 0x01, 0x6f, 0x0f, 0x30, 0x61, 0x0a,
858 0x20, 0x00, 0x00, 0x88, 0x02, 0x00, 0x61, 0x02,
859 0x41, 0x04, 0x04, 0x19, 0x02, 0x04, 0x61, 0x02,
860 0x43, 0x04, 0x04, 0x39, 0xcf, 0x30, 0x00, 0x09,
861 0x20, 0x00, 0x09, 0x49, 0x00, 0x59, 0x00, 0x44,
862 0x93, 0x00, 0x01, 0x4f, 0xe7, 0x00, 0x01, 0x6f,
863 0x0d, 0x30, 0x61, 0x0a, 0x20, 0x00, 0x61, 0x88,
864 0xc2, 0x00, 0x00, 0x82, 0xc2, 0x03, 0x00, 0x82,
865 0xcd, 0x30, 0x00, 0x09, 0x20, 0x00, 0x09, 0x49,
866 0x0f, 0x30, 0x61, 0x0a, 0x0d, 0x30, 0xc8, 0x0a,
867 0x0c, 0x58, 0x00, 0x84, 0x02, 0x30, 0x61, 0x0a,
868 0x05, 0xb0, 0xa8, 0x18, 0xc2, 0x30, 0x04, 0x19,
869 0x00, 0x00, 0x00, 0x46, 0x90, 0x40, 0x09, 0x8f,
870 0x12, 0x04, 0x09, 0x6e, 0x03, 0x00, 0x09, 0x0e,
871 0x00, 0x01, 0x71, 0x82, 0x20, 0x01, 0x00, 0x80,
872 0x00, 0x00, 0x61, 0xcb, 0x80, 0x04, 0xb1, 0x80,
873 0x00, 0x01, 0xe0, 0x60, 0x0c, 0xd8, 0x04, 0x14,
874 0x00, 0x01, 0xeb, 0x80, 0x40, 0x00, 0x52, 0x1b,
875 0x80, 0x00, 0x79, 0x80, 0xc0, 0x01, 0x71, 0xc2,
876 0x20, 0x00, 0xc0, 0x80, 0x08, 0x0a, 0x04, 0x54,
877 0xc0, 0x04, 0xa8, 0x82, 0x80, 0x00, 0x72, 0x1b,
878 0x80, 0x00, 0x00, 0x80, 0x00, 0x01, 0xf0, 0x80,
879 0x20, 0x00, 0xc0, 0x80, 0x0c, 0x2a, 0x04, 0x54,
880 0xc0, 0x04, 0xa8, 0x82, 0x10, 0x00, 0x72, 0x1b,
881 0x80, 0x00, 0x00, 0x80, 0x00, 0x01, 0xf0, 0x80,
882 0x20, 0x00, 0xc0, 0x80, 0x08, 0x3a, 0x04, 0x54,
883 0xc0, 0x04, 0xa8, 0x82, 0x20, 0x00, 0x72, 0x1b,
884 0x80, 0x00, 0x00, 0x80, 0xc0, 0x03, 0xf0, 0x82,
885 0x20, 0x00, 0xa0, 0x80, 0x00, 0x01, 0x00, 0x11,
886 0x40, 0x00, 0xc2, 0x8b, 0x00, 0xaa, 0x00, 0xc4,
887 0x00, 0x00, 0xe9, 0x80, 0x05, 0xb0, 0xa8, 0x18,
888 0x00, 0x01, 0xa8, 0x22, 0xd0, 0x01, 0x00, 0x82,
889 0xf0, 0x00, 0xe2, 0x1b, 0x06, 0x20, 0xa8, 0x0a,
890 0x2d, 0x10, 0x61, 0x0a, 0xd1, 0x00, 0x09, 0x2e,
891 0x00, 0x01, 0xa8, 0x02, 0x0e, 0x10, 0xc8, 0x0a,
892 0x0c, 0xba, 0x04, 0x14, 0x0e, 0x10, 0x61, 0x0a,
893 0x04, 0x4a, 0x00, 0x44, 0x0c, 0x10, 0xc8, 0x0a,
894 0x04, 0x4a, 0x04, 0x54, 0x0c, 0x10, 0x61, 0x0a,
895 0xd0, 0x01, 0x00, 0x82, 0x00, 0x10, 0xa8, 0x18,
896 0xa0, 0x00, 0x00, 0x88, 0x00, 0x01, 0x71, 0x82,
897 0x03, 0x00, 0x09, 0x0e, 0x9a, 0x01, 0x00, 0x60,
898 0x32, 0x00, 0x09, 0x2e, 0x00, 0x00, 0x00, 0x46,
899 0x00, 0x01, 0x71, 0x82, 0x20, 0x01, 0x00, 0x80,
900 0x00, 0x00, 0x61, 0xcb, 0x80, 0x24, 0xb1, 0xc0,
901 0x00, 0x31, 0xe0, 0x60, 0x0c, 0xca, 0x04, 0x14,
902 0x00, 0x01, 0xeb, 0x80, 0x40, 0x00, 0x52, 0x1b,
903 0x80, 0x00, 0x79, 0x80, 0xc0, 0x01, 0x71, 0xc2,
904 0x20, 0x00, 0xc0, 0x80, 0x08, 0xda, 0x04, 0x54,
905 0xc0, 0x04, 0xa8, 0x82, 0x80, 0x00, 0x72, 0x1b,
906 0x80, 0x00, 0x00, 0x80, 0x00, 0x01, 0xf0, 0x80,
907 0x20, 0x00, 0xc0, 0x80, 0x0c, 0xfa, 0x04, 0x54,
908 0xc0, 0x04, 0xa8, 0x82, 0x10, 0x00, 0x72, 0x1b,
909 0x80, 0x00, 0x00, 0x80, 0x00, 0x01, 0xf0, 0x80,
910 0x20, 0x00, 0xc0, 0x80, 0x08, 0x29, 0x04, 0x54,
911 0xc0, 0x04, 0xa8, 0x82, 0x20, 0x00, 0x72, 0x1b,
912 0x80, 0x00, 0x00, 0x80, 0xc0, 0x03, 0xf0, 0x82,
913 0x20, 0x00, 0xa0, 0x80, 0x00, 0x01, 0x00, 0x11,
914 0x40, 0x00, 0xc2, 0x8b, 0x00, 0x39, 0x00, 0xc4,
915 0x00, 0x00, 0xe9, 0x80, 0x05, 0xb0, 0xa8, 0x18,
916 0x00, 0x01, 0xa8, 0x22, 0xd0, 0x01, 0x00, 0x82,
917 0xb0, 0x00, 0xe2, 0x1b, 0x06, 0x20, 0xa8, 0x0a,
918 0x2f, 0x10, 0x61, 0x0a, 0xf1, 0x00, 0x09, 0x2e,
919 0x00, 0x01, 0xa8, 0x02, 0x0e, 0x10, 0xc8, 0x0a,
920 0x0c, 0xa9, 0x04, 0x14, 0x0e, 0x10, 0x61, 0x0a,
921 0x04, 0x99, 0x00, 0x44, 0x0c, 0x10, 0xc8, 0x0a,
922 0x04, 0x99, 0x04, 0x54, 0x0c, 0x10, 0x61, 0x0a,
923 0xd0, 0x01, 0x00, 0x82, 0x00, 0x10, 0xa8, 0x18,
924 0xa0, 0x00, 0x00, 0x88, 0x00, 0x01, 0x71, 0x82,
925 0x9f, 0x01, 0x00, 0x60, 0x00, 0x00, 0x00, 0x46,
926 0x00, 0x00, 0x33, 0x80, 0x00, 0x00, 0x83, 0x80,
927 0x20, 0x00, 0x7a, 0x80, 0x20, 0x07, 0x33, 0x80,
928 0x00, 0x00, 0x83, 0x80, 0x20, 0x04, 0x7a, 0x80,
929 0x20, 0x01, 0x00, 0x80, 0x00, 0x00, 0x00, 0x46,
930 0x02, 0x00, 0x61, 0x0a, 0x04, 0x1b, 0x04, 0x14,
931 0x01, 0x00, 0x61, 0x0a, 0x03, 0x00, 0x48, 0x0a,
932 0x0c, 0x79, 0x04, 0x54, 0xc3, 0x00, 0x04, 0x19,
933 0x04, 0xc9, 0x00, 0x44, 0x08, 0x00, 0xc8, 0x0a,
934 0x04, 0xc9, 0x04, 0x54, 0xc8, 0x00, 0x04, 0x19,
935 0x0a, 0x00, 0x61, 0x0a, 0x09, 0x00, 0x48, 0x0a,
936 0x0c, 0xe9, 0x04, 0x54, 0xc9, 0x00, 0x04, 0x19,
937 0x04, 0xd9, 0x00, 0x44, 0x0b, 0x00, 0xc8, 0x0a,
938 0x04, 0xd9, 0x04, 0x54, 0xcb, 0x00, 0x04, 0x19,
939 0x04, 0x00, 0x61, 0x0a, 0x06, 0x00, 0x48, 0x0a,
940 0x0c, 0xf9, 0x04, 0x54, 0xc6, 0x00, 0x04, 0x19,
941 0x04, 0x0b, 0x00, 0x44, 0x05, 0x00, 0xc8, 0x0a,
942 0x04, 0x0b, 0x04, 0x54, 0xc5, 0x00, 0x04, 0x19,
943 0x07, 0x00, 0x61, 0x0a, 0x0c, 0x00, 0x48, 0x0a,
944 0x0c, 0x2b, 0x04, 0x54, 0xcc, 0x00, 0x04, 0x19,
945 0x04, 0x1b, 0x00, 0x44, 0x0e, 0x00, 0xc8, 0x0a,
946 0x04, 0x1b, 0x04, 0x54, 0xce, 0x00, 0x04, 0x19,
947 0x00, 0x00, 0x40, 0x45, 0x92, 0x20, 0x71, 0x8b,
948 0xa6, 0xc5, 0x11, 0x00
949};
diff --git a/sound/isa/sb/sb16_main.c b/sound/isa/sb/sb16_main.c
new file mode 100644
index 000000000000..a6a0fa516268
--- /dev/null
+++ b/sound/isa/sb/sb16_main.c
@@ -0,0 +1,916 @@
1/*
2 * Copyright (c) by Jaroslav Kysela <perex@suse.cz>
3 * Routines for control of 16-bit SoundBlaster cards and clones
4 * Note: This is very ugly hardware which uses one 8-bit DMA channel and
5 * second 16-bit DMA channel. Unfortunately 8-bit DMA channel can't
6 * transfer 16-bit samples and 16-bit DMA channels can't transfer
7 * 8-bit samples. This make full duplex more complicated than
8 * can be... People, don't buy these soundcards for full 16-bit
9 * duplex!!!
10 * Note: 16-bit wide is assigned to first direction which made request.
11 * With full duplex - playback is preferred with abstract layer.
12 *
13 * Note: Some chip revisions have hardware bug. Changing capture
14 * channel from full-duplex 8bit DMA to 16bit DMA will block
15 * 16bit DMA transfers from DSP chip (capture) until 8bit transfer
16 * to DSP chip (playback) starts. This bug can be avoided with
17 * "16bit DMA Allocation" setting set to Playback or Capture.
18 *
19 *
20 * This program is free software; you can redistribute it and/or modify
21 * it under the terms of the GNU General Public License as published by
22 * the Free Software Foundation; either version 2 of the License, or
23 * (at your option) any later version.
24 *
25 * This program is distributed in the hope that it will be useful,
26 * but WITHOUT ANY WARRANTY; without even the implied warranty of
27 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
28 * GNU General Public License for more details.
29 *
30 * You should have received a copy of the GNU General Public License
31 * along with this program; if not, write to the Free Software
32 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
33 *
34 */
35
36#include <sound/driver.h>
37#include <asm/io.h>
38#include <asm/dma.h>
39#include <linux/init.h>
40#include <linux/time.h>
41#include <sound/core.h>
42#include <sound/sb.h>
43#include <sound/sb16_csp.h>
44#include <sound/mpu401.h>
45#include <sound/control.h>
46#include <sound/info.h>
47
48MODULE_AUTHOR("Jaroslav Kysela <perex@suse.cz>");
49MODULE_DESCRIPTION("Routines for control of 16-bit SoundBlaster cards and clones");
50MODULE_LICENSE("GPL");
51
52#ifdef CONFIG_SND_SB16_CSP
53static void snd_sb16_csp_playback_prepare(sb_t *chip, snd_pcm_runtime_t *runtime)
54{
55 if (chip->hardware == SB_HW_16CSP) {
56 snd_sb_csp_t *csp = chip->csp;
57
58 if (csp->running & SNDRV_SB_CSP_ST_LOADED) {
59 /* manually loaded codec */
60 if ((csp->mode & SNDRV_SB_CSP_MODE_DSP_WRITE) &&
61 ((1U << runtime->format) == csp->acc_format)) {
62 /* Supported runtime PCM format for playback */
63 if (csp->ops.csp_use(csp) == 0) {
64 /* If CSP was successfully acquired */
65 goto __start_CSP;
66 }
67 } else if ((csp->mode & SNDRV_SB_CSP_MODE_QSOUND) && (csp->q_enabled)) {
68 /* QSound decoder is loaded and enabled */
69 if ((1 << runtime->format) & (SNDRV_PCM_FMTBIT_S8 | SNDRV_PCM_FMTBIT_U8 |
70 SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_U16_LE)) {
71 /* Only for simple PCM formats */
72 if (csp->ops.csp_use(csp) == 0) {
73 /* If CSP was successfully acquired */
74 goto __start_CSP;
75 }
76 }
77 }
78 } else if (csp->ops.csp_use(csp) == 0) {
79 /* Acquire CSP and try to autoload hardware codec */
80 if (csp->ops.csp_autoload(csp, runtime->format, SNDRV_SB_CSP_MODE_DSP_WRITE)) {
81 /* Unsupported format, release CSP */
82 csp->ops.csp_unuse(csp);
83 } else {
84 __start_CSP:
85 /* Try to start CSP */
86 if (csp->ops.csp_start(csp, (chip->mode & SB_MODE_PLAYBACK_16) ?
87 SNDRV_SB_CSP_SAMPLE_16BIT : SNDRV_SB_CSP_SAMPLE_8BIT,
88 (runtime->channels > 1) ?
89 SNDRV_SB_CSP_STEREO : SNDRV_SB_CSP_MONO)) {
90 /* Failed, release CSP */
91 csp->ops.csp_unuse(csp);
92 } else {
93 /* Success, CSP acquired and running */
94 chip->open = SNDRV_SB_CSP_MODE_DSP_WRITE;
95 }
96 }
97 }
98 }
99}
100
101static void snd_sb16_csp_capture_prepare(sb_t *chip, snd_pcm_runtime_t *runtime)
102{
103 if (chip->hardware == SB_HW_16CSP) {
104 snd_sb_csp_t *csp = chip->csp;
105
106 if (csp->running & SNDRV_SB_CSP_ST_LOADED) {
107 /* manually loaded codec */
108 if ((csp->mode & SNDRV_SB_CSP_MODE_DSP_READ) &&
109 ((1U << runtime->format) == csp->acc_format)) {
110 /* Supported runtime PCM format for capture */
111 if (csp->ops.csp_use(csp) == 0) {
112 /* If CSP was successfully acquired */
113 goto __start_CSP;
114 }
115 }
116 } else if (csp->ops.csp_use(csp) == 0) {
117 /* Acquire CSP and try to autoload hardware codec */
118 if (csp->ops.csp_autoload(csp, runtime->format, SNDRV_SB_CSP_MODE_DSP_READ)) {
119 /* Unsupported format, release CSP */
120 csp->ops.csp_unuse(csp);
121 } else {
122 __start_CSP:
123 /* Try to start CSP */
124 if (csp->ops.csp_start(csp, (chip->mode & SB_MODE_CAPTURE_16) ?
125 SNDRV_SB_CSP_SAMPLE_16BIT : SNDRV_SB_CSP_SAMPLE_8BIT,
126 (runtime->channels > 1) ?
127 SNDRV_SB_CSP_STEREO : SNDRV_SB_CSP_MONO)) {
128 /* Failed, release CSP */
129 csp->ops.csp_unuse(csp);
130 } else {
131 /* Success, CSP acquired and running */
132 chip->open = SNDRV_SB_CSP_MODE_DSP_READ;
133 }
134 }
135 }
136 }
137}
138
139static void snd_sb16_csp_update(sb_t *chip)
140{
141 if (chip->hardware == SB_HW_16CSP) {
142 snd_sb_csp_t *csp = chip->csp;
143
144 if (csp->qpos_changed) {
145 spin_lock(&chip->reg_lock);
146 csp->ops.csp_qsound_transfer (csp);
147 spin_unlock(&chip->reg_lock);
148 }
149 }
150}
151
152static void snd_sb16_csp_playback_open(sb_t *chip, snd_pcm_runtime_t *runtime)
153{
154 /* CSP decoders (QSound excluded) support only 16bit transfers */
155 if (chip->hardware == SB_HW_16CSP) {
156 snd_sb_csp_t *csp = chip->csp;
157
158 if (csp->running & SNDRV_SB_CSP_ST_LOADED) {
159 /* manually loaded codec */
160 if (csp->mode & SNDRV_SB_CSP_MODE_DSP_WRITE) {
161 runtime->hw.formats |= csp->acc_format;
162 }
163 } else {
164 /* autoloaded codecs */
165 runtime->hw.formats |= SNDRV_PCM_FMTBIT_MU_LAW | SNDRV_PCM_FMTBIT_A_LAW |
166 SNDRV_PCM_FMTBIT_IMA_ADPCM;
167 }
168 }
169}
170
171static void snd_sb16_csp_playback_close(sb_t *chip)
172{
173 if ((chip->hardware == SB_HW_16CSP) && (chip->open == SNDRV_SB_CSP_MODE_DSP_WRITE)) {
174 snd_sb_csp_t *csp = chip->csp;
175
176 if (csp->ops.csp_stop(csp) == 0) {
177 csp->ops.csp_unuse(csp);
178 chip->open = 0;
179 }
180 }
181}
182
183static void snd_sb16_csp_capture_open(sb_t *chip, snd_pcm_runtime_t *runtime)
184{
185 /* CSP coders support only 16bit transfers */
186 if (chip->hardware == SB_HW_16CSP) {
187 snd_sb_csp_t *csp = chip->csp;
188
189 if (csp->running & SNDRV_SB_CSP_ST_LOADED) {
190 /* manually loaded codec */
191 if (csp->mode & SNDRV_SB_CSP_MODE_DSP_READ) {
192 runtime->hw.formats |= csp->acc_format;
193 }
194 } else {
195 /* autoloaded codecs */
196 runtime->hw.formats |= SNDRV_PCM_FMTBIT_MU_LAW | SNDRV_PCM_FMTBIT_A_LAW |
197 SNDRV_PCM_FMTBIT_IMA_ADPCM;
198 }
199 }
200}
201
202static void snd_sb16_csp_capture_close(sb_t *chip)
203{
204 if ((chip->hardware == SB_HW_16CSP) && (chip->open == SNDRV_SB_CSP_MODE_DSP_READ)) {
205 snd_sb_csp_t *csp = chip->csp;
206
207 if (csp->ops.csp_stop(csp) == 0) {
208 csp->ops.csp_unuse(csp);
209 chip->open = 0;
210 }
211 }
212}
213#else
214#define snd_sb16_csp_playback_prepare(chip, runtime) /*nop*/
215#define snd_sb16_csp_capture_prepare(chip, runtime) /*nop*/
216#define snd_sb16_csp_update(chip) /*nop*/
217#define snd_sb16_csp_playback_open(chip, runtime) /*nop*/
218#define snd_sb16_csp_playback_close(chip) /*nop*/
219#define snd_sb16_csp_capture_open(chip, runtime) /*nop*/
220#define snd_sb16_csp_capture_close(chip) /*nop*/
221#endif
222
223
224static void snd_sb16_setup_rate(sb_t *chip,
225 unsigned short rate,
226 int channel)
227{
228 unsigned long flags;
229
230 spin_lock_irqsave(&chip->reg_lock, flags);
231 if (chip->mode & (channel == SNDRV_PCM_STREAM_PLAYBACK ? SB_MODE_PLAYBACK_16 : SB_MODE_CAPTURE_16))
232 snd_sb_ack_16bit(chip);
233 else
234 snd_sb_ack_8bit(chip);
235 if (!(chip->mode & SB_RATE_LOCK)) {
236 chip->locked_rate = rate;
237 snd_sbdsp_command(chip, SB_DSP_SAMPLE_RATE_IN);
238 snd_sbdsp_command(chip, rate >> 8);
239 snd_sbdsp_command(chip, rate & 0xff);
240 snd_sbdsp_command(chip, SB_DSP_SAMPLE_RATE_OUT);
241 snd_sbdsp_command(chip, rate >> 8);
242 snd_sbdsp_command(chip, rate & 0xff);
243 }
244 spin_unlock_irqrestore(&chip->reg_lock, flags);
245}
246
247static int snd_sb16_hw_params(snd_pcm_substream_t * substream,
248 snd_pcm_hw_params_t * hw_params)
249{
250 return snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(hw_params));
251}
252
253static int snd_sb16_hw_free(snd_pcm_substream_t * substream)
254{
255 snd_pcm_lib_free_pages(substream);
256 return 0;
257}
258
259static int snd_sb16_playback_prepare(snd_pcm_substream_t * substream)
260{
261 unsigned long flags;
262 sb_t *chip = snd_pcm_substream_chip(substream);
263 snd_pcm_runtime_t *runtime = substream->runtime;
264 unsigned char format;
265 unsigned int size, count, dma;
266
267 snd_sb16_csp_playback_prepare(chip, runtime);
268 if (snd_pcm_format_unsigned(runtime->format) > 0) {
269 format = runtime->channels > 1 ? SB_DSP4_MODE_UNS_STEREO : SB_DSP4_MODE_UNS_MONO;
270 } else {
271 format = runtime->channels > 1 ? SB_DSP4_MODE_SIGN_STEREO : SB_DSP4_MODE_SIGN_MONO;
272 }
273
274 snd_sb16_setup_rate(chip, runtime->rate, SNDRV_PCM_STREAM_PLAYBACK);
275 size = chip->p_dma_size = snd_pcm_lib_buffer_bytes(substream);
276 dma = (chip->mode & SB_MODE_PLAYBACK_8) ? chip->dma8 : chip->dma16;
277 snd_dma_program(dma, runtime->dma_addr, size, DMA_MODE_WRITE | DMA_AUTOINIT);
278
279 count = snd_pcm_lib_period_bytes(substream);
280 spin_lock_irqsave(&chip->reg_lock, flags);
281 if (chip->mode & SB_MODE_PLAYBACK_16) {
282 count >>= 1;
283 count--;
284 snd_sbdsp_command(chip, SB_DSP4_OUT16_AI);
285 snd_sbdsp_command(chip, format);
286 snd_sbdsp_command(chip, count & 0xff);
287 snd_sbdsp_command(chip, count >> 8);
288 snd_sbdsp_command(chip, SB_DSP_DMA16_OFF);
289 } else {
290 count--;
291 snd_sbdsp_command(chip, SB_DSP4_OUT8_AI);
292 snd_sbdsp_command(chip, format);
293 snd_sbdsp_command(chip, count & 0xff);
294 snd_sbdsp_command(chip, count >> 8);
295 snd_sbdsp_command(chip, SB_DSP_DMA8_OFF);
296 }
297 spin_unlock_irqrestore(&chip->reg_lock, flags);
298 return 0;
299}
300
301static int snd_sb16_playback_trigger(snd_pcm_substream_t * substream,
302 int cmd)
303{
304 sb_t *chip = snd_pcm_substream_chip(substream);
305 int result = 0;
306
307 spin_lock(&chip->reg_lock);
308 switch (cmd) {
309 case SNDRV_PCM_TRIGGER_START:
310 chip->mode |= SB_RATE_LOCK_PLAYBACK;
311 snd_sbdsp_command(chip, chip->mode & SB_MODE_PLAYBACK_16 ? SB_DSP_DMA16_ON : SB_DSP_DMA8_ON);
312 break;
313 case SNDRV_PCM_TRIGGER_STOP:
314 snd_sbdsp_command(chip, chip->mode & SB_MODE_PLAYBACK_16 ? SB_DSP_DMA16_OFF : SB_DSP_DMA8_OFF);
315 /* next two lines are needed for some types of DSP4 (SB AWE 32 - 4.13) */
316 if (chip->mode & SB_RATE_LOCK_CAPTURE)
317 snd_sbdsp_command(chip, chip->mode & SB_MODE_CAPTURE_16 ? SB_DSP_DMA16_ON : SB_DSP_DMA8_ON);
318 chip->mode &= ~SB_RATE_LOCK_PLAYBACK;
319 break;
320 default:
321 result = -EINVAL;
322 }
323 spin_unlock(&chip->reg_lock);
324 return result;
325}
326
327static int snd_sb16_capture_prepare(snd_pcm_substream_t * substream)
328{
329 unsigned long flags;
330 sb_t *chip = snd_pcm_substream_chip(substream);
331 snd_pcm_runtime_t *runtime = substream->runtime;
332 unsigned char format;
333 unsigned int size, count, dma;
334
335 snd_sb16_csp_capture_prepare(chip, runtime);
336 if (snd_pcm_format_unsigned(runtime->format) > 0) {
337 format = runtime->channels > 1 ? SB_DSP4_MODE_UNS_STEREO : SB_DSP4_MODE_UNS_MONO;
338 } else {
339 format = runtime->channels > 1 ? SB_DSP4_MODE_SIGN_STEREO : SB_DSP4_MODE_SIGN_MONO;
340 }
341 snd_sb16_setup_rate(chip, runtime->rate, SNDRV_PCM_STREAM_CAPTURE);
342 size = chip->c_dma_size = snd_pcm_lib_buffer_bytes(substream);
343 dma = (chip->mode & SB_MODE_CAPTURE_8) ? chip->dma8 : chip->dma16;
344 snd_dma_program(dma, runtime->dma_addr, size, DMA_MODE_READ | DMA_AUTOINIT);
345
346 count = snd_pcm_lib_period_bytes(substream);
347 spin_lock_irqsave(&chip->reg_lock, flags);
348 if (chip->mode & SB_MODE_CAPTURE_16) {
349 count >>= 1;
350 count--;
351 snd_sbdsp_command(chip, SB_DSP4_IN16_AI);
352 snd_sbdsp_command(chip, format);
353 snd_sbdsp_command(chip, count & 0xff);
354 snd_sbdsp_command(chip, count >> 8);
355 snd_sbdsp_command(chip, SB_DSP_DMA16_OFF);
356 } else {
357 count--;
358 snd_sbdsp_command(chip, SB_DSP4_IN8_AI);
359 snd_sbdsp_command(chip, format);
360 snd_sbdsp_command(chip, count & 0xff);
361 snd_sbdsp_command(chip, count >> 8);
362 snd_sbdsp_command(chip, SB_DSP_DMA8_OFF);
363 }
364 spin_unlock_irqrestore(&chip->reg_lock, flags);
365 return 0;
366}
367
368static int snd_sb16_capture_trigger(snd_pcm_substream_t * substream,
369 int cmd)
370{
371 sb_t *chip = snd_pcm_substream_chip(substream);
372 int result = 0;
373
374 spin_lock(&chip->reg_lock);
375 switch (cmd) {
376 case SNDRV_PCM_TRIGGER_START:
377 chip->mode |= SB_RATE_LOCK_CAPTURE;
378 snd_sbdsp_command(chip, chip->mode & SB_MODE_CAPTURE_16 ? SB_DSP_DMA16_ON : SB_DSP_DMA8_ON);
379 break;
380 case SNDRV_PCM_TRIGGER_STOP:
381 snd_sbdsp_command(chip, chip->mode & SB_MODE_CAPTURE_16 ? SB_DSP_DMA16_OFF : SB_DSP_DMA8_OFF);
382 /* next two lines are needed for some types of DSP4 (SB AWE 32 - 4.13) */
383 if (chip->mode & SB_RATE_LOCK_PLAYBACK)
384 snd_sbdsp_command(chip, chip->mode & SB_MODE_PLAYBACK_16 ? SB_DSP_DMA16_ON : SB_DSP_DMA8_ON);
385 chip->mode &= ~SB_RATE_LOCK_CAPTURE;
386 break;
387 default:
388 result = -EINVAL;
389 }
390 spin_unlock(&chip->reg_lock);
391 return result;
392}
393
394irqreturn_t snd_sb16dsp_interrupt(int irq, void *dev_id, struct pt_regs *regs)
395{
396 sb_t *chip = dev_id;
397 unsigned char status;
398 int ok;
399
400 spin_lock(&chip->mixer_lock);
401 status = snd_sbmixer_read(chip, SB_DSP4_IRQSTATUS);
402 spin_unlock(&chip->mixer_lock);
403 if ((status & SB_IRQTYPE_MPUIN) && chip->rmidi_callback)
404 chip->rmidi_callback(irq, chip->rmidi->private_data, regs);
405 if (status & SB_IRQTYPE_8BIT) {
406 ok = 0;
407 if (chip->mode & SB_MODE_PLAYBACK_8) {
408 snd_pcm_period_elapsed(chip->playback_substream);
409 snd_sb16_csp_update(chip);
410 ok++;
411 }
412 if (chip->mode & SB_MODE_CAPTURE_8) {
413 snd_pcm_period_elapsed(chip->capture_substream);
414 ok++;
415 }
416 spin_lock(&chip->reg_lock);
417 if (!ok)
418 snd_sbdsp_command(chip, SB_DSP_DMA8_OFF);
419 snd_sb_ack_8bit(chip);
420 spin_unlock(&chip->reg_lock);
421 }
422 if (status & SB_IRQTYPE_16BIT) {
423 ok = 0;
424 if (chip->mode & SB_MODE_PLAYBACK_16) {
425 snd_pcm_period_elapsed(chip->playback_substream);
426 snd_sb16_csp_update(chip);
427 ok++;
428 }
429 if (chip->mode & SB_MODE_CAPTURE_16) {
430 snd_pcm_period_elapsed(chip->capture_substream);
431 ok++;
432 }
433 spin_lock(&chip->reg_lock);
434 if (!ok)
435 snd_sbdsp_command(chip, SB_DSP_DMA16_OFF);
436 snd_sb_ack_16bit(chip);
437 spin_unlock(&chip->reg_lock);
438 }
439 return IRQ_HANDLED;
440}
441
442/*
443
444 */
445
446static snd_pcm_uframes_t snd_sb16_playback_pointer(snd_pcm_substream_t * substream)
447{
448 sb_t *chip = snd_pcm_substream_chip(substream);
449 unsigned int dma;
450 size_t ptr;
451
452 dma = (chip->mode & SB_MODE_PLAYBACK_8) ? chip->dma8 : chip->dma16;
453 ptr = snd_dma_pointer(dma, chip->p_dma_size);
454 return bytes_to_frames(substream->runtime, ptr);
455}
456
457static snd_pcm_uframes_t snd_sb16_capture_pointer(snd_pcm_substream_t * substream)
458{
459 sb_t *chip = snd_pcm_substream_chip(substream);
460 unsigned int dma;
461 size_t ptr;
462
463 dma = (chip->mode & SB_MODE_CAPTURE_8) ? chip->dma8 : chip->dma16;
464 ptr = snd_dma_pointer(dma, chip->c_dma_size);
465 return bytes_to_frames(substream->runtime, ptr);
466}
467
468/*
469
470 */
471
472static snd_pcm_hardware_t snd_sb16_playback =
473{
474 .info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED |
475 SNDRV_PCM_INFO_MMAP_VALID),
476 .formats = 0,
477 .rates = SNDRV_PCM_RATE_CONTINUOUS | SNDRV_PCM_RATE_8000_44100,
478 .rate_min = 4000,
479 .rate_max = 44100,
480 .channels_min = 1,
481 .channels_max = 2,
482 .buffer_bytes_max = (128*1024),
483 .period_bytes_min = 64,
484 .period_bytes_max = (128*1024),
485 .periods_min = 1,
486 .periods_max = 1024,
487 .fifo_size = 0,
488};
489
490static snd_pcm_hardware_t snd_sb16_capture =
491{
492 .info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED |
493 SNDRV_PCM_INFO_MMAP_VALID),
494 .formats = 0,
495 .rates = SNDRV_PCM_RATE_CONTINUOUS | SNDRV_PCM_RATE_8000_44100,
496 .rate_min = 4000,
497 .rate_max = 44100,
498 .channels_min = 1,
499 .channels_max = 2,
500 .buffer_bytes_max = (128*1024),
501 .period_bytes_min = 64,
502 .period_bytes_max = (128*1024),
503 .periods_min = 1,
504 .periods_max = 1024,
505 .fifo_size = 0,
506};
507
508/*
509 * open/close
510 */
511
512static int snd_sb16_playback_open(snd_pcm_substream_t * substream)
513{
514 unsigned long flags;
515 sb_t *chip = snd_pcm_substream_chip(substream);
516 snd_pcm_runtime_t *runtime = substream->runtime;
517
518 spin_lock_irqsave(&chip->open_lock, flags);
519 if (chip->mode & SB_MODE_PLAYBACK) {
520 spin_unlock_irqrestore(&chip->open_lock, flags);
521 return -EAGAIN;
522 }
523 runtime->hw = snd_sb16_playback;
524
525 /* skip if 16 bit DMA was reserved for capture */
526 if (chip->force_mode16 & SB_MODE_CAPTURE_16)
527 goto __skip_16bit;
528
529 if (chip->dma16 >= 0 && !(chip->mode & SB_MODE_CAPTURE_16)) {
530 chip->mode |= SB_MODE_PLAYBACK_16;
531 runtime->hw.formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_U16_LE;
532 /* Vibra16X hack */
533 if (chip->dma16 <= 3) {
534 runtime->hw.buffer_bytes_max =
535 runtime->hw.period_bytes_max = 64 * 1024;
536 } else {
537 snd_sb16_csp_playback_open(chip, runtime);
538 }
539 goto __open_ok;
540 }
541
542 __skip_16bit:
543 if (chip->dma8 >= 0 && !(chip->mode & SB_MODE_CAPTURE_8)) {
544 chip->mode |= SB_MODE_PLAYBACK_8;
545 /* DSP v 4.xx can transfer 16bit data through 8bit DMA channel, SBHWPG 2-7 */
546 if (chip->dma16 < 0) {
547 runtime->hw.formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_U16_LE;
548 chip->mode |= SB_MODE_PLAYBACK_16;
549 } else {
550 runtime->hw.formats = SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S8;
551 }
552 runtime->hw.buffer_bytes_max =
553 runtime->hw.period_bytes_max = 64 * 1024;
554 goto __open_ok;
555 }
556 spin_unlock_irqrestore(&chip->open_lock, flags);
557 return -EAGAIN;
558
559 __open_ok:
560 if (chip->hardware == SB_HW_ALS100)
561 runtime->hw.rate_max = 48000;
562 if (chip->mode & SB_RATE_LOCK)
563 runtime->hw.rate_min = runtime->hw.rate_max = chip->locked_rate;
564 chip->playback_substream = substream;
565 spin_unlock_irqrestore(&chip->open_lock, flags);
566 return 0;
567}
568
569static int snd_sb16_playback_close(snd_pcm_substream_t * substream)
570{
571 unsigned long flags;
572 sb_t *chip = snd_pcm_substream_chip(substream);
573
574 snd_sb16_csp_playback_close(chip);
575 spin_lock_irqsave(&chip->open_lock, flags);
576 chip->playback_substream = NULL;
577 chip->mode &= ~SB_MODE_PLAYBACK;
578 spin_unlock_irqrestore(&chip->open_lock, flags);
579 return 0;
580}
581
582static int snd_sb16_capture_open(snd_pcm_substream_t * substream)
583{
584 unsigned long flags;
585 sb_t *chip = snd_pcm_substream_chip(substream);
586 snd_pcm_runtime_t *runtime = substream->runtime;
587
588 spin_lock_irqsave(&chip->open_lock, flags);
589 if (chip->mode & SB_MODE_CAPTURE) {
590 spin_unlock_irqrestore(&chip->open_lock, flags);
591 return -EAGAIN;
592 }
593 runtime->hw = snd_sb16_capture;
594
595 /* skip if 16 bit DMA was reserved for playback */
596 if (chip->force_mode16 & SB_MODE_PLAYBACK_16)
597 goto __skip_16bit;
598
599 if (chip->dma16 >= 0 && !(chip->mode & SB_MODE_PLAYBACK_16)) {
600 chip->mode |= SB_MODE_CAPTURE_16;
601 runtime->hw.formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_U16_LE;
602 /* Vibra16X hack */
603 if (chip->dma16 <= 3) {
604 runtime->hw.buffer_bytes_max =
605 runtime->hw.period_bytes_max = 64 * 1024;
606 } else {
607 snd_sb16_csp_capture_open(chip, runtime);
608 }
609 goto __open_ok;
610 }
611
612 __skip_16bit:
613 if (chip->dma8 >= 0 && !(chip->mode & SB_MODE_PLAYBACK_8)) {
614 chip->mode |= SB_MODE_CAPTURE_8;
615 /* DSP v 4.xx can transfer 16bit data through 8bit DMA channel, SBHWPG 2-7 */
616 if (chip->dma16 < 0) {
617 runtime->hw.formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_U16_LE;
618 chip->mode |= SB_MODE_CAPTURE_16;
619 } else {
620 runtime->hw.formats = SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S8;
621 }
622 runtime->hw.buffer_bytes_max =
623 runtime->hw.period_bytes_max = 64 * 1024;
624 goto __open_ok;
625 }
626 spin_unlock_irqrestore(&chip->open_lock, flags);
627 return -EAGAIN;
628
629 __open_ok:
630 if (chip->hardware == SB_HW_ALS100)
631 runtime->hw.rate_max = 48000;
632 if (chip->mode & SB_RATE_LOCK)
633 runtime->hw.rate_min = runtime->hw.rate_max = chip->locked_rate;
634 chip->capture_substream = substream;
635 spin_unlock_irqrestore(&chip->open_lock, flags);
636 return 0;
637}
638
639static int snd_sb16_capture_close(snd_pcm_substream_t * substream)
640{
641 unsigned long flags;
642 sb_t *chip = snd_pcm_substream_chip(substream);
643
644 snd_sb16_csp_capture_close(chip);
645 spin_lock_irqsave(&chip->open_lock, flags);
646 chip->capture_substream = NULL;
647 chip->mode &= ~SB_MODE_CAPTURE;
648 spin_unlock_irqrestore(&chip->open_lock, flags);
649 return 0;
650}
651
652/*
653 * DMA control interface
654 */
655
656static int snd_sb16_set_dma_mode(sb_t *chip, int what)
657{
658 if (chip->dma8 < 0 || chip->dma16 < 0) {
659 snd_assert(what == 0, return -EINVAL);
660 return 0;
661 }
662 if (what == 0) {
663 chip->force_mode16 = 0;
664 } else if (what == 1) {
665 chip->force_mode16 = SB_MODE_PLAYBACK_16;
666 } else if (what == 2) {
667 chip->force_mode16 = SB_MODE_CAPTURE_16;
668 } else {
669 return -EINVAL;
670 }
671 return 0;
672}
673
674static int snd_sb16_get_dma_mode(sb_t *chip)
675{
676 if (chip->dma8 < 0 || chip->dma16 < 0)
677 return 0;
678 switch (chip->force_mode16) {
679 case SB_MODE_PLAYBACK_16:
680 return 1;
681 case SB_MODE_CAPTURE_16:
682 return 2;
683 default:
684 return 0;
685 }
686}
687
688static int snd_sb16_dma_control_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
689{
690 static char *texts[3] = {
691 "Auto", "Playback", "Capture"
692 };
693
694 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
695 uinfo->count = 1;
696 uinfo->value.enumerated.items = 3;
697 if (uinfo->value.enumerated.item > 2)
698 uinfo->value.enumerated.item = 2;
699 strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]);
700 return 0;
701}
702
703static int snd_sb16_dma_control_get(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
704{
705 sb_t *chip = snd_kcontrol_chip(kcontrol);
706 unsigned long flags;
707
708 spin_lock_irqsave(&chip->reg_lock, flags);
709 ucontrol->value.enumerated.item[0] = snd_sb16_get_dma_mode(chip);
710 spin_unlock_irqrestore(&chip->reg_lock, flags);
711 return 0;
712}
713
714static int snd_sb16_dma_control_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
715{
716 sb_t *chip = snd_kcontrol_chip(kcontrol);
717 unsigned long flags;
718 unsigned char nval, oval;
719 int change;
720
721 if ((nval = ucontrol->value.enumerated.item[0]) > 2)
722 return -EINVAL;
723 spin_lock_irqsave(&chip->reg_lock, flags);
724 oval = snd_sb16_get_dma_mode(chip);
725 change = nval != oval;
726 snd_sb16_set_dma_mode(chip, nval);
727 spin_unlock_irqrestore(&chip->reg_lock, flags);
728 return change;
729}
730
731static snd_kcontrol_new_t snd_sb16_dma_control = {
732 .iface = SNDRV_CTL_ELEM_IFACE_PCM,
733 .name = "16-bit DMA Allocation",
734 .info = snd_sb16_dma_control_info,
735 .get = snd_sb16_dma_control_get,
736 .put = snd_sb16_dma_control_put
737};
738
739/*
740 * Initialization part
741 */
742
743int snd_sb16dsp_configure(sb_t * chip)
744{
745 unsigned long flags;
746 unsigned char irqreg = 0, dmareg = 0, mpureg;
747 unsigned char realirq, realdma, realmpureg;
748 /* note: mpu register should be present only on SB16 Vibra soundcards */
749
750 // printk("codec->irq=%i, codec->dma8=%i, codec->dma16=%i\n", chip->irq, chip->dma8, chip->dma16);
751 spin_lock_irqsave(&chip->mixer_lock, flags);
752 mpureg = snd_sbmixer_read(chip, SB_DSP4_MPUSETUP) & ~0x06;
753 spin_unlock_irqrestore(&chip->mixer_lock, flags);
754 switch (chip->irq) {
755 case 2:
756 case 9:
757 irqreg |= SB_IRQSETUP_IRQ9;
758 break;
759 case 5:
760 irqreg |= SB_IRQSETUP_IRQ5;
761 break;
762 case 7:
763 irqreg |= SB_IRQSETUP_IRQ7;
764 break;
765 case 10:
766 irqreg |= SB_IRQSETUP_IRQ10;
767 break;
768 default:
769 return -EINVAL;
770 }
771 if (chip->dma8 >= 0) {
772 switch (chip->dma8) {
773 case 0:
774 dmareg |= SB_DMASETUP_DMA0;
775 break;
776 case 1:
777 dmareg |= SB_DMASETUP_DMA1;
778 break;
779 case 3:
780 dmareg |= SB_DMASETUP_DMA3;
781 break;
782 default:
783 return -EINVAL;
784 }
785 }
786 if (chip->dma16 >= 0 && chip->dma16 != chip->dma8) {
787 switch (chip->dma16) {
788 case 5:
789 dmareg |= SB_DMASETUP_DMA5;
790 break;
791 case 6:
792 dmareg |= SB_DMASETUP_DMA6;
793 break;
794 case 7:
795 dmareg |= SB_DMASETUP_DMA7;
796 break;
797 default:
798 return -EINVAL;
799 }
800 }
801 switch (chip->mpu_port) {
802 case 0x300:
803 mpureg |= 0x04;
804 break;
805 case 0x330:
806 mpureg |= 0x00;
807 break;
808 default:
809 mpureg |= 0x02; /* disable MPU */
810 }
811 spin_lock_irqsave(&chip->mixer_lock, flags);
812
813 snd_sbmixer_write(chip, SB_DSP4_IRQSETUP, irqreg);
814 realirq = snd_sbmixer_read(chip, SB_DSP4_IRQSETUP);
815
816 snd_sbmixer_write(chip, SB_DSP4_DMASETUP, dmareg);
817 realdma = snd_sbmixer_read(chip, SB_DSP4_DMASETUP);
818
819 snd_sbmixer_write(chip, SB_DSP4_MPUSETUP, mpureg);
820 realmpureg = snd_sbmixer_read(chip, SB_DSP4_MPUSETUP);
821
822 spin_unlock_irqrestore(&chip->mixer_lock, flags);
823 if ((~realirq) & irqreg || (~realdma) & dmareg) {
824 snd_printk("SB16 [0x%lx]: unable to set DMA & IRQ (PnP device?)\n", chip->port);
825 snd_printk("SB16 [0x%lx]: wanted: irqreg=0x%x, dmareg=0x%x, mpureg = 0x%x\n", chip->port, realirq, realdma, realmpureg);
826 snd_printk("SB16 [0x%lx]: got: irqreg=0x%x, dmareg=0x%x, mpureg = 0x%x\n", chip->port, irqreg, dmareg, mpureg);
827 return -ENODEV;
828 }
829 return 0;
830}
831
832static snd_pcm_ops_t snd_sb16_playback_ops = {
833 .open = snd_sb16_playback_open,
834 .close = snd_sb16_playback_close,
835 .ioctl = snd_pcm_lib_ioctl,
836 .hw_params = snd_sb16_hw_params,
837 .hw_free = snd_sb16_hw_free,
838 .prepare = snd_sb16_playback_prepare,
839 .trigger = snd_sb16_playback_trigger,
840 .pointer = snd_sb16_playback_pointer,
841};
842
843static snd_pcm_ops_t snd_sb16_capture_ops = {
844 .open = snd_sb16_capture_open,
845 .close = snd_sb16_capture_close,
846 .ioctl = snd_pcm_lib_ioctl,
847 .hw_params = snd_sb16_hw_params,
848 .hw_free = snd_sb16_hw_free,
849 .prepare = snd_sb16_capture_prepare,
850 .trigger = snd_sb16_capture_trigger,
851 .pointer = snd_sb16_capture_pointer,
852};
853
854static void snd_sb16dsp_pcm_free(snd_pcm_t *pcm)
855{
856 snd_pcm_lib_preallocate_free_for_all(pcm);
857}
858
859int snd_sb16dsp_pcm(sb_t * chip, int device, snd_pcm_t ** rpcm)
860{
861 snd_card_t *card = chip->card;
862 snd_pcm_t *pcm;
863 int err;
864
865 if (rpcm)
866 *rpcm = NULL;
867 if ((err = snd_pcm_new(card, "SB16 DSP", device, 1, 1, &pcm)) < 0)
868 return err;
869 sprintf(pcm->name, "DSP v%i.%i", chip->version >> 8, chip->version & 0xff);
870 pcm->info_flags = SNDRV_PCM_INFO_JOINT_DUPLEX;
871 pcm->private_data = chip;
872 pcm->private_free = snd_sb16dsp_pcm_free;
873
874 snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_sb16_playback_ops);
875 snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_sb16_capture_ops);
876
877 if (chip->dma16 >= 0 && chip->dma8 != chip->dma16)
878 snd_ctl_add(card, snd_ctl_new1(&snd_sb16_dma_control, chip));
879 else
880 pcm->info_flags = SNDRV_PCM_INFO_HALF_DUPLEX;
881
882 snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV,
883 snd_dma_isa_data(),
884 64*1024, 128*1024);
885
886 if (rpcm)
887 *rpcm = pcm;
888 return 0;
889}
890
891const snd_pcm_ops_t *snd_sb16dsp_get_pcm_ops(int direction)
892{
893 return direction == SNDRV_PCM_STREAM_PLAYBACK ?
894 &snd_sb16_playback_ops : &snd_sb16_capture_ops;
895}
896
897EXPORT_SYMBOL(snd_sb16dsp_pcm);
898EXPORT_SYMBOL(snd_sb16dsp_get_pcm_ops);
899EXPORT_SYMBOL(snd_sb16dsp_configure);
900EXPORT_SYMBOL(snd_sb16dsp_interrupt);
901
902/*
903 * INIT part
904 */
905
906static int __init alsa_sb16_init(void)
907{
908 return 0;
909}
910
911static void __exit alsa_sb16_exit(void)
912{
913}
914
915module_init(alsa_sb16_init)
916module_exit(alsa_sb16_exit)
diff --git a/sound/isa/sb/sb8.c b/sound/isa/sb/sb8.c
new file mode 100644
index 000000000000..e2cbc4202b3d
--- /dev/null
+++ b/sound/isa/sb/sb8.c
@@ -0,0 +1,223 @@
1/*
2 * Driver for SoundBlaster 1.0/2.0/Pro soundcards and compatible
3 * Copyright (c) by Jaroslav Kysela <perex@suse.cz>
4 *
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 *
20 */
21
22#include <sound/driver.h>
23#include <linux/init.h>
24#include <linux/slab.h>
25#include <linux/ioport.h>
26#include <linux/moduleparam.h>
27#include <sound/core.h>
28#include <sound/sb.h>
29#include <sound/opl3.h>
30#define SNDRV_LEGACY_AUTO_PROBE
31#include <sound/initval.h>
32
33MODULE_AUTHOR("Jaroslav Kysela <perex@suse.cz>");
34MODULE_DESCRIPTION("Sound Blaster 1.0/2.0/Pro");
35MODULE_LICENSE("GPL");
36MODULE_SUPPORTED_DEVICE("{{Creative Labs,SB 1.0/SB 2.0/SB Pro}}");
37
38static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-MAX */
39static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* ID for this card */
40static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE; /* Enable this card */
41static long port[SNDRV_CARDS] = SNDRV_DEFAULT_PORT; /* 0x220,0x240,0x260 */
42static int irq[SNDRV_CARDS] = SNDRV_DEFAULT_IRQ; /* 5,7,9,10 */
43static int dma8[SNDRV_CARDS] = SNDRV_DEFAULT_DMA; /* 1,3 */
44
45module_param_array(index, int, NULL, 0444);
46MODULE_PARM_DESC(index, "Index value for Sound Blaster soundcard.");
47module_param_array(id, charp, NULL, 0444);
48MODULE_PARM_DESC(id, "ID string for Sound Blaster soundcard.");
49module_param_array(enable, bool, NULL, 0444);
50MODULE_PARM_DESC(enable, "Enable Sound Blaster soundcard.");
51module_param_array(port, long, NULL, 0444);
52MODULE_PARM_DESC(port, "Port # for SB8 driver.");
53module_param_array(irq, int, NULL, 0444);
54MODULE_PARM_DESC(irq, "IRQ # for SB8 driver.");
55module_param_array(dma8, int, NULL, 0444);
56MODULE_PARM_DESC(dma8, "8-bit DMA # for SB8 driver.");
57
58struct snd_sb8 {
59 struct resource *fm_res; /* used to block FM i/o region for legacy cards */
60};
61
62static snd_card_t *snd_sb8_cards[SNDRV_CARDS] = SNDRV_DEFAULT_PTR;
63
64static irqreturn_t snd_sb8_interrupt(int irq, void *dev_id, struct pt_regs *regs)
65{
66 sb_t *chip = dev_id;
67
68 if (chip->open & SB_OPEN_PCM) {
69 return snd_sb8dsp_interrupt(chip);
70 } else {
71 return snd_sb8dsp_midi_interrupt(chip);
72 }
73}
74
75static void snd_sb8_free(snd_card_t *card)
76{
77 struct snd_sb8 *acard = (struct snd_sb8 *)card->private_data;
78
79 if (acard == NULL)
80 return;
81 if (acard->fm_res) {
82 release_resource(acard->fm_res);
83 kfree_nocheck(acard->fm_res);
84 }
85}
86
87static int __init snd_sb8_probe(int dev)
88{
89 sb_t *chip;
90 snd_card_t *card;
91 struct snd_sb8 *acard;
92 opl3_t *opl3;
93 int err;
94
95 card = snd_card_new(index[dev], id[dev], THIS_MODULE,
96 sizeof(struct snd_sb8));
97 if (card == NULL)
98 return -ENOMEM;
99 acard = (struct snd_sb8 *)card->private_data;
100 card->private_free = snd_sb8_free;
101
102 /* block the 0x388 port to avoid PnP conflicts */
103 acard->fm_res = request_region(0x388, 4, "SoundBlaster FM");
104
105 if ((err = snd_sbdsp_create(card, port[dev], irq[dev],
106 snd_sb8_interrupt,
107 dma8[dev],
108 -1,
109 SB_HW_AUTO,
110 &chip)) < 0) {
111 snd_card_free(card);
112 return err;
113 }
114 if (chip->hardware >= SB_HW_16) {
115 snd_card_free(card);
116 if (chip->hardware == SB_HW_ALS100)
117 snd_printdd("ALS100 chip detected at 0x%lx, try snd-als100 module\n",
118 port[dev]);
119 else
120 snd_printdd("SB 16 chip detected at 0x%lx, try snd-sb16 module\n",
121 port[dev]);
122 return -ENODEV;
123 }
124
125 if ((err = snd_sb8dsp_pcm(chip, 0, NULL)) < 0) {
126 snd_card_free(card);
127 return err;
128 }
129 if ((err = snd_sbmixer_new(chip)) < 0) {
130 snd_card_free(card);
131 return err;
132 }
133 if (chip->hardware == SB_HW_10 || chip->hardware == SB_HW_20) {
134 if ((err = snd_opl3_create(card, chip->port + 8, 0,
135 OPL3_HW_AUTO, 1,
136 &opl3)) < 0) {
137 snd_printk(KERN_ERR "sb8: no OPL device at 0x%lx\n", chip->port + 8);
138 }
139 } else {
140 if ((err = snd_opl3_create(card, chip->port, chip->port + 2,
141 OPL3_HW_AUTO, 1,
142 &opl3)) < 0) {
143 snd_printk(KERN_ERR "sb8: no OPL device at 0x%lx-0x%lx\n",
144 chip->port, chip->port + 2);
145 }
146 }
147 if (err >= 0) {
148 if ((err = snd_opl3_hwdep_new(opl3, 0, 1, NULL)) < 0) {
149 snd_card_free(card);
150 return err;
151 }
152 }
153
154 if ((err = snd_sb8dsp_midi(chip, 0, NULL)) < 0) {
155 snd_card_free(card);
156 return err;
157 }
158
159 strcpy(card->driver, chip->hardware == SB_HW_PRO ? "SB Pro" : "SB8");
160 strcpy(card->shortname, chip->name);
161 sprintf(card->longname, "%s at 0x%lx, irq %d, dma %d",
162 chip->name,
163 chip->port,
164 irq[dev], dma8[dev]);
165 if ((err = snd_card_register(card)) < 0) {
166 snd_card_free(card);
167 return err;
168 }
169 snd_sb8_cards[dev] = card;
170 return 0;
171}
172
173static int __init snd_card_sb8_legacy_auto_probe(unsigned long xport)
174{
175 static int dev;
176 int res;
177
178 for ( ; dev < SNDRV_CARDS; dev++) {
179 if (!enable[dev] || port[dev] != SNDRV_AUTO_PORT)
180 continue;
181 port[dev] = xport;
182 res = snd_sb8_probe(dev);
183 if (res < 0)
184 port[dev] = SNDRV_AUTO_PORT;
185 return res;
186 }
187 return -ENODEV;
188}
189
190static int __init alsa_card_sb8_init(void)
191{
192 static unsigned long possible_ports[] = {0x220, 0x240, 0x260, -1};
193 int dev, cards, i;
194
195 for (dev = cards = 0; dev < SNDRV_CARDS && enable[dev]; dev++) {
196 if (port[dev] == SNDRV_AUTO_PORT)
197 continue;
198 if (snd_sb8_probe(dev) >= 0)
199 cards++;
200 }
201 i = snd_legacy_auto_probe(possible_ports, snd_card_sb8_legacy_auto_probe);
202 if (i > 0)
203 cards += i;
204
205 if (!cards) {
206#ifdef MODULE
207 snd_printk(KERN_ERR "Sound Blaster soundcard not found or device busy\n");
208#endif
209 return -ENODEV;
210 }
211 return 0;
212}
213
214static void __exit alsa_card_sb8_exit(void)
215{
216 int idx;
217
218 for (idx = 0; idx < SNDRV_CARDS; idx++)
219 snd_card_free(snd_sb8_cards[idx]);
220}
221
222module_init(alsa_card_sb8_init)
223module_exit(alsa_card_sb8_exit)
diff --git a/sound/isa/sb/sb8_main.c b/sound/isa/sb/sb8_main.c
new file mode 100644
index 000000000000..87c9b1ba06cf
--- /dev/null
+++ b/sound/isa/sb/sb8_main.c
@@ -0,0 +1,565 @@
1/*
2 * Copyright (c) by Jaroslav Kysela <perex@suse.cz>
3 * Uros Bizjak <uros@kss-loka.si>
4 *
5 * Routines for control of 8-bit SoundBlaster cards and clones
6 * Please note: I don't have access to old SB8 soundcards.
7 *
8 *
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
13 *
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22 *
23 * --
24 *
25 * Thu Apr 29 20:36:17 BST 1999 George David Morrison <gdm@gedamo.demon.co.uk>
26 * DSP can't respond to commands whilst in "high speed" mode. Caused
27 * glitching during playback. Fixed.
28 *
29 * Wed Jul 12 22:02:55 CEST 2000 Uros Bizjak <uros@kss-loka.si>
30 * Cleaned up and rewrote lowlevel routines.
31 */
32
33#include <sound/driver.h>
34#include <asm/io.h>
35#include <asm/dma.h>
36#include <linux/init.h>
37#include <linux/time.h>
38#include <sound/core.h>
39#include <sound/sb.h>
40
41MODULE_AUTHOR("Jaroslav Kysela <perex@suse.cz>, Uros Bizjak <uros@kss-loka.si>");
42MODULE_DESCRIPTION("Routines for control of 8-bit SoundBlaster cards and clones");
43MODULE_LICENSE("GPL");
44
45#define SB8_CLOCK 1000000
46#define SB8_DEN(v) ((SB8_CLOCK + (v) / 2) / (v))
47#define SB8_RATE(v) (SB8_CLOCK / SB8_DEN(v))
48
49static ratnum_t clock = {
50 .num = SB8_CLOCK,
51 .den_min = 1,
52 .den_max = 256,
53 .den_step = 1,
54};
55
56static snd_pcm_hw_constraint_ratnums_t hw_constraints_clock = {
57 .nrats = 1,
58 .rats = &clock,
59};
60
61static ratnum_t stereo_clocks[] = {
62 {
63 .num = SB8_CLOCK,
64 .den_min = SB8_DEN(22050),
65 .den_max = SB8_DEN(22050),
66 .den_step = 1,
67 },
68 {
69 .num = SB8_CLOCK,
70 .den_min = SB8_DEN(11025),
71 .den_max = SB8_DEN(11025),
72 .den_step = 1,
73 }
74};
75
76static int snd_sb8_hw_constraint_rate_channels(snd_pcm_hw_params_t *params,
77 snd_pcm_hw_rule_t *rule)
78{
79 snd_interval_t *c = hw_param_interval(params, SNDRV_PCM_HW_PARAM_CHANNELS);
80 if (c->min > 1) {
81 unsigned int num = 0, den = 0;
82 int err = snd_interval_ratnum(hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE),
83 2, stereo_clocks, &num, &den);
84 if (err >= 0 && den) {
85 params->rate_num = num;
86 params->rate_den = den;
87 }
88 return err;
89 }
90 return 0;
91}
92
93static int snd_sb8_hw_constraint_channels_rate(snd_pcm_hw_params_t *params,
94 snd_pcm_hw_rule_t *rule)
95{
96 snd_interval_t *r = hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE);
97 if (r->min > SB8_RATE(22050) || r->max <= SB8_RATE(11025)) {
98 snd_interval_t t = { .min = 1, .max = 1 };
99 return snd_interval_refine(hw_param_interval(params, SNDRV_PCM_HW_PARAM_CHANNELS), &t);
100 }
101 return 0;
102}
103
104static int snd_sb8_playback_prepare(snd_pcm_substream_t * substream)
105{
106 unsigned long flags;
107 sb_t *chip = snd_pcm_substream_chip(substream);
108 snd_pcm_runtime_t *runtime = substream->runtime;
109 unsigned int mixreg, rate, size, count;
110
111 rate = runtime->rate;
112 switch (chip->hardware) {
113 case SB_HW_PRO:
114 if (runtime->channels > 1) {
115 snd_assert(rate == SB8_RATE(11025) || rate == SB8_RATE(22050), return -EINVAL);
116 chip->playback_format = SB_DSP_HI_OUTPUT_AUTO;
117 break;
118 }
119 /* fallthru */
120 case SB_HW_201:
121 if (rate > 23000) {
122 chip->playback_format = SB_DSP_HI_OUTPUT_AUTO;
123 break;
124 }
125 /* fallthru */
126 case SB_HW_20:
127 chip->playback_format = SB_DSP_LO_OUTPUT_AUTO;
128 break;
129 case SB_HW_10:
130 chip->playback_format = SB_DSP_OUTPUT;
131 break;
132 default:
133 return -EINVAL;
134 }
135 size = chip->p_dma_size = snd_pcm_lib_buffer_bytes(substream);
136 count = chip->p_period_size = snd_pcm_lib_period_bytes(substream);
137 spin_lock_irqsave(&chip->reg_lock, flags);
138 snd_sbdsp_command(chip, SB_DSP_SPEAKER_ON);
139 if (runtime->channels > 1) {
140 /* set playback stereo mode */
141 spin_lock(&chip->mixer_lock);
142 mixreg = snd_sbmixer_read(chip, SB_DSP_STEREO_SW);
143 snd_sbmixer_write(chip, SB_DSP_STEREO_SW, mixreg | 0x02);
144 spin_unlock(&chip->mixer_lock);
145
146 /* Soundblaster hardware programming reference guide, 3-23 */
147 snd_sbdsp_command(chip, SB_DSP_DMA8_EXIT);
148 runtime->dma_area[0] = 0x80;
149 snd_dma_program(chip->dma8, runtime->dma_addr, 1, DMA_MODE_WRITE);
150 /* force interrupt */
151 chip->mode = SB_MODE_HALT;
152 snd_sbdsp_command(chip, SB_DSP_OUTPUT);
153 snd_sbdsp_command(chip, 0);
154 snd_sbdsp_command(chip, 0);
155 }
156 snd_sbdsp_command(chip, SB_DSP_SAMPLE_RATE);
157 if (runtime->channels > 1) {
158 snd_sbdsp_command(chip, 256 - runtime->rate_den / 2);
159 spin_lock(&chip->mixer_lock);
160 /* save output filter status and turn it off */
161 mixreg = snd_sbmixer_read(chip, SB_DSP_PLAYBACK_FILT);
162 snd_sbmixer_write(chip, SB_DSP_PLAYBACK_FILT, mixreg | 0x20);
163 spin_unlock(&chip->mixer_lock);
164 /* just use force_mode16 for temporary storate... */
165 chip->force_mode16 = mixreg;
166 } else {
167 snd_sbdsp_command(chip, 256 - runtime->rate_den);
168 }
169 if (chip->playback_format != SB_DSP_OUTPUT) {
170 count--;
171 snd_sbdsp_command(chip, SB_DSP_BLOCK_SIZE);
172 snd_sbdsp_command(chip, count & 0xff);
173 snd_sbdsp_command(chip, count >> 8);
174 }
175 spin_unlock_irqrestore(&chip->reg_lock, flags);
176 snd_dma_program(chip->dma8, runtime->dma_addr,
177 size, DMA_MODE_WRITE | DMA_AUTOINIT);
178 return 0;
179}
180
181static int snd_sb8_playback_trigger(snd_pcm_substream_t * substream,
182 int cmd)
183{
184 unsigned long flags;
185 sb_t *chip = snd_pcm_substream_chip(substream);
186 unsigned int count;
187
188 spin_lock_irqsave(&chip->reg_lock, flags);
189 switch (cmd) {
190 case SNDRV_PCM_TRIGGER_START:
191 snd_sbdsp_command(chip, chip->playback_format);
192 if (chip->playback_format == SB_DSP_OUTPUT) {
193 count = chip->p_period_size - 1;
194 snd_sbdsp_command(chip, count & 0xff);
195 snd_sbdsp_command(chip, count >> 8);
196 }
197 break;
198 case SNDRV_PCM_TRIGGER_STOP:
199 if (chip->playback_format == SB_DSP_HI_OUTPUT_AUTO) {
200 snd_pcm_runtime_t *runtime = substream->runtime;
201 snd_sbdsp_reset(chip);
202 if (runtime->channels > 1) {
203 spin_lock(&chip->mixer_lock);
204 /* restore output filter and set hardware to mono mode */
205 snd_sbmixer_write(chip, SB_DSP_STEREO_SW, chip->force_mode16 & ~0x02);
206 spin_unlock(&chip->mixer_lock);
207 }
208 } else {
209 snd_sbdsp_command(chip, SB_DSP_DMA8_OFF);
210 }
211 snd_sbdsp_command(chip, SB_DSP_SPEAKER_OFF);
212 }
213 spin_unlock_irqrestore(&chip->reg_lock, flags);
214 chip->mode = (cmd == SNDRV_PCM_TRIGGER_START) ? SB_MODE_PLAYBACK_8 : SB_MODE_HALT;
215 return 0;
216}
217
218static int snd_sb8_hw_params(snd_pcm_substream_t * substream,
219 snd_pcm_hw_params_t * hw_params)
220{
221 return snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(hw_params));
222}
223
224static int snd_sb8_hw_free(snd_pcm_substream_t * substream)
225{
226 snd_pcm_lib_free_pages(substream);
227 return 0;
228}
229
230static int snd_sb8_capture_prepare(snd_pcm_substream_t * substream)
231{
232 unsigned long flags;
233 sb_t *chip = snd_pcm_substream_chip(substream);
234 snd_pcm_runtime_t *runtime = substream->runtime;
235 unsigned int mixreg, rate, size, count;
236
237 rate = runtime->rate;
238 switch (chip->hardware) {
239 case SB_HW_PRO:
240 if (runtime->channels > 1) {
241 snd_assert(rate == SB8_RATE(11025) || rate == SB8_RATE(22050), return -EINVAL);
242 chip->capture_format = SB_DSP_HI_INPUT_AUTO;
243 break;
244 }
245 chip->capture_format = (rate > 23000) ? SB_DSP_HI_INPUT_AUTO : SB_DSP_LO_INPUT_AUTO;
246 break;
247 case SB_HW_201:
248 if (rate > 13000) {
249 chip->capture_format = SB_DSP_HI_INPUT_AUTO;
250 break;
251 }
252 /* fallthru */
253 case SB_HW_20:
254 chip->capture_format = SB_DSP_LO_INPUT_AUTO;
255 break;
256 case SB_HW_10:
257 chip->capture_format = SB_DSP_INPUT;
258 break;
259 default:
260 return -EINVAL;
261 }
262 size = chip->c_dma_size = snd_pcm_lib_buffer_bytes(substream);
263 count = chip->c_period_size = snd_pcm_lib_period_bytes(substream);
264 spin_lock_irqsave(&chip->reg_lock, flags);
265 snd_sbdsp_command(chip, SB_DSP_SPEAKER_OFF);
266 if (runtime->channels > 1)
267 snd_sbdsp_command(chip, SB_DSP_STEREO_8BIT);
268 snd_sbdsp_command(chip, SB_DSP_SAMPLE_RATE);
269 if (runtime->channels > 1) {
270 snd_sbdsp_command(chip, 256 - runtime->rate_den / 2);
271 spin_lock(&chip->mixer_lock);
272 /* save input filter status and turn it off */
273 mixreg = snd_sbmixer_read(chip, SB_DSP_CAPTURE_FILT);
274 snd_sbmixer_write(chip, SB_DSP_CAPTURE_FILT, mixreg | 0x20);
275 spin_unlock(&chip->mixer_lock);
276 /* just use force_mode16 for temporary storate... */
277 chip->force_mode16 = mixreg;
278 } else {
279 snd_sbdsp_command(chip, 256 - runtime->rate_den);
280 }
281 if (chip->capture_format != SB_DSP_OUTPUT) {
282 count--;
283 snd_sbdsp_command(chip, SB_DSP_BLOCK_SIZE);
284 snd_sbdsp_command(chip, count & 0xff);
285 snd_sbdsp_command(chip, count >> 8);
286 }
287 spin_unlock_irqrestore(&chip->reg_lock, flags);
288 snd_dma_program(chip->dma8, runtime->dma_addr,
289 size, DMA_MODE_READ | DMA_AUTOINIT);
290 return 0;
291}
292
293static int snd_sb8_capture_trigger(snd_pcm_substream_t * substream,
294 int cmd)
295{
296 unsigned long flags;
297 sb_t *chip = snd_pcm_substream_chip(substream);
298 unsigned int count;
299
300 spin_lock_irqsave(&chip->reg_lock, flags);
301 switch (cmd) {
302 case SNDRV_PCM_TRIGGER_START:
303 snd_sbdsp_command(chip, chip->capture_format);
304 if (chip->capture_format == SB_DSP_INPUT) {
305 count = chip->c_period_size - 1;
306 snd_sbdsp_command(chip, count & 0xff);
307 snd_sbdsp_command(chip, count >> 8);
308 }
309 break;
310 case SNDRV_PCM_TRIGGER_STOP:
311 if (chip->capture_format == SB_DSP_HI_INPUT_AUTO) {
312 snd_pcm_runtime_t *runtime = substream->runtime;
313 snd_sbdsp_reset(chip);
314 if (runtime->channels > 1) {
315 /* restore input filter status */
316 spin_lock(&chip->mixer_lock);
317 snd_sbmixer_write(chip, SB_DSP_CAPTURE_FILT, chip->force_mode16);
318 spin_unlock(&chip->mixer_lock);
319 /* set hardware to mono mode */
320 snd_sbdsp_command(chip, SB_DSP_MONO_8BIT);
321 }
322 } else {
323 snd_sbdsp_command(chip, SB_DSP_DMA8_OFF);
324 }
325 snd_sbdsp_command(chip, SB_DSP_SPEAKER_OFF);
326 }
327 spin_unlock_irqrestore(&chip->reg_lock, flags);
328 chip->mode = (cmd == SNDRV_PCM_TRIGGER_START) ? SB_MODE_CAPTURE_8 : SB_MODE_HALT;
329 return 0;
330}
331
332irqreturn_t snd_sb8dsp_interrupt(sb_t *chip)
333{
334 snd_pcm_substream_t *substream;
335 snd_pcm_runtime_t *runtime;
336
337#if 0
338 snd_printk("sb8: interrupt\n");
339#endif
340 snd_sb_ack_8bit(chip);
341 switch (chip->mode) {
342 case SB_MODE_PLAYBACK_8: /* ok.. playback is active */
343 substream = chip->playback_substream;
344 runtime = substream->runtime;
345 if (chip->playback_format == SB_DSP_OUTPUT)
346 snd_sb8_playback_trigger(substream, SNDRV_PCM_TRIGGER_START);
347 snd_pcm_period_elapsed(substream);
348 break;
349 case SB_MODE_CAPTURE_8:
350 substream = chip->capture_substream;
351 runtime = substream->runtime;
352 if (chip->capture_format == SB_DSP_INPUT)
353 snd_sb8_capture_trigger(substream, SNDRV_PCM_TRIGGER_START);
354 snd_pcm_period_elapsed(substream);
355 break;
356 }
357 return IRQ_HANDLED;
358}
359
360static snd_pcm_uframes_t snd_sb8_playback_pointer(snd_pcm_substream_t * substream)
361{
362 sb_t *chip = snd_pcm_substream_chip(substream);
363 size_t ptr;
364
365 if (chip->mode != SB_MODE_PLAYBACK_8)
366 return 0;
367 ptr = snd_dma_pointer(chip->dma8, chip->p_dma_size);
368 return bytes_to_frames(substream->runtime, ptr);
369}
370
371static snd_pcm_uframes_t snd_sb8_capture_pointer(snd_pcm_substream_t * substream)
372{
373 sb_t *chip = snd_pcm_substream_chip(substream);
374 size_t ptr;
375
376 if (chip->mode != SB_MODE_CAPTURE_8)
377 return 0;
378 ptr = snd_dma_pointer(chip->dma8, chip->c_dma_size);
379 return bytes_to_frames(substream->runtime, ptr);
380}
381
382/*
383
384 */
385
386static snd_pcm_hardware_t snd_sb8_playback =
387{
388 .info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED |
389 SNDRV_PCM_INFO_MMAP_VALID),
390 .formats = SNDRV_PCM_FMTBIT_U8,
391 .rates = (SNDRV_PCM_RATE_CONTINUOUS | SNDRV_PCM_RATE_8000 |
392 SNDRV_PCM_RATE_11025 | SNDRV_PCM_RATE_22050),
393 .rate_min = 4000,
394 .rate_max = 23000,
395 .channels_min = 1,
396 .channels_max = 1,
397 .buffer_bytes_max = 65536,
398 .period_bytes_min = 64,
399 .period_bytes_max = 65536,
400 .periods_min = 1,
401 .periods_max = 1024,
402 .fifo_size = 0,
403};
404
405static snd_pcm_hardware_t snd_sb8_capture =
406{
407 .info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED |
408 SNDRV_PCM_INFO_MMAP_VALID),
409 .formats = SNDRV_PCM_FMTBIT_U8,
410 .rates = (SNDRV_PCM_RATE_CONTINUOUS | SNDRV_PCM_RATE_8000 |
411 SNDRV_PCM_RATE_11025),
412 .rate_min = 4000,
413 .rate_max = 13000,
414 .channels_min = 1,
415 .channels_max = 1,
416 .buffer_bytes_max = 65536,
417 .period_bytes_min = 64,
418 .period_bytes_max = 65536,
419 .periods_min = 1,
420 .periods_max = 1024,
421 .fifo_size = 0,
422};
423
424/*
425 *
426 */
427
428static int snd_sb8_open(snd_pcm_substream_t *substream)
429{
430 sb_t *chip = snd_pcm_substream_chip(substream);
431 snd_pcm_runtime_t *runtime = substream->runtime;
432 unsigned long flags;
433
434 spin_lock_irqsave(&chip->open_lock, flags);
435 if (chip->open) {
436 spin_unlock_irqrestore(&chip->open_lock, flags);
437 return -EAGAIN;
438 }
439 chip->open |= SB_OPEN_PCM;
440 spin_unlock_irqrestore(&chip->open_lock, flags);
441 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
442 chip->playback_substream = substream;
443 runtime->hw = snd_sb8_playback;
444 } else {
445 chip->capture_substream = substream;
446 runtime->hw = snd_sb8_capture;
447 }
448 switch (chip->hardware) {
449 case SB_HW_PRO:
450 runtime->hw.rate_max = 44100;
451 runtime->hw.channels_max = 2;
452 snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_RATE,
453 snd_sb8_hw_constraint_rate_channels, NULL,
454 SNDRV_PCM_HW_PARAM_CHANNELS,
455 SNDRV_PCM_HW_PARAM_RATE, -1);
456 snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS,
457 snd_sb8_hw_constraint_channels_rate, NULL,
458 SNDRV_PCM_HW_PARAM_RATE, -1);
459 break;
460 case SB_HW_201:
461 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
462 runtime->hw.rate_max = 44100;
463 } else {
464 runtime->hw.rate_max = 15000;
465 }
466 default:
467 break;
468 }
469 snd_pcm_hw_constraint_ratnums(runtime, 0, SNDRV_PCM_HW_PARAM_RATE,
470 &hw_constraints_clock);
471 return 0;
472}
473
474static int snd_sb8_close(snd_pcm_substream_t *substream)
475{
476 unsigned long flags;
477 sb_t *chip = snd_pcm_substream_chip(substream);
478
479 chip->playback_substream = NULL;
480 chip->capture_substream = NULL;
481 spin_lock_irqsave(&chip->open_lock, flags);
482 chip->open &= ~SB_OPEN_PCM;
483 spin_unlock_irqrestore(&chip->open_lock, flags);
484 return 0;
485}
486
487/*
488 * Initialization part
489 */
490
491static snd_pcm_ops_t snd_sb8_playback_ops = {
492 .open = snd_sb8_open,
493 .close = snd_sb8_close,
494 .ioctl = snd_pcm_lib_ioctl,
495 .hw_params = snd_sb8_hw_params,
496 .hw_free = snd_sb8_hw_free,
497 .prepare = snd_sb8_playback_prepare,
498 .trigger = snd_sb8_playback_trigger,
499 .pointer = snd_sb8_playback_pointer,
500};
501
502static snd_pcm_ops_t snd_sb8_capture_ops = {
503 .open = snd_sb8_open,
504 .close = snd_sb8_close,
505 .ioctl = snd_pcm_lib_ioctl,
506 .hw_params = snd_sb8_hw_params,
507 .hw_free = snd_sb8_hw_free,
508 .prepare = snd_sb8_capture_prepare,
509 .trigger = snd_sb8_capture_trigger,
510 .pointer = snd_sb8_capture_pointer,
511};
512
513static void snd_sb8dsp_pcm_free(snd_pcm_t *pcm)
514{
515 snd_pcm_lib_preallocate_free_for_all(pcm);
516}
517
518int snd_sb8dsp_pcm(sb_t *chip, int device, snd_pcm_t ** rpcm)
519{
520 snd_card_t *card = chip->card;
521 snd_pcm_t *pcm;
522 int err;
523
524 if (rpcm)
525 *rpcm = NULL;
526 if ((err = snd_pcm_new(card, "SB8 DSP", device, 1, 1, &pcm)) < 0)
527 return err;
528 sprintf(pcm->name, "DSP v%i.%i", chip->version >> 8, chip->version & 0xff);
529 pcm->info_flags = SNDRV_PCM_INFO_HALF_DUPLEX;
530 pcm->private_data = chip;
531 pcm->private_free = snd_sb8dsp_pcm_free;
532
533 snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_sb8_playback_ops);
534 snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_sb8_capture_ops);
535
536 snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV,
537 snd_dma_isa_data(),
538 64*1024, 64*1024);
539
540 if (rpcm)
541 *rpcm = pcm;
542 return 0;
543}
544
545EXPORT_SYMBOL(snd_sb8dsp_pcm);
546EXPORT_SYMBOL(snd_sb8dsp_interrupt);
547 /* sb8_midi.c */
548EXPORT_SYMBOL(snd_sb8dsp_midi_interrupt);
549EXPORT_SYMBOL(snd_sb8dsp_midi);
550
551/*
552 * INIT part
553 */
554
555static int __init alsa_sb8_init(void)
556{
557 return 0;
558}
559
560static void __exit alsa_sb8_exit(void)
561{
562}
563
564module_init(alsa_sb8_init)
565module_exit(alsa_sb8_exit)
diff --git a/sound/isa/sb/sb8_midi.c b/sound/isa/sb/sb8_midi.c
new file mode 100644
index 000000000000..d2c633a40e74
--- /dev/null
+++ b/sound/isa/sb/sb8_midi.c
@@ -0,0 +1,293 @@
1/*
2 * Copyright (c) by Jaroslav Kysela <perex@suse.cz>
3 * Routines for control of SoundBlaster cards - MIDI interface
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 *
19 * --
20 *
21 * Sun May 9 22:54:38 BST 1999 George David Morrison <gdm@gedamo.demon.co.uk>
22 * Fixed typo in snd_sb8dsp_midi_new_device which prevented midi from
23 * working.
24 *
25 * Sun May 11 12:34:56 UTC 2003 Clemens Ladisch <clemens@ladisch.de>
26 * Added full duplex UART mode for DSP version 2.0 and later.
27 */
28
29#include <sound/driver.h>
30#include <asm/io.h>
31#include <linux/time.h>
32#include <sound/core.h>
33#include <sound/sb.h>
34
35/*
36
37 */
38
39irqreturn_t snd_sb8dsp_midi_interrupt(sb_t * chip)
40{
41 snd_rawmidi_t *rmidi;
42 int max = 64;
43 char byte;
44
45 if (chip == NULL || (rmidi = chip->rmidi) == NULL) {
46 inb(SBP(chip, DATA_AVAIL)); /* ack interrupt */
47 return IRQ_NONE;
48 }
49 spin_lock(&chip->midi_input_lock);
50 while (max-- > 0) {
51 if (inb(SBP(chip, DATA_AVAIL)) & 0x80) {
52 byte = inb(SBP(chip, READ));
53 if (chip->open & SB_OPEN_MIDI_INPUT_TRIGGER) {
54 snd_rawmidi_receive(chip->midi_substream_input, &byte, 1);
55 }
56 }
57 }
58 spin_unlock(&chip->midi_input_lock);
59 return IRQ_HANDLED;
60}
61
62/*
63
64 */
65
66static int snd_sb8dsp_midi_input_open(snd_rawmidi_substream_t * substream)
67{
68 unsigned long flags;
69 sb_t *chip;
70 unsigned int valid_open_flags;
71
72 chip = substream->rmidi->private_data;
73 valid_open_flags = chip->hardware >= SB_HW_20
74 ? SB_OPEN_MIDI_OUTPUT | SB_OPEN_MIDI_OUTPUT_TRIGGER : 0;
75 spin_lock_irqsave(&chip->open_lock, flags);
76 if (chip->open & ~valid_open_flags) {
77 spin_unlock_irqrestore(&chip->open_lock, flags);
78 return -EAGAIN;
79 }
80 chip->open |= SB_OPEN_MIDI_INPUT;
81 chip->midi_substream_input = substream;
82 if (!(chip->open & SB_OPEN_MIDI_OUTPUT)) {
83 spin_unlock_irqrestore(&chip->open_lock, flags);
84 snd_sbdsp_reset(chip); /* reset DSP */
85 if (chip->hardware >= SB_HW_20)
86 snd_sbdsp_command(chip, SB_DSP_MIDI_UART_IRQ);
87 } else {
88 spin_unlock_irqrestore(&chip->open_lock, flags);
89 }
90 return 0;
91}
92
93static int snd_sb8dsp_midi_output_open(snd_rawmidi_substream_t * substream)
94{
95 unsigned long flags;
96 sb_t *chip;
97 unsigned int valid_open_flags;
98
99 chip = substream->rmidi->private_data;
100 valid_open_flags = chip->hardware >= SB_HW_20
101 ? SB_OPEN_MIDI_INPUT | SB_OPEN_MIDI_INPUT_TRIGGER : 0;
102 spin_lock_irqsave(&chip->open_lock, flags);
103 if (chip->open & ~valid_open_flags) {
104 spin_unlock_irqrestore(&chip->open_lock, flags);
105 return -EAGAIN;
106 }
107 chip->open |= SB_OPEN_MIDI_OUTPUT;
108 chip->midi_substream_output = substream;
109 if (!(chip->open & SB_OPEN_MIDI_INPUT)) {
110 spin_unlock_irqrestore(&chip->open_lock, flags);
111 snd_sbdsp_reset(chip); /* reset DSP */
112 if (chip->hardware >= SB_HW_20)
113 snd_sbdsp_command(chip, SB_DSP_MIDI_UART_IRQ);
114 } else {
115 spin_unlock_irqrestore(&chip->open_lock, flags);
116 }
117 return 0;
118}
119
120static int snd_sb8dsp_midi_input_close(snd_rawmidi_substream_t * substream)
121{
122 unsigned long flags;
123 sb_t *chip;
124
125 chip = substream->rmidi->private_data;
126 spin_lock_irqsave(&chip->open_lock, flags);
127 chip->open &= ~(SB_OPEN_MIDI_INPUT | SB_OPEN_MIDI_INPUT_TRIGGER);
128 chip->midi_substream_input = NULL;
129 if (!(chip->open & SB_OPEN_MIDI_OUTPUT)) {
130 spin_unlock_irqrestore(&chip->open_lock, flags);
131 snd_sbdsp_reset(chip); /* reset DSP */
132 } else {
133 spin_unlock_irqrestore(&chip->open_lock, flags);
134 }
135 return 0;
136}
137
138static int snd_sb8dsp_midi_output_close(snd_rawmidi_substream_t * substream)
139{
140 unsigned long flags;
141 sb_t *chip;
142
143 chip = substream->rmidi->private_data;
144 spin_lock_irqsave(&chip->open_lock, flags);
145 chip->open &= ~(SB_OPEN_MIDI_OUTPUT | SB_OPEN_MIDI_OUTPUT_TRIGGER);
146 chip->midi_substream_output = NULL;
147 if (!(chip->open & SB_OPEN_MIDI_INPUT)) {
148 spin_unlock_irqrestore(&chip->open_lock, flags);
149 snd_sbdsp_reset(chip); /* reset DSP */
150 } else {
151 spin_unlock_irqrestore(&chip->open_lock, flags);
152 }
153 return 0;
154}
155
156static void snd_sb8dsp_midi_input_trigger(snd_rawmidi_substream_t * substream, int up)
157{
158 unsigned long flags;
159 sb_t *chip;
160
161 chip = substream->rmidi->private_data;
162 spin_lock_irqsave(&chip->open_lock, flags);
163 if (up) {
164 if (!(chip->open & SB_OPEN_MIDI_INPUT_TRIGGER)) {
165 if (chip->hardware < SB_HW_20)
166 snd_sbdsp_command(chip, SB_DSP_MIDI_INPUT_IRQ);
167 chip->open |= SB_OPEN_MIDI_INPUT_TRIGGER;
168 }
169 } else {
170 if (chip->open & SB_OPEN_MIDI_INPUT_TRIGGER) {
171 if (chip->hardware < SB_HW_20)
172 snd_sbdsp_command(chip, SB_DSP_MIDI_INPUT_IRQ);
173 chip->open &= ~SB_OPEN_MIDI_INPUT_TRIGGER;
174 }
175 }
176 spin_unlock_irqrestore(&chip->open_lock, flags);
177}
178
179static void snd_sb8dsp_midi_output_write(snd_rawmidi_substream_t * substream)
180{
181 unsigned long flags;
182 sb_t *chip;
183 char byte;
184 int max = 32;
185
186 /* how big is Tx FIFO? */
187 chip = substream->rmidi->private_data;
188 while (max-- > 0) {
189 spin_lock_irqsave(&chip->open_lock, flags);
190 if (snd_rawmidi_transmit_peek(substream, &byte, 1) != 1) {
191 chip->open &= ~SB_OPEN_MIDI_OUTPUT_TRIGGER;
192 del_timer(&chip->midi_timer);
193 spin_unlock_irqrestore(&chip->open_lock, flags);
194 break;
195 }
196 if (chip->hardware >= SB_HW_20) {
197 int timeout = 8;
198 while ((inb(SBP(chip, STATUS)) & 0x80) != 0 && --timeout > 0)
199 ;
200 if (timeout == 0) {
201 /* Tx FIFO full - try again later */
202 spin_unlock_irqrestore(&chip->open_lock, flags);
203 break;
204 }
205 outb(byte, SBP(chip, WRITE));
206 } else {
207 snd_sbdsp_command(chip, SB_DSP_MIDI_OUTPUT);
208 snd_sbdsp_command(chip, byte);
209 }
210 snd_rawmidi_transmit_ack(substream, 1);
211 spin_unlock_irqrestore(&chip->open_lock, flags);
212 }
213}
214
215static void snd_sb8dsp_midi_output_timer(unsigned long data)
216{
217 snd_rawmidi_substream_t * substream = (snd_rawmidi_substream_t *) data;
218 sb_t * chip = substream->rmidi->private_data;
219 unsigned long flags;
220
221 spin_lock_irqsave(&chip->open_lock, flags);
222 chip->midi_timer.expires = 1 + jiffies;
223 add_timer(&chip->midi_timer);
224 spin_unlock_irqrestore(&chip->open_lock, flags);
225 snd_sb8dsp_midi_output_write(substream);
226}
227
228static void snd_sb8dsp_midi_output_trigger(snd_rawmidi_substream_t * substream, int up)
229{
230 unsigned long flags;
231 sb_t *chip;
232
233 chip = substream->rmidi->private_data;
234 spin_lock_irqsave(&chip->open_lock, flags);
235 if (up) {
236 if (!(chip->open & SB_OPEN_MIDI_OUTPUT_TRIGGER)) {
237 init_timer(&chip->midi_timer);
238 chip->midi_timer.function = snd_sb8dsp_midi_output_timer;
239 chip->midi_timer.data = (unsigned long) substream;
240 chip->midi_timer.expires = 1 + jiffies;
241 add_timer(&chip->midi_timer);
242 chip->open |= SB_OPEN_MIDI_OUTPUT_TRIGGER;
243 }
244 } else {
245 if (chip->open & SB_OPEN_MIDI_OUTPUT_TRIGGER) {
246 chip->open &= ~SB_OPEN_MIDI_OUTPUT_TRIGGER;
247 }
248 }
249 spin_unlock_irqrestore(&chip->open_lock, flags);
250
251 if (up)
252 snd_sb8dsp_midi_output_write(substream);
253}
254
255/*
256
257 */
258
259static snd_rawmidi_ops_t snd_sb8dsp_midi_output =
260{
261 .open = snd_sb8dsp_midi_output_open,
262 .close = snd_sb8dsp_midi_output_close,
263 .trigger = snd_sb8dsp_midi_output_trigger,
264};
265
266static snd_rawmidi_ops_t snd_sb8dsp_midi_input =
267{
268 .open = snd_sb8dsp_midi_input_open,
269 .close = snd_sb8dsp_midi_input_close,
270 .trigger = snd_sb8dsp_midi_input_trigger,
271};
272
273int snd_sb8dsp_midi(sb_t *chip, int device, snd_rawmidi_t ** rrawmidi)
274{
275 snd_rawmidi_t *rmidi;
276 int err;
277
278 if (rrawmidi)
279 *rrawmidi = NULL;
280 if ((err = snd_rawmidi_new(chip->card, "SB8 MIDI", device, 1, 1, &rmidi)) < 0)
281 return err;
282 strcpy(rmidi->name, "SB8 MIDI");
283 snd_rawmidi_set_ops(rmidi, SNDRV_RAWMIDI_STREAM_OUTPUT, &snd_sb8dsp_midi_output);
284 snd_rawmidi_set_ops(rmidi, SNDRV_RAWMIDI_STREAM_INPUT, &snd_sb8dsp_midi_input);
285 rmidi->info_flags |= SNDRV_RAWMIDI_INFO_OUTPUT | SNDRV_RAWMIDI_INFO_INPUT;
286 if (chip->hardware >= SB_HW_20)
287 rmidi->info_flags |= SNDRV_RAWMIDI_INFO_DUPLEX;
288 rmidi->private_data = chip;
289 chip->rmidi = rmidi;
290 if (rrawmidi)
291 *rrawmidi = rmidi;
292 return 0;
293}
diff --git a/sound/isa/sb/sb_common.c b/sound/isa/sb/sb_common.c
new file mode 100644
index 000000000000..5b6bde213ea0
--- /dev/null
+++ b/sound/isa/sb/sb_common.c
@@ -0,0 +1,313 @@
1/*
2 * Copyright (c) by Jaroslav Kysela <perex@suse.cz>
3 * Uros Bizjak <uros@kss-loka.si>
4 *
5 * Lowlevel routines for control of Sound Blaster cards
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 *
21 */
22
23#include <sound/driver.h>
24#include <linux/delay.h>
25#include <linux/init.h>
26#include <linux/interrupt.h>
27#include <linux/slab.h>
28#include <linux/ioport.h>
29#include <sound/core.h>
30#include <sound/sb.h>
31#include <sound/initval.h>
32
33#include <asm/io.h>
34#include <asm/dma.h>
35
36MODULE_AUTHOR("Jaroslav Kysela <perex@suse.cz>");
37MODULE_DESCRIPTION("ALSA lowlevel driver for Sound Blaster cards");
38MODULE_LICENSE("GPL");
39
40#define BUSY_LOOPS 100000
41
42#undef IO_DEBUG
43
44int snd_sbdsp_command(sb_t *chip, unsigned char val)
45{
46 int i;
47#ifdef IO_DEBUG
48 snd_printk("command 0x%x\n", val);
49#endif
50 for (i = BUSY_LOOPS; i; i--)
51 if ((inb(SBP(chip, STATUS)) & 0x80) == 0) {
52 outb(val, SBP(chip, COMMAND));
53 return 1;
54 }
55 snd_printd("%s [0x%lx]: timeout (0x%x)\n", __FUNCTION__, chip->port, val);
56 return 0;
57}
58
59int snd_sbdsp_get_byte(sb_t *chip)
60{
61 int val;
62 int i;
63 for (i = BUSY_LOOPS; i; i--) {
64 if (inb(SBP(chip, DATA_AVAIL)) & 0x80) {
65 val = inb(SBP(chip, READ));
66#ifdef IO_DEBUG
67 snd_printk("get_byte 0x%x\n", val);
68#endif
69 return val;
70 }
71 }
72 snd_printd("%s [0x%lx]: timeout\n", __FUNCTION__, chip->port);
73 return -ENODEV;
74}
75
76int snd_sbdsp_reset(sb_t *chip)
77{
78 int i;
79
80 outb(1, SBP(chip, RESET));
81 udelay(10);
82 outb(0, SBP(chip, RESET));
83 udelay(30);
84 for (i = BUSY_LOOPS; i; i--)
85 if (inb(SBP(chip, DATA_AVAIL)) & 0x80) {
86 if (inb(SBP(chip, READ)) == 0xaa)
87 return 0;
88 else
89 break;
90 }
91 snd_printdd("%s [0x%lx] failed...\n", __FUNCTION__, chip->port);
92 return -ENODEV;
93}
94
95static int snd_sbdsp_version(sb_t * chip)
96{
97 unsigned int result = -ENODEV;
98
99 snd_sbdsp_command(chip, SB_DSP_GET_VERSION);
100 result = (short) snd_sbdsp_get_byte(chip) << 8;
101 result |= (short) snd_sbdsp_get_byte(chip);
102 return result;
103}
104
105static int snd_sbdsp_probe(sb_t * chip)
106{
107 int version;
108 int major, minor;
109 char *str;
110 unsigned long flags;
111
112 /*
113 * initialization sequence
114 */
115
116 spin_lock_irqsave(&chip->reg_lock, flags);
117 if (snd_sbdsp_reset(chip) < 0) {
118 spin_unlock_irqrestore(&chip->reg_lock, flags);
119 return -ENODEV;
120 }
121 version = snd_sbdsp_version(chip);
122 if (version < 0) {
123 spin_unlock_irqrestore(&chip->reg_lock, flags);
124 return -ENODEV;
125 }
126 spin_unlock_irqrestore(&chip->reg_lock, flags);
127 major = version >> 8;
128 minor = version & 0xff;
129 snd_printdd("SB [0x%lx]: DSP chip found, version = %i.%i\n",
130 chip->port, major, minor);
131
132 switch (chip->hardware) {
133 case SB_HW_AUTO:
134 switch (major) {
135 case 1:
136 chip->hardware = SB_HW_10;
137 str = "1.0";
138 break;
139 case 2:
140 if (minor) {
141 chip->hardware = SB_HW_201;
142 str = "2.01+";
143 } else {
144 chip->hardware = SB_HW_20;
145 str = "2.0";
146 }
147 break;
148 case 3:
149 chip->hardware = SB_HW_PRO;
150 str = "Pro";
151 break;
152 case 4:
153 chip->hardware = SB_HW_16;
154 str = "16";
155 break;
156 default:
157 snd_printk("SB [0x%lx]: unknown DSP chip version %i.%i\n",
158 chip->port, major, minor);
159 return -ENODEV;
160 }
161 break;
162 case SB_HW_ALS100:
163 str = "16 (ALS-100)";
164 break;
165 case SB_HW_ALS4000:
166 str = "16 (ALS-4000)";
167 break;
168 case SB_HW_DT019X:
169 str = "(DT019X/ALS007)";
170 break;
171 default:
172 return -ENODEV;
173 }
174 sprintf(chip->name, "Sound Blaster %s", str);
175 chip->version = (major << 8) | minor;
176 return 0;
177}
178
179static int snd_sbdsp_free(sb_t *chip)
180{
181 if (chip->res_port) {
182 release_resource(chip->res_port);
183 kfree_nocheck(chip->res_port);
184 }
185 if (chip->irq >= 0)
186 free_irq(chip->irq, (void *) chip);
187#ifdef CONFIG_ISA
188 if (chip->dma8 >= 0) {
189 disable_dma(chip->dma8);
190 free_dma(chip->dma8);
191 }
192 if (chip->dma16 >= 0 && chip->dma16 != chip->dma8) {
193 disable_dma(chip->dma16);
194 free_dma(chip->dma16);
195 }
196#endif
197 kfree(chip);
198 return 0;
199}
200
201static int snd_sbdsp_dev_free(snd_device_t *device)
202{
203 sb_t *chip = device->device_data;
204 return snd_sbdsp_free(chip);
205}
206
207int snd_sbdsp_create(snd_card_t *card,
208 unsigned long port,
209 int irq,
210 irqreturn_t (*irq_handler)(int, void *, struct pt_regs *),
211 int dma8,
212 int dma16,
213 unsigned short hardware,
214 sb_t **r_chip)
215{
216 sb_t *chip;
217 int err;
218 static snd_device_ops_t ops = {
219 .dev_free = snd_sbdsp_dev_free,
220 };
221
222 snd_assert(r_chip != NULL, return -EINVAL);
223 *r_chip = NULL;
224 chip = kcalloc(1, sizeof(*chip), GFP_KERNEL);
225 if (chip == NULL)
226 return -ENOMEM;
227 spin_lock_init(&chip->reg_lock);
228 spin_lock_init(&chip->open_lock);
229 spin_lock_init(&chip->midi_input_lock);
230 spin_lock_init(&chip->mixer_lock);
231 chip->irq = -1;
232 chip->dma8 = -1;
233 chip->dma16 = -1;
234 chip->port = port;
235
236 if (request_irq(irq, irq_handler, hardware == SB_HW_ALS4000 ?
237 SA_INTERRUPT | SA_SHIRQ : SA_INTERRUPT,
238 "SoundBlaster", (void *) chip)) {
239 snd_printk(KERN_ERR "sb: can't grab irq %d\n", irq);
240 snd_sbdsp_free(chip);
241 return -EBUSY;
242 }
243 chip->irq = irq;
244
245 if (hardware == SB_HW_ALS4000)
246 goto __skip_allocation;
247
248 if ((chip->res_port = request_region(port, 16, "SoundBlaster")) == NULL) {
249 snd_printk(KERN_ERR "sb: can't grab port 0x%lx\n", port);
250 snd_sbdsp_free(chip);
251 return -EBUSY;
252 }
253
254#ifdef CONFIG_ISA
255 if (dma8 >= 0 && request_dma(dma8, "SoundBlaster - 8bit")) {
256 snd_printk(KERN_ERR "sb: can't grab DMA8 %d\n", dma8);
257 snd_sbdsp_free(chip);
258 return -EBUSY;
259 }
260 chip->dma8 = dma8;
261 if (dma16 >= 0) {
262 if (hardware != SB_HW_ALS100 && (dma16 < 5 || dma16 > 7)) {
263 /* no duplex */
264 dma16 = -1;
265 } else if (request_dma(dma16, "SoundBlaster - 16bit")) {
266 snd_printk(KERN_ERR "sb: can't grab DMA16 %d\n", dma16);
267 snd_sbdsp_free(chip);
268 return -EBUSY;
269 }
270 }
271 chip->dma16 = dma16;
272#endif
273
274 __skip_allocation:
275 chip->card = card;
276 chip->hardware = hardware;
277 if ((err = snd_sbdsp_probe(chip)) < 0) {
278 snd_sbdsp_free(chip);
279 return err;
280 }
281 if ((err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops)) < 0) {
282 snd_sbdsp_free(chip);
283 return err;
284 }
285 *r_chip = chip;
286 return 0;
287}
288
289EXPORT_SYMBOL(snd_sbdsp_command);
290EXPORT_SYMBOL(snd_sbdsp_get_byte);
291EXPORT_SYMBOL(snd_sbdsp_reset);
292EXPORT_SYMBOL(snd_sbdsp_create);
293/* sb_mixer.c */
294EXPORT_SYMBOL(snd_sbmixer_write);
295EXPORT_SYMBOL(snd_sbmixer_read);
296EXPORT_SYMBOL(snd_sbmixer_new);
297EXPORT_SYMBOL(snd_sbmixer_add_ctl);
298
299/*
300 * INIT part
301 */
302
303static int __init alsa_sb_common_init(void)
304{
305 return 0;
306}
307
308static void __exit alsa_sb_common_exit(void)
309{
310}
311
312module_init(alsa_sb_common_init)
313module_exit(alsa_sb_common_exit)
diff --git a/sound/isa/sb/sb_mixer.c b/sound/isa/sb/sb_mixer.c
new file mode 100644
index 000000000000..cc5a2c6dec16
--- /dev/null
+++ b/sound/isa/sb/sb_mixer.c
@@ -0,0 +1,844 @@
1/*
2 * Copyright (c) by Jaroslav Kysela <perex@suse.cz>
3 * Routines for Sound Blaster mixer control
4 *
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 *
20 */
21
22#include <sound/driver.h>
23#include <asm/io.h>
24#include <linux/delay.h>
25#include <linux/time.h>
26#include <sound/core.h>
27#include <sound/sb.h>
28#include <sound/control.h>
29
30#undef IO_DEBUG
31
32void snd_sbmixer_write(sb_t *chip, unsigned char reg, unsigned char data)
33{
34 outb(reg, SBP(chip, MIXER_ADDR));
35 udelay(10);
36 outb(data, SBP(chip, MIXER_DATA));
37 udelay(10);
38#ifdef IO_DEBUG
39 snd_printk("mixer_write 0x%x 0x%x\n", reg, data);
40#endif
41}
42
43unsigned char snd_sbmixer_read(sb_t *chip, unsigned char reg)
44{
45 unsigned char result;
46
47 outb(reg, SBP(chip, MIXER_ADDR));
48 udelay(10);
49 result = inb(SBP(chip, MIXER_DATA));
50 udelay(10);
51#ifdef IO_DEBUG
52 snd_printk("mixer_read 0x%x 0x%x\n", reg, result);
53#endif
54 return result;
55}
56
57/*
58 * Single channel mixer element
59 */
60
61static int snd_sbmixer_info_single(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
62{
63 int mask = (kcontrol->private_value >> 24) & 0xff;
64
65 uinfo->type = mask == 1 ? SNDRV_CTL_ELEM_TYPE_BOOLEAN : SNDRV_CTL_ELEM_TYPE_INTEGER;
66 uinfo->count = 1;
67 uinfo->value.integer.min = 0;
68 uinfo->value.integer.max = mask;
69 return 0;
70}
71
72static int snd_sbmixer_get_single(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
73{
74 sb_t *sb = snd_kcontrol_chip(kcontrol);
75 unsigned long flags;
76 int reg = kcontrol->private_value & 0xff;
77 int shift = (kcontrol->private_value >> 16) & 0xff;
78 int mask = (kcontrol->private_value >> 24) & 0xff;
79 unsigned char val;
80
81 spin_lock_irqsave(&sb->mixer_lock, flags);
82 val = (snd_sbmixer_read(sb, reg) >> shift) & mask;
83 spin_unlock_irqrestore(&sb->mixer_lock, flags);
84 ucontrol->value.integer.value[0] = val;
85 return 0;
86}
87
88static int snd_sbmixer_put_single(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
89{
90 sb_t *sb = snd_kcontrol_chip(kcontrol);
91 unsigned long flags;
92 int reg = kcontrol->private_value & 0xff;
93 int shift = (kcontrol->private_value >> 16) & 0x07;
94 int mask = (kcontrol->private_value >> 24) & 0xff;
95 int change;
96 unsigned char val, oval;
97
98 val = (ucontrol->value.integer.value[0] & mask) << shift;
99 spin_lock_irqsave(&sb->mixer_lock, flags);
100 oval = snd_sbmixer_read(sb, reg);
101 val = (oval & ~(mask << shift)) | val;
102 change = val != oval;
103 if (change)
104 snd_sbmixer_write(sb, reg, val);
105 spin_unlock_irqrestore(&sb->mixer_lock, flags);
106 return change;
107}
108
109/*
110 * Double channel mixer element
111 */
112
113static int snd_sbmixer_info_double(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
114{
115 int mask = (kcontrol->private_value >> 24) & 0xff;
116
117 uinfo->type = mask == 1 ? SNDRV_CTL_ELEM_TYPE_BOOLEAN : SNDRV_CTL_ELEM_TYPE_INTEGER;
118 uinfo->count = 2;
119 uinfo->value.integer.min = 0;
120 uinfo->value.integer.max = mask;
121 return 0;
122}
123
124static int snd_sbmixer_get_double(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
125{
126 sb_t *sb = snd_kcontrol_chip(kcontrol);
127 unsigned long flags;
128 int left_reg = kcontrol->private_value & 0xff;
129 int right_reg = (kcontrol->private_value >> 8) & 0xff;
130 int left_shift = (kcontrol->private_value >> 16) & 0x07;
131 int right_shift = (kcontrol->private_value >> 19) & 0x07;
132 int mask = (kcontrol->private_value >> 24) & 0xff;
133 unsigned char left, right;
134
135 spin_lock_irqsave(&sb->mixer_lock, flags);
136 left = (snd_sbmixer_read(sb, left_reg) >> left_shift) & mask;
137 right = (snd_sbmixer_read(sb, right_reg) >> right_shift) & mask;
138 spin_unlock_irqrestore(&sb->mixer_lock, flags);
139 ucontrol->value.integer.value[0] = left;
140 ucontrol->value.integer.value[1] = right;
141 return 0;
142}
143
144static int snd_sbmixer_put_double(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
145{
146 sb_t *sb = snd_kcontrol_chip(kcontrol);
147 unsigned long flags;
148 int left_reg = kcontrol->private_value & 0xff;
149 int right_reg = (kcontrol->private_value >> 8) & 0xff;
150 int left_shift = (kcontrol->private_value >> 16) & 0x07;
151 int right_shift = (kcontrol->private_value >> 19) & 0x07;
152 int mask = (kcontrol->private_value >> 24) & 0xff;
153 int change;
154 unsigned char left, right, oleft, oright;
155
156 left = (ucontrol->value.integer.value[0] & mask) << left_shift;
157 right = (ucontrol->value.integer.value[1] & mask) << right_shift;
158 spin_lock_irqsave(&sb->mixer_lock, flags);
159 if (left_reg == right_reg) {
160 oleft = snd_sbmixer_read(sb, left_reg);
161 left = (oleft & ~((mask << left_shift) | (mask << right_shift))) | left | right;
162 change = left != oleft;
163 if (change)
164 snd_sbmixer_write(sb, left_reg, left);
165 } else {
166 oleft = snd_sbmixer_read(sb, left_reg);
167 oright = snd_sbmixer_read(sb, right_reg);
168 left = (oleft & ~(mask << left_shift)) | left;
169 right = (oright & ~(mask << right_shift)) | right;
170 change = left != oleft || right != oright;
171 if (change) {
172 snd_sbmixer_write(sb, left_reg, left);
173 snd_sbmixer_write(sb, right_reg, right);
174 }
175 }
176 spin_unlock_irqrestore(&sb->mixer_lock, flags);
177 return change;
178}
179
180/*
181 * DT-019x / ALS-007 capture/input switch
182 */
183
184static int snd_dt019x_input_sw_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
185{
186 static char *texts[5] = {
187 "CD", "Mic", "Line", "Synth", "Master"
188 };
189
190 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
191 uinfo->count = 1;
192 uinfo->value.enumerated.items = 5;
193 if (uinfo->value.enumerated.item > 4)
194 uinfo->value.enumerated.item = 4;
195 strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]);
196 return 0;
197}
198
199static int snd_dt019x_input_sw_get(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
200{
201 sb_t *sb = snd_kcontrol_chip(kcontrol);
202 unsigned long flags;
203 unsigned char oval;
204
205 spin_lock_irqsave(&sb->mixer_lock, flags);
206 oval = snd_sbmixer_read(sb, SB_DT019X_CAPTURE_SW);
207 spin_unlock_irqrestore(&sb->mixer_lock, flags);
208 switch (oval & 0x07) {
209 case SB_DT019X_CAP_CD:
210 ucontrol->value.enumerated.item[0] = 0;
211 break;
212 case SB_DT019X_CAP_MIC:
213 ucontrol->value.enumerated.item[0] = 1;
214 break;
215 case SB_DT019X_CAP_LINE:
216 ucontrol->value.enumerated.item[0] = 2;
217 break;
218 case SB_DT019X_CAP_MAIN:
219 ucontrol->value.enumerated.item[0] = 4;
220 break;
221 /* To record the synth on these cards you must record the main. */
222 /* Thus SB_DT019X_CAP_SYNTH == SB_DT019X_CAP_MAIN and would cause */
223 /* duplicate case labels if left uncommented. */
224 /* case SB_DT019X_CAP_SYNTH:
225 * ucontrol->value.enumerated.item[0] = 3;
226 * break;
227 */
228 default:
229 ucontrol->value.enumerated.item[0] = 4;
230 break;
231 }
232 return 0;
233}
234
235static int snd_dt019x_input_sw_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
236{
237 sb_t *sb = snd_kcontrol_chip(kcontrol);
238 unsigned long flags;
239 int change;
240 unsigned char nval, oval;
241
242 if (ucontrol->value.enumerated.item[0] > 4)
243 return -EINVAL;
244 switch (ucontrol->value.enumerated.item[0]) {
245 case 0:
246 nval = SB_DT019X_CAP_CD;
247 break;
248 case 1:
249 nval = SB_DT019X_CAP_MIC;
250 break;
251 case 2:
252 nval = SB_DT019X_CAP_LINE;
253 break;
254 case 3:
255 nval = SB_DT019X_CAP_SYNTH;
256 break;
257 case 4:
258 nval = SB_DT019X_CAP_MAIN;
259 break;
260 default:
261 nval = SB_DT019X_CAP_MAIN;
262 }
263 spin_lock_irqsave(&sb->mixer_lock, flags);
264 oval = snd_sbmixer_read(sb, SB_DT019X_CAPTURE_SW);
265 change = nval != oval;
266 if (change)
267 snd_sbmixer_write(sb, SB_DT019X_CAPTURE_SW, nval);
268 spin_unlock_irqrestore(&sb->mixer_lock, flags);
269 return change;
270}
271
272/*
273 * SBPRO input multiplexer
274 */
275
276static int snd_sb8mixer_info_mux(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
277{
278 static char *texts[3] = {
279 "Mic", "CD", "Line"
280 };
281
282 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
283 uinfo->count = 1;
284 uinfo->value.enumerated.items = 3;
285 if (uinfo->value.enumerated.item > 2)
286 uinfo->value.enumerated.item = 2;
287 strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]);
288 return 0;
289}
290
291
292static int snd_sb8mixer_get_mux(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
293{
294 sb_t *sb = snd_kcontrol_chip(kcontrol);
295 unsigned long flags;
296 unsigned char oval;
297
298 spin_lock_irqsave(&sb->mixer_lock, flags);
299 oval = snd_sbmixer_read(sb, SB_DSP_CAPTURE_SOURCE);
300 spin_unlock_irqrestore(&sb->mixer_lock, flags);
301 switch ((oval >> 0x01) & 0x03) {
302 case SB_DSP_MIXS_CD:
303 ucontrol->value.enumerated.item[0] = 1;
304 break;
305 case SB_DSP_MIXS_LINE:
306 ucontrol->value.enumerated.item[0] = 2;
307 break;
308 default:
309 ucontrol->value.enumerated.item[0] = 0;
310 break;
311 }
312 return 0;
313}
314
315static int snd_sb8mixer_put_mux(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
316{
317 sb_t *sb = snd_kcontrol_chip(kcontrol);
318 unsigned long flags;
319 int change;
320 unsigned char nval, oval;
321
322 if (ucontrol->value.enumerated.item[0] > 2)
323 return -EINVAL;
324 switch (ucontrol->value.enumerated.item[0]) {
325 case 1:
326 nval = SB_DSP_MIXS_CD;
327 break;
328 case 2:
329 nval = SB_DSP_MIXS_LINE;
330 break;
331 default:
332 nval = SB_DSP_MIXS_MIC;
333 }
334 nval <<= 1;
335 spin_lock_irqsave(&sb->mixer_lock, flags);
336 oval = snd_sbmixer_read(sb, SB_DSP_CAPTURE_SOURCE);
337 nval |= oval & ~0x06;
338 change = nval != oval;
339 if (change)
340 snd_sbmixer_write(sb, SB_DSP_CAPTURE_SOURCE, nval);
341 spin_unlock_irqrestore(&sb->mixer_lock, flags);
342 return change;
343}
344
345/*
346 * SB16 input switch
347 */
348
349static int snd_sb16mixer_info_input_sw(snd_kcontrol_t * kcontrol, snd_ctl_elem_info_t * uinfo)
350{
351 uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
352 uinfo->count = 4;
353 uinfo->value.integer.min = 0;
354 uinfo->value.integer.max = 1;
355 return 0;
356}
357
358static int snd_sb16mixer_get_input_sw(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
359{
360 sb_t *sb = snd_kcontrol_chip(kcontrol);
361 unsigned long flags;
362 int reg1 = kcontrol->private_value & 0xff;
363 int reg2 = (kcontrol->private_value >> 8) & 0xff;
364 int left_shift = (kcontrol->private_value >> 16) & 0x0f;
365 int right_shift = (kcontrol->private_value >> 24) & 0x0f;
366 unsigned char val1, val2;
367
368 spin_lock_irqsave(&sb->mixer_lock, flags);
369 val1 = snd_sbmixer_read(sb, reg1);
370 val2 = snd_sbmixer_read(sb, reg2);
371 spin_unlock_irqrestore(&sb->mixer_lock, flags);
372 ucontrol->value.integer.value[0] = (val1 >> left_shift) & 0x01;
373 ucontrol->value.integer.value[1] = (val2 >> left_shift) & 0x01;
374 ucontrol->value.integer.value[2] = (val1 >> right_shift) & 0x01;
375 ucontrol->value.integer.value[3] = (val2 >> right_shift) & 0x01;
376 return 0;
377}
378
379static int snd_sb16mixer_put_input_sw(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
380{
381 sb_t *sb = snd_kcontrol_chip(kcontrol);
382 unsigned long flags;
383 int reg1 = kcontrol->private_value & 0xff;
384 int reg2 = (kcontrol->private_value >> 8) & 0xff;
385 int left_shift = (kcontrol->private_value >> 16) & 0x0f;
386 int right_shift = (kcontrol->private_value >> 24) & 0x0f;
387 int change;
388 unsigned char val1, val2, oval1, oval2;
389
390 spin_lock_irqsave(&sb->mixer_lock, flags);
391 oval1 = snd_sbmixer_read(sb, reg1);
392 oval2 = snd_sbmixer_read(sb, reg2);
393 val1 = oval1 & ~((1 << left_shift) | (1 << right_shift));
394 val2 = oval2 & ~((1 << left_shift) | (1 << right_shift));
395 val1 |= (ucontrol->value.integer.value[0] & 1) << left_shift;
396 val2 |= (ucontrol->value.integer.value[1] & 1) << left_shift;
397 val1 |= (ucontrol->value.integer.value[2] & 1) << right_shift;
398 val2 |= (ucontrol->value.integer.value[3] & 1) << right_shift;
399 change = val1 != oval1 || val2 != oval2;
400 if (change) {
401 snd_sbmixer_write(sb, reg1, val1);
402 snd_sbmixer_write(sb, reg2, val2);
403 }
404 spin_unlock_irqrestore(&sb->mixer_lock, flags);
405 return change;
406}
407
408
409/*
410 */
411/*
412 */
413int snd_sbmixer_add_ctl(sb_t *chip, const char *name, int index, int type, unsigned long value)
414{
415 static snd_kcontrol_new_t newctls[] = {
416 [SB_MIX_SINGLE] = {
417 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
418 .info = snd_sbmixer_info_single,
419 .get = snd_sbmixer_get_single,
420 .put = snd_sbmixer_put_single,
421 },
422 [SB_MIX_DOUBLE] = {
423 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
424 .info = snd_sbmixer_info_double,
425 .get = snd_sbmixer_get_double,
426 .put = snd_sbmixer_put_double,
427 },
428 [SB_MIX_INPUT_SW] = {
429 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
430 .info = snd_sb16mixer_info_input_sw,
431 .get = snd_sb16mixer_get_input_sw,
432 .put = snd_sb16mixer_put_input_sw,
433 },
434 [SB_MIX_CAPTURE_PRO] = {
435 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
436 .info = snd_sb8mixer_info_mux,
437 .get = snd_sb8mixer_get_mux,
438 .put = snd_sb8mixer_put_mux,
439 },
440 [SB_MIX_CAPTURE_DT019X] = {
441 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
442 .info = snd_dt019x_input_sw_info,
443 .get = snd_dt019x_input_sw_get,
444 .put = snd_dt019x_input_sw_put,
445 },
446 };
447 snd_kcontrol_t *ctl;
448 int err;
449
450 ctl = snd_ctl_new1(&newctls[type], chip);
451 if (! ctl)
452 return -ENOMEM;
453 strlcpy(ctl->id.name, name, sizeof(ctl->id.name));
454 ctl->id.index = index;
455 ctl->private_value = value;
456 if ((err = snd_ctl_add(chip->card, ctl)) < 0) {
457 snd_ctl_free_one(ctl);
458 return err;
459 }
460 return 0;
461}
462
463/*
464 * SB 2.0 specific mixer elements
465 */
466
467static struct sbmix_elem snd_sb20_ctl_master_play_vol =
468 SB_SINGLE("Master Playback Volume", SB_DSP20_MASTER_DEV, 1, 7);
469static struct sbmix_elem snd_sb20_ctl_pcm_play_vol =
470 SB_SINGLE("PCM Playback Volume", SB_DSP20_PCM_DEV, 1, 3);
471static struct sbmix_elem snd_sb20_ctl_synth_play_vol =
472 SB_SINGLE("Synth Playback Volume", SB_DSP20_FM_DEV, 1, 7);
473static struct sbmix_elem snd_sb20_ctl_cd_play_vol =
474 SB_SINGLE("CD Playback Volume", SB_DSP20_CD_DEV, 1, 7);
475
476static struct sbmix_elem *snd_sb20_controls[] = {
477 &snd_sb20_ctl_master_play_vol,
478 &snd_sb20_ctl_pcm_play_vol,
479 &snd_sb20_ctl_synth_play_vol,
480 &snd_sb20_ctl_cd_play_vol
481};
482
483static unsigned char snd_sb20_init_values[][2] = {
484 { SB_DSP20_MASTER_DEV, 0 },
485 { SB_DSP20_FM_DEV, 0 },
486};
487
488/*
489 * SB Pro specific mixer elements
490 */
491static struct sbmix_elem snd_sbpro_ctl_master_play_vol =
492 SB_DOUBLE("Master Playback Volume", SB_DSP_MASTER_DEV, SB_DSP_MASTER_DEV, 5, 1, 7);
493static struct sbmix_elem snd_sbpro_ctl_pcm_play_vol =
494 SB_DOUBLE("PCM Playback Volume", SB_DSP_PCM_DEV, SB_DSP_PCM_DEV, 5, 1, 7);
495static struct sbmix_elem snd_sbpro_ctl_pcm_play_filter =
496 SB_SINGLE("PCM Playback Filter", SB_DSP_PLAYBACK_FILT, 5, 1);
497static struct sbmix_elem snd_sbpro_ctl_synth_play_vol =
498 SB_DOUBLE("Synth Playback Volume", SB_DSP_FM_DEV, SB_DSP_FM_DEV, 5, 1, 7);
499static struct sbmix_elem snd_sbpro_ctl_cd_play_vol =
500 SB_DOUBLE("CD Playback Volume", SB_DSP_CD_DEV, SB_DSP_CD_DEV, 5, 1, 7);
501static struct sbmix_elem snd_sbpro_ctl_line_play_vol =
502 SB_DOUBLE("Line Playback Volume", SB_DSP_LINE_DEV, SB_DSP_LINE_DEV, 5, 1, 7);
503static struct sbmix_elem snd_sbpro_ctl_mic_play_vol =
504 SB_SINGLE("Mic Playback Volume", SB_DSP_MIC_DEV, 1, 3);
505static struct sbmix_elem snd_sbpro_ctl_capture_source =
506 {
507 .name = "Capture Source",
508 .type = SB_MIX_CAPTURE_PRO
509 };
510static struct sbmix_elem snd_sbpro_ctl_capture_filter =
511 SB_SINGLE("Capture Filter", SB_DSP_CAPTURE_FILT, 5, 1);
512static struct sbmix_elem snd_sbpro_ctl_capture_low_filter =
513 SB_SINGLE("Capture Low-Pass Filter", SB_DSP_CAPTURE_FILT, 3, 1);
514
515static struct sbmix_elem *snd_sbpro_controls[] = {
516 &snd_sbpro_ctl_master_play_vol,
517 &snd_sbpro_ctl_pcm_play_vol,
518 &snd_sbpro_ctl_pcm_play_filter,
519 &snd_sbpro_ctl_synth_play_vol,
520 &snd_sbpro_ctl_cd_play_vol,
521 &snd_sbpro_ctl_line_play_vol,
522 &snd_sbpro_ctl_mic_play_vol,
523 &snd_sbpro_ctl_capture_source,
524 &snd_sbpro_ctl_capture_filter,
525 &snd_sbpro_ctl_capture_low_filter
526};
527
528static unsigned char snd_sbpro_init_values[][2] = {
529 { SB_DSP_MASTER_DEV, 0 },
530 { SB_DSP_PCM_DEV, 0 },
531 { SB_DSP_FM_DEV, 0 },
532};
533
534/*
535 * SB16 specific mixer elements
536 */
537static struct sbmix_elem snd_sb16_ctl_master_play_vol =
538 SB_DOUBLE("Master Playback Volume", SB_DSP4_MASTER_DEV, (SB_DSP4_MASTER_DEV + 1), 3, 3, 31);
539static struct sbmix_elem snd_sb16_ctl_3d_enhance_switch =
540 SB_SINGLE("3D Enhancement Switch", SB_DSP4_3DSE, 0, 1);
541static struct sbmix_elem snd_sb16_ctl_tone_bass =
542 SB_DOUBLE("Tone Control - Bass", SB_DSP4_BASS_DEV, (SB_DSP4_BASS_DEV + 1), 4, 4, 15);
543static struct sbmix_elem snd_sb16_ctl_tone_treble =
544 SB_DOUBLE("Tone Control - Treble", SB_DSP4_TREBLE_DEV, (SB_DSP4_TREBLE_DEV + 1), 4, 4, 15);
545static struct sbmix_elem snd_sb16_ctl_pcm_play_vol =
546 SB_DOUBLE("PCM Playback Volume", SB_DSP4_PCM_DEV, (SB_DSP4_PCM_DEV + 1), 3, 3, 31);
547static struct sbmix_elem snd_sb16_ctl_synth_capture_route =
548 SB16_INPUT_SW("Synth Capture Route", SB_DSP4_INPUT_LEFT, SB_DSP4_INPUT_RIGHT, 6, 5);
549static struct sbmix_elem snd_sb16_ctl_synth_play_vol =
550 SB_DOUBLE("Synth Playback Volume", SB_DSP4_SYNTH_DEV, (SB_DSP4_SYNTH_DEV + 1), 3, 3, 31);
551static struct sbmix_elem snd_sb16_ctl_cd_capture_route =
552 SB16_INPUT_SW("CD Capture Route", SB_DSP4_INPUT_LEFT, SB_DSP4_INPUT_RIGHT, 2, 1);
553static struct sbmix_elem snd_sb16_ctl_cd_play_switch =
554 SB_DOUBLE("CD Playback Switch", SB_DSP4_OUTPUT_SW, SB_DSP4_OUTPUT_SW, 2, 1, 1);
555static struct sbmix_elem snd_sb16_ctl_cd_play_vol =
556 SB_DOUBLE("CD Playback Volume", SB_DSP4_CD_DEV, (SB_DSP4_CD_DEV + 1), 3, 3, 31);
557static struct sbmix_elem snd_sb16_ctl_line_capture_route =
558 SB16_INPUT_SW("Line Capture Route", SB_DSP4_INPUT_LEFT, SB_DSP4_INPUT_RIGHT, 4, 3);
559static struct sbmix_elem snd_sb16_ctl_line_play_switch =
560 SB_DOUBLE("Line Playback Switch", SB_DSP4_OUTPUT_SW, SB_DSP4_OUTPUT_SW, 4, 3, 1);
561static struct sbmix_elem snd_sb16_ctl_line_play_vol =
562 SB_DOUBLE("Line Playback Volume", SB_DSP4_LINE_DEV, (SB_DSP4_LINE_DEV + 1), 3, 3, 31);
563static struct sbmix_elem snd_sb16_ctl_mic_capture_route =
564 SB16_INPUT_SW("Mic Capture Route", SB_DSP4_INPUT_LEFT, SB_DSP4_INPUT_RIGHT, 0, 0);
565static struct sbmix_elem snd_sb16_ctl_mic_play_switch =
566 SB_SINGLE("Mic Playback Switch", SB_DSP4_OUTPUT_SW, 0, 1);
567static struct sbmix_elem snd_sb16_ctl_mic_play_vol =
568 SB_SINGLE("Mic Playback Volume", SB_DSP4_MIC_DEV, 3, 31);
569static struct sbmix_elem snd_sb16_ctl_pc_speaker_vol =
570 SB_SINGLE("PC Speaker Volume", SB_DSP4_SPEAKER_DEV, 6, 3);
571static struct sbmix_elem snd_sb16_ctl_capture_vol =
572 SB_DOUBLE("Capture Volume", SB_DSP4_IGAIN_DEV, (SB_DSP4_IGAIN_DEV + 1), 6, 6, 3);
573static struct sbmix_elem snd_sb16_ctl_play_vol =
574 SB_DOUBLE("Playback Volume", SB_DSP4_OGAIN_DEV, (SB_DSP4_OGAIN_DEV + 1), 6, 6, 3);
575static struct sbmix_elem snd_sb16_ctl_auto_mic_gain =
576 SB_SINGLE("Mic Auto Gain", SB_DSP4_MIC_AGC, 0, 1);
577
578static struct sbmix_elem *snd_sb16_controls[] = {
579 &snd_sb16_ctl_master_play_vol,
580 &snd_sb16_ctl_3d_enhance_switch,
581 &snd_sb16_ctl_tone_bass,
582 &snd_sb16_ctl_tone_treble,
583 &snd_sb16_ctl_pcm_play_vol,
584 &snd_sb16_ctl_synth_capture_route,
585 &snd_sb16_ctl_synth_play_vol,
586 &snd_sb16_ctl_cd_capture_route,
587 &snd_sb16_ctl_cd_play_switch,
588 &snd_sb16_ctl_cd_play_vol,
589 &snd_sb16_ctl_line_capture_route,
590 &snd_sb16_ctl_line_play_switch,
591 &snd_sb16_ctl_line_play_vol,
592 &snd_sb16_ctl_mic_capture_route,
593 &snd_sb16_ctl_mic_play_switch,
594 &snd_sb16_ctl_mic_play_vol,
595 &snd_sb16_ctl_pc_speaker_vol,
596 &snd_sb16_ctl_capture_vol,
597 &snd_sb16_ctl_play_vol,
598 &snd_sb16_ctl_auto_mic_gain
599};
600
601static unsigned char snd_sb16_init_values[][2] = {
602 { SB_DSP4_MASTER_DEV + 0, 0 },
603 { SB_DSP4_MASTER_DEV + 1, 0 },
604 { SB_DSP4_PCM_DEV + 0, 0 },
605 { SB_DSP4_PCM_DEV + 1, 0 },
606 { SB_DSP4_SYNTH_DEV + 0, 0 },
607 { SB_DSP4_SYNTH_DEV + 1, 0 },
608 { SB_DSP4_INPUT_LEFT, 0 },
609 { SB_DSP4_INPUT_RIGHT, 0 },
610 { SB_DSP4_OUTPUT_SW, 0 },
611 { SB_DSP4_SPEAKER_DEV, 0 },
612};
613
614/*
615 * DT019x specific mixer elements
616 */
617static struct sbmix_elem snd_dt019x_ctl_master_play_vol =
618 SB_DOUBLE("Master Playback Volume", SB_DT019X_MASTER_DEV, SB_DT019X_MASTER_DEV, 4,0, 15);
619static struct sbmix_elem snd_dt019x_ctl_pcm_play_vol =
620 SB_DOUBLE("PCM Playback Volume", SB_DT019X_PCM_DEV, SB_DT019X_PCM_DEV, 4,0, 15);
621static struct sbmix_elem snd_dt019x_ctl_synth_play_vol =
622 SB_DOUBLE("Synth Playback Volume", SB_DT019X_SYNTH_DEV, SB_DT019X_SYNTH_DEV, 4,0, 15);
623static struct sbmix_elem snd_dt019x_ctl_cd_play_vol =
624 SB_DOUBLE("CD Playback Volume", SB_DT019X_CD_DEV, SB_DT019X_CD_DEV, 4,0, 15);
625static struct sbmix_elem snd_dt019x_ctl_mic_play_vol =
626 SB_SINGLE("Mic Playback Volume", SB_DT019X_MIC_DEV, 4, 7);
627static struct sbmix_elem snd_dt019x_ctl_pc_speaker_vol =
628 SB_SINGLE("PC Speaker Volume", SB_DT019X_SPKR_DEV, 0, 7);
629static struct sbmix_elem snd_dt019x_ctl_line_play_vol =
630 SB_DOUBLE("Line Playback Volume", SB_DT019X_LINE_DEV, SB_DT019X_LINE_DEV, 4,0, 15);
631static struct sbmix_elem snd_dt019x_ctl_pcm_play_switch =
632 SB_DOUBLE("PCM Playback Switch", SB_DT019X_OUTPUT_SW2, SB_DT019X_OUTPUT_SW2, 2,1, 1);
633static struct sbmix_elem snd_dt019x_ctl_synth_play_switch =
634 SB_DOUBLE("Synth Playback Switch", SB_DT019X_OUTPUT_SW2, SB_DT019X_OUTPUT_SW2, 4,3, 1);
635static struct sbmix_elem snd_dt019x_ctl_capture_source =
636 {
637 .name = "Capture Source",
638 .type = SB_MIX_CAPTURE_DT019X
639 };
640
641static struct sbmix_elem *snd_dt019x_controls[] = {
642 &snd_dt019x_ctl_master_play_vol,
643 &snd_dt019x_ctl_pcm_play_vol,
644 &snd_dt019x_ctl_synth_play_vol,
645 &snd_dt019x_ctl_cd_play_vol,
646 &snd_dt019x_ctl_mic_play_vol,
647 &snd_dt019x_ctl_pc_speaker_vol,
648 &snd_dt019x_ctl_line_play_vol,
649 &snd_sb16_ctl_mic_play_switch,
650 &snd_sb16_ctl_cd_play_switch,
651 &snd_sb16_ctl_line_play_switch,
652 &snd_dt019x_ctl_pcm_play_switch,
653 &snd_dt019x_ctl_synth_play_switch,
654 &snd_dt019x_ctl_capture_source
655};
656
657static unsigned char snd_dt019x_init_values[][2] = {
658 { SB_DT019X_MASTER_DEV, 0 },
659 { SB_DT019X_PCM_DEV, 0 },
660 { SB_DT019X_SYNTH_DEV, 0 },
661 { SB_DT019X_CD_DEV, 0 },
662 { SB_DT019X_MIC_DEV, 0 }, /* Includes PC-speaker in high nibble */
663 { SB_DT019X_LINE_DEV, 0 },
664 { SB_DSP4_OUTPUT_SW, 0 },
665 { SB_DT019X_OUTPUT_SW2, 0 },
666 { SB_DT019X_CAPTURE_SW, 0x06 },
667};
668
669/*
670 * ALS4000 specific mixer elements
671 */
672/* FIXME: SB_ALS4000_MONO_IO_CTRL needs output select ctrl ! */
673static struct sbmix_elem snd_als4000_ctl_mono_output_switch =
674 SB_SINGLE("Mono Output Switch", SB_ALS4000_MONO_IO_CTRL, 5, 1);
675/* FIXME: mono input switch also available on DT019X ? */
676static struct sbmix_elem snd_als4000_ctl_mono_input_switch =
677 SB_SINGLE("Mono Input Switch", SB_DT019X_OUTPUT_SW2, 0, 1);
678static struct sbmix_elem snd_als4000_ctl_mic_20db_boost =
679 SB_SINGLE("Mic Boost (+20dB)", SB_ALS4000_MIC_IN_GAIN, 0, 0x03);
680static struct sbmix_elem snd_als4000_ctl_mixer_out_to_in =
681 SB_SINGLE("Mixer Out To In", SB_ALS4000_MIC_IN_GAIN, 7, 0x01);
682/* FIXME: 3D needs much more sophisticated controls, many more features ! */
683static struct sbmix_elem snd_als4000_ctl_3d_output_switch =
684 SB_SINGLE("3D Output Switch", SB_ALS4000_3D_SND_FX, 6, 0x01);
685static struct sbmix_elem snd_als4000_ctl_3d_output_ratio =
686 SB_SINGLE("3D Output Ratio", SB_ALS4000_3D_SND_FX, 0, 0x07);
687static struct sbmix_elem snd_als4000_ctl_3d_poweroff_switch =
688 SB_SINGLE("3D PowerOff Switch", SB_ALS4000_3D_TIME_DELAY, 4, 0x01);
689static struct sbmix_elem snd_als4000_ctl_3d_delay =
690 SB_SINGLE("3D Delay", SB_ALS4000_3D_TIME_DELAY, 0, 0x0f);
691#if NOT_AVAILABLE
692static struct sbmix_elem snd_als4000_ctl_fmdac =
693 SB_SINGLE("FMDAC Switch (Option ?)", SB_ALS4000_FMDAC, 0, 0x01);
694static struct sbmix_elem snd_als4000_ctl_qsound =
695 SB_SINGLE("QSound Mode", SB_ALS4000_QSOUND, 1, 0x1f);
696#endif
697
698static struct sbmix_elem *snd_als4000_controls[] = {
699 &snd_sb16_ctl_master_play_vol,
700 &snd_dt019x_ctl_pcm_play_switch,
701 &snd_sb16_ctl_pcm_play_vol,
702 &snd_sb16_ctl_synth_capture_route,
703 &snd_dt019x_ctl_synth_play_switch,
704 &snd_sb16_ctl_synth_play_vol,
705 &snd_sb16_ctl_cd_capture_route,
706 &snd_sb16_ctl_cd_play_switch,
707 &snd_sb16_ctl_cd_play_vol,
708 &snd_sb16_ctl_line_capture_route,
709 &snd_sb16_ctl_line_play_switch,
710 &snd_sb16_ctl_line_play_vol,
711 &snd_sb16_ctl_mic_capture_route,
712 &snd_als4000_ctl_mic_20db_boost,
713 &snd_sb16_ctl_auto_mic_gain,
714 &snd_sb16_ctl_mic_play_switch,
715 &snd_sb16_ctl_mic_play_vol,
716 &snd_sb16_ctl_pc_speaker_vol,
717 &snd_sb16_ctl_capture_vol,
718 &snd_sb16_ctl_play_vol,
719 &snd_als4000_ctl_mono_output_switch,
720 &snd_als4000_ctl_mono_input_switch,
721 &snd_als4000_ctl_mixer_out_to_in,
722 &snd_als4000_ctl_3d_output_switch,
723 &snd_als4000_ctl_3d_output_ratio,
724 &snd_als4000_ctl_3d_delay,
725 &snd_als4000_ctl_3d_poweroff_switch,
726#if NOT_AVAILABLE
727 &snd_als4000_ctl_fmdac,
728 &snd_als4000_ctl_qsound,
729#endif
730};
731
732static unsigned char snd_als4000_init_values[][2] = {
733 { SB_DSP4_MASTER_DEV + 0, 0 },
734 { SB_DSP4_MASTER_DEV + 1, 0 },
735 { SB_DSP4_PCM_DEV + 0, 0 },
736 { SB_DSP4_PCM_DEV + 1, 0 },
737 { SB_DSP4_SYNTH_DEV + 0, 0 },
738 { SB_DSP4_SYNTH_DEV + 1, 0 },
739 { SB_DSP4_SPEAKER_DEV, 0 },
740 { SB_DSP4_OUTPUT_SW, 0 },
741 { SB_DSP4_INPUT_LEFT, 0 },
742 { SB_DSP4_INPUT_RIGHT, 0 },
743 { SB_DT019X_OUTPUT_SW2, 0 },
744 { SB_ALS4000_MIC_IN_GAIN, 0 },
745};
746
747
748/*
749 */
750static int snd_sbmixer_init(sb_t *chip,
751 struct sbmix_elem **controls,
752 int controls_count,
753 unsigned char map[][2],
754 int map_count,
755 char *name)
756{
757 unsigned long flags;
758 snd_card_t *card = chip->card;
759 int idx, err;
760
761 /* mixer reset */
762 spin_lock_irqsave(&chip->mixer_lock, flags);
763 snd_sbmixer_write(chip, 0x00, 0x00);
764 spin_unlock_irqrestore(&chip->mixer_lock, flags);
765
766 /* mute and zero volume channels */
767 for (idx = 0; idx < map_count; idx++) {
768 spin_lock_irqsave(&chip->mixer_lock, flags);
769 snd_sbmixer_write(chip, map[idx][0], map[idx][1]);
770 spin_unlock_irqrestore(&chip->mixer_lock, flags);
771 }
772
773 for (idx = 0; idx < controls_count; idx++) {
774 if ((err = snd_sbmixer_add_ctl_elem(chip, controls[idx])) < 0)
775 return err;
776 }
777 snd_component_add(card, name);
778 strcpy(card->mixername, name);
779 return 0;
780}
781
782int snd_sbmixer_new(sb_t *chip)
783{
784 snd_card_t * card;
785 int err;
786
787 snd_assert(chip != NULL && chip->card != NULL, return -EINVAL);
788
789 card = chip->card;
790
791 switch (chip->hardware) {
792 case SB_HW_10:
793 return 0; /* no mixer chip on SB1.x */
794 case SB_HW_20:
795 case SB_HW_201:
796 if ((err = snd_sbmixer_init(chip,
797 snd_sb20_controls,
798 ARRAY_SIZE(snd_sb20_controls),
799 snd_sb20_init_values,
800 ARRAY_SIZE(snd_sb20_init_values),
801 "CTL1335")) < 0)
802 return err;
803 break;
804 case SB_HW_PRO:
805 if ((err = snd_sbmixer_init(chip,
806 snd_sbpro_controls,
807 ARRAY_SIZE(snd_sbpro_controls),
808 snd_sbpro_init_values,
809 ARRAY_SIZE(snd_sbpro_init_values),
810 "CTL1345")) < 0)
811 return err;
812 break;
813 case SB_HW_16:
814 case SB_HW_ALS100:
815 if ((err = snd_sbmixer_init(chip,
816 snd_sb16_controls,
817 ARRAY_SIZE(snd_sb16_controls),
818 snd_sb16_init_values,
819 ARRAY_SIZE(snd_sb16_init_values),
820 "CTL1745")) < 0)
821 return err;
822 break;
823 case SB_HW_ALS4000:
824 if ((err = snd_sbmixer_init(chip,
825 snd_als4000_controls,
826 ARRAY_SIZE(snd_als4000_controls),
827 snd_als4000_init_values,
828 ARRAY_SIZE(snd_als4000_init_values),
829 "ALS4000")) < 0)
830 return err;
831 break;
832 case SB_HW_DT019X:
833 if ((err = snd_sbmixer_init(chip,
834 snd_dt019x_controls,
835 ARRAY_SIZE(snd_dt019x_controls),
836 snd_dt019x_init_values,
837 ARRAY_SIZE(snd_dt019x_init_values),
838 "DT019X")) < 0)
839 break;
840 default:
841 strcpy(card->mixername, "???");
842 }
843 return 0;
844}
diff --git a/sound/isa/sb/sbawe.c b/sound/isa/sb/sbawe.c
new file mode 100644
index 000000000000..2ec52a3473a2
--- /dev/null
+++ b/sound/isa/sb/sbawe.c
@@ -0,0 +1,2 @@
1#define SNDRV_SBAWE
2#include "sb16.c"
diff --git a/sound/isa/sgalaxy.c b/sound/isa/sgalaxy.c
new file mode 100644
index 000000000000..17f585b0ddc1
--- /dev/null
+++ b/sound/isa/sgalaxy.c
@@ -0,0 +1,322 @@
1/*
2 * Driver for Aztech Sound Galaxy cards
3 * Copyright (c) by Christopher Butler <chrisb@sandy.force9.co.uk.
4 *
5 * I don't have documentation for this card, I based this driver on the
6 * driver for OSS/Free included in the kernel source (drivers/sound/sgalaxy.c)
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21 *
22 */
23
24#include <sound/driver.h>
25#include <asm/dma.h>
26#include <linux/init.h>
27#include <linux/delay.h>
28#include <linux/time.h>
29#include <linux/interrupt.h>
30#include <linux/moduleparam.h>
31#include <sound/core.h>
32#include <sound/sb.h>
33#include <sound/ad1848.h>
34#include <sound/control.h>
35#define SNDRV_LEGACY_FIND_FREE_IRQ
36#define SNDRV_LEGACY_FIND_FREE_DMA
37#include <sound/initval.h>
38
39MODULE_AUTHOR("Christopher Butler <chrisb@sandy.force9.co.uk>");
40MODULE_DESCRIPTION("Aztech Sound Galaxy");
41MODULE_LICENSE("GPL");
42MODULE_SUPPORTED_DEVICE("{{Aztech Systems,Sound Galaxy}}");
43
44static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-MAX */
45static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* ID for this card */
46static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE; /* Enable this card */
47static long sbport[SNDRV_CARDS] = SNDRV_DEFAULT_PORT; /* 0x220,0x240 */
48static long wssport[SNDRV_CARDS] = SNDRV_DEFAULT_PORT; /* 0x530,0xe80,0xf40,0x604 */
49static int irq[SNDRV_CARDS] = SNDRV_DEFAULT_IRQ; /* 7,9,10,11 */
50static int dma1[SNDRV_CARDS] = SNDRV_DEFAULT_DMA; /* 0,1,3 */
51
52module_param_array(index, int, NULL, 0444);
53MODULE_PARM_DESC(index, "Index value for Sound Galaxy soundcard.");
54module_param_array(id, charp, NULL, 0444);
55MODULE_PARM_DESC(id, "ID string for Sound Galaxy soundcard.");
56module_param_array(sbport, long, NULL, 0444);
57MODULE_PARM_DESC(sbport, "Port # for Sound Galaxy SB driver.");
58module_param_array(wssport, long, NULL, 0444);
59MODULE_PARM_DESC(wssport, "Port # for Sound Galaxy WSS driver.");
60module_param_array(irq, int, NULL, 0444);
61MODULE_PARM_DESC(irq, "IRQ # for Sound Galaxy driver.");
62module_param_array(dma1, int, NULL, 0444);
63MODULE_PARM_DESC(dma1, "DMA1 # for Sound Galaxy driver.");
64
65#define SGALAXY_AUXC_LEFT 18
66#define SGALAXY_AUXC_RIGHT 19
67
68static snd_card_t *snd_sgalaxy_cards[SNDRV_CARDS] = SNDRV_DEFAULT_PTR;
69
70/*
71
72 */
73
74#define AD1848P1( port, x ) ( port + c_d_c_AD1848##x )
75
76/* from lowlevel/sb/sb.c - to avoid having to allocate a sb_t for the */
77/* short time we actually need it.. */
78
79static int snd_sgalaxy_sbdsp_reset(unsigned long port)
80{
81 int i;
82
83 outb(1, SBP1(port, RESET));
84 udelay(10);
85 outb(0, SBP1(port, RESET));
86 udelay(30);
87 for (i = 0; i < 1000 && !(inb(SBP1(port, DATA_AVAIL)) & 0x80); i++);
88 if (inb(SBP1(port, READ)) != 0xaa) {
89 snd_printd("sb_reset: failed at 0x%lx!!!\n", port);
90 return -ENODEV;
91 }
92 return 0;
93}
94
95static int __init snd_sgalaxy_sbdsp_command(unsigned long port, unsigned char val)
96{
97 int i;
98
99 for (i = 10000; i; i--)
100 if ((inb(SBP1(port, STATUS)) & 0x80) == 0) {
101 outb(val, SBP1(port, COMMAND));
102 return 1;
103 }
104
105 return 0;
106}
107
108static irqreturn_t snd_sgalaxy_dummy_interrupt(int irq, void *dev_id, struct pt_regs *regs)
109{
110 return IRQ_NONE;
111}
112
113static int __init snd_sgalaxy_setup_wss(unsigned long port, int irq, int dma)
114{
115 static int interrupt_bits[] = {-1, -1, -1, -1, -1, -1, -1, 0x08, -1,
116 0x10, 0x18, 0x20, -1, -1, -1, -1};
117 static int dma_bits[] = {1, 2, 0, 3};
118 int tmp, tmp1;
119
120 if ((tmp = inb(port + 3)) == 0xff)
121 {
122 snd_printdd("I/O address dead (0x%lx)\n", port);
123 return 0;
124 }
125#if 0
126 snd_printdd("WSS signature = 0x%x\n", tmp);
127#endif
128
129 if ((tmp & 0x3f) != 0x04 &&
130 (tmp & 0x3f) != 0x0f &&
131 (tmp & 0x3f) != 0x00) {
132 snd_printdd("No WSS signature detected on port 0x%lx\n",
133 port + 3);
134 return 0;
135 }
136
137#if 0
138 snd_printdd("sgalaxy - setting up IRQ/DMA for WSS\n");
139#endif
140
141 /* initialize IRQ for WSS codec */
142 tmp = interrupt_bits[irq % 16];
143 if (tmp < 0)
144 return -EINVAL;
145
146 if (request_irq(irq, snd_sgalaxy_dummy_interrupt, SA_INTERRUPT, "sgalaxy", NULL)) {
147 snd_printk(KERN_ERR "sgalaxy: can't grab irq %d\n", irq);
148 return -EIO;
149 }
150
151 outb(tmp | 0x40, port);
152 tmp1 = dma_bits[dma % 4];
153 outb(tmp | tmp1, port);
154
155 free_irq(irq, NULL);
156
157 return 0;
158}
159
160static int __init snd_sgalaxy_detect(int dev, int irq, int dma)
161{
162#if 0
163 snd_printdd("sgalaxy - switching to WSS mode\n");
164#endif
165
166 /* switch to WSS mode */
167 snd_sgalaxy_sbdsp_reset(sbport[dev]);
168
169 snd_sgalaxy_sbdsp_command(sbport[dev], 9);
170 snd_sgalaxy_sbdsp_command(sbport[dev], 0);
171
172 udelay(400);
173 return snd_sgalaxy_setup_wss(wssport[dev], irq, dma);
174}
175
176static struct ad1848_mix_elem snd_sgalaxy_controls[] = {
177AD1848_DOUBLE("Aux Playback Switch", 0, SGALAXY_AUXC_LEFT, SGALAXY_AUXC_RIGHT, 7, 7, 1, 1),
178AD1848_DOUBLE("Aux Playback Volume", 0, SGALAXY_AUXC_LEFT, SGALAXY_AUXC_RIGHT, 0, 0, 31, 0)
179};
180
181static int __init snd_sgalaxy_mixer(ad1848_t *chip)
182{
183 snd_card_t *card = chip->card;
184 snd_ctl_elem_id_t id1, id2;
185 unsigned int idx;
186 int err;
187
188 memset(&id1, 0, sizeof(id1));
189 memset(&id2, 0, sizeof(id2));
190 id1.iface = id2.iface = SNDRV_CTL_ELEM_IFACE_MIXER;
191 /* reassign AUX0 to LINE */
192 strcpy(id1.name, "Aux Playback Switch");
193 strcpy(id2.name, "Line Playback Switch");
194 if ((err = snd_ctl_rename_id(card, &id1, &id2)) < 0)
195 return err;
196 strcpy(id1.name, "Aux Playback Volume");
197 strcpy(id2.name, "Line Playback Volume");
198 if ((err = snd_ctl_rename_id(card, &id1, &id2)) < 0)
199 return err;
200 /* reassign AUX1 to FM */
201 strcpy(id1.name, "Aux Playback Switch"); id1.index = 1;
202 strcpy(id2.name, "FM Playback Switch");
203 if ((err = snd_ctl_rename_id(card, &id1, &id2)) < 0)
204 return err;
205 strcpy(id1.name, "Aux Playback Volume");
206 strcpy(id2.name, "FM Playback Volume");
207 if ((err = snd_ctl_rename_id(card, &id1, &id2)) < 0)
208 return err;
209 /* build AUX2 input */
210 for (idx = 0; idx < ARRAY_SIZE(snd_sgalaxy_controls); idx++) {
211 if ((err = snd_ad1848_add_ctl_elem(chip, &snd_sgalaxy_controls[idx])) < 0)
212 return err;
213 }
214 return 0;
215}
216
217static int __init snd_sgalaxy_probe(int dev)
218{
219 static int possible_irqs[] = {7, 9, 10, 11, -1};
220 static int possible_dmas[] = {1, 3, 0, -1};
221 int err, xirq, xdma1;
222 snd_card_t *card;
223 ad1848_t *chip;
224
225 if (sbport[dev] == SNDRV_AUTO_PORT) {
226 snd_printk("specify SB port\n");
227 return -EINVAL;
228 }
229 if (wssport[dev] == SNDRV_AUTO_PORT) {
230 snd_printk("specify WSS port\n");
231 return -EINVAL;
232 }
233 card = snd_card_new(index[dev], id[dev], THIS_MODULE, 0);
234 if (card == NULL)
235 return -ENOMEM;
236
237 xirq = irq[dev];
238 if (xirq == SNDRV_AUTO_IRQ) {
239 if ((xirq = snd_legacy_find_free_irq(possible_irqs)) < 0) {
240 snd_card_free(card);
241 snd_printk("unable to find a free IRQ\n");
242 return -EBUSY;
243 }
244 }
245 xdma1 = dma1[dev];
246 if (xdma1 == SNDRV_AUTO_DMA) {
247 if ((xdma1 = snd_legacy_find_free_dma(possible_dmas)) < 0) {
248 snd_card_free(card);
249 snd_printk("unable to find a free DMA\n");
250 return -EBUSY;
251 }
252 }
253
254 if ((err = snd_sgalaxy_detect(dev, xirq, xdma1)) < 0) {
255 snd_card_free(card);
256 return err;
257 }
258
259 if ((err = snd_ad1848_create(card, wssport[dev] + 4,
260 xirq, xdma1,
261 AD1848_HW_DETECT, &chip)) < 0) {
262 snd_card_free(card);
263 return err;
264 }
265
266 if ((err = snd_ad1848_pcm(chip, 0, NULL)) < 0) {
267 snd_printdd("sgalaxy - error creating new ad1848 PCM device\n");
268 snd_card_free(card);
269 return err;
270 }
271 if ((err = snd_ad1848_mixer(chip)) < 0) {
272 snd_printdd("sgalaxy - error creating new ad1848 mixer\n");
273 snd_card_free(card);
274 return err;
275 }
276 if (snd_sgalaxy_mixer(chip) < 0) {
277 snd_printdd("sgalaxy - the mixer rewrite failed\n");
278 snd_card_free(card);
279 return err;
280 }
281
282 strcpy(card->driver, "Sound Galaxy");
283 strcpy(card->shortname, "Sound Galaxy");
284 sprintf(card->longname, "Sound Galaxy at 0x%lx, irq %d, dma %d",
285 wssport[dev], xirq, xdma1);
286
287 if ((err = snd_card_register(card)) < 0) {
288 snd_card_free(card);
289 return err;
290 }
291 snd_sgalaxy_cards[dev] = card;
292 return 0;
293}
294
295static int __init alsa_card_sgalaxy_init(void)
296{
297 int dev, cards;
298
299 for (dev = cards = 0; dev < SNDRV_CARDS && enable[dev]; dev++) {
300 if (snd_sgalaxy_probe(dev) >= 0)
301 cards++;
302 }
303 if (!cards) {
304#ifdef MODULE
305 snd_printk(KERN_ERR "Sound Galaxy soundcard not found or device busy\n");
306#endif
307 return -ENODEV;
308 }
309
310 return 0;
311}
312
313static void __exit alsa_card_sgalaxy_exit(void)
314{
315 int idx;
316
317 for (idx = 0; idx < SNDRV_CARDS; idx++)
318 snd_card_free(snd_sgalaxy_cards[idx]);
319}
320
321module_init(alsa_card_sgalaxy_init)
322module_exit(alsa_card_sgalaxy_exit)
diff --git a/sound/isa/sscape.c b/sound/isa/sscape.c
new file mode 100644
index 000000000000..3959ed694eec
--- /dev/null
+++ b/sound/isa/sscape.c
@@ -0,0 +1,1517 @@
1/*
2 * Low-level ALSA driver for the ENSONIQ SoundScape PnP
3 * Copyright (c) by Chris Rankin
4 *
5 * This driver was written in part using information obtained from
6 * the OSS/Free SoundScape driver, written by Hannu Savolainen.
7 *
8 *
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
13 *
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22 */
23
24#include <sound/driver.h>
25#include <linux/init.h>
26#include <linux/delay.h>
27#include <linux/pnp.h>
28#include <linux/spinlock.h>
29#include <linux/moduleparam.h>
30#include <asm/dma.h>
31#include <sound/core.h>
32#include <sound/hwdep.h>
33#include <sound/cs4231.h>
34#include <sound/mpu401.h>
35#include <sound/initval.h>
36
37#include <sound/sscape_ioctl.h>
38
39
40MODULE_AUTHOR("Chris Rankin");
41MODULE_DESCRIPTION("ENSONIQ SoundScape PnP driver");
42MODULE_LICENSE("GPL");
43
44static int index[SNDRV_CARDS] __devinitdata = SNDRV_DEFAULT_IDX;
45static char* id[SNDRV_CARDS] __devinitdata = SNDRV_DEFAULT_STR;
46static long port[SNDRV_CARDS] __devinitdata = { [0 ... (SNDRV_CARDS-1)] = SNDRV_AUTO_PORT };
47static int irq[SNDRV_CARDS] __devinitdata = SNDRV_DEFAULT_IRQ;
48static int mpu_irq[SNDRV_CARDS] __devinitdata = SNDRV_DEFAULT_IRQ;
49static int dma[SNDRV_CARDS] __devinitdata = SNDRV_DEFAULT_DMA;
50
51module_param_array(index, int, NULL, 0444);
52MODULE_PARM_DESC(index, "Index number for SoundScape soundcard");
53
54module_param_array(id, charp, NULL, 0444);
55MODULE_PARM_DESC(id, "Description for SoundScape card");
56
57module_param_array(port, long, NULL, 0444);
58MODULE_PARM_DESC(port, "Port # for SoundScape driver.");
59
60module_param_array(irq, int, NULL, 0444);
61MODULE_PARM_DESC(irq, "IRQ # for SoundScape driver.");
62
63module_param_array(mpu_irq, int, NULL, 0444);
64MODULE_PARM_DESC(mpu_irq, "MPU401 IRQ # for SoundScape driver.");
65
66module_param_array(dma, int, NULL, 0444);
67MODULE_PARM_DESC(dma, "DMA # for SoundScape driver.");
68
69#ifdef CONFIG_PNP
70static struct pnp_card_device_id sscape_pnpids[] = {
71 { .id = "ENS3081", .devs = { { "ENS0000" } } },
72 { .id = "" } /* end */
73};
74
75MODULE_DEVICE_TABLE(pnp_card, sscape_pnpids);
76#endif
77
78static snd_card_t *sscape_card[SNDRV_CARDS];
79
80
81#define MPU401_IO(i) ((i) + 0)
82#define MIDI_DATA_IO(i) ((i) + 0)
83#define MIDI_CTRL_IO(i) ((i) + 1)
84#define HOST_CTRL_IO(i) ((i) + 2)
85#define HOST_DATA_IO(i) ((i) + 3)
86#define ODIE_ADDR_IO(i) ((i) + 4)
87#define ODIE_DATA_IO(i) ((i) + 5)
88#define CODEC_IO(i) ((i) + 8)
89
90#define IC_ODIE 1
91#define IC_OPUS 2
92
93#define RX_READY 0x01
94#define TX_READY 0x02
95
96#define CMD_ACK 0x80
97#define CMD_SET_MIDI_VOL 0x84
98#define CMD_GET_MIDI_VOL 0x85
99#define CMD_XXX_MIDI_VOL 0x86
100#define CMD_SET_EXTMIDI 0x8a
101#define CMD_GET_EXTMIDI 0x8b
102#define CMD_SET_MT32 0x8c
103#define CMD_GET_MT32 0x8d
104
105enum GA_REG {
106 GA_INTSTAT_REG = 0,
107 GA_INTENA_REG,
108 GA_DMAA_REG,
109 GA_DMAB_REG,
110 GA_INTCFG_REG,
111 GA_DMACFG_REG,
112 GA_CDCFG_REG,
113 GA_SMCFGA_REG,
114 GA_SMCFGB_REG,
115 GA_HMCTL_REG
116};
117
118#define DMA_8BIT 0x80
119
120
121#define AD1845_FREQ_SEL_MSB 0x16
122#define AD1845_FREQ_SEL_LSB 0x17
123
124struct soundscape {
125 spinlock_t lock;
126 unsigned io_base;
127 int codec_type;
128 int ic_type;
129 struct resource *io_res;
130 cs4231_t *chip;
131 mpu401_t *mpu;
132 snd_hwdep_t *hw;
133
134 /*
135 * The MIDI device won't work until we've loaded
136 * its firmware via a hardware-dependent device IOCTL
137 */
138 spinlock_t fwlock;
139 int hw_in_use;
140 unsigned long midi_usage;
141 unsigned char midi_vol;
142};
143
144#define INVALID_IRQ ((unsigned)-1)
145
146
147static inline struct soundscape *get_card_soundscape(snd_card_t * c)
148{
149 return (struct soundscape *) (c->private_data);
150}
151
152static inline struct soundscape *get_mpu401_soundscape(mpu401_t * mpu)
153{
154 return (struct soundscape *) (mpu->private_data);
155}
156
157static inline struct soundscape *get_hwdep_soundscape(snd_hwdep_t * hw)
158{
159 return (struct soundscape *) (hw->private_data);
160}
161
162
163/*
164 * Allocates some kernel memory that we can use for DMA.
165 * I think this means that the memory has to map to
166 * contiguous pages of physical memory.
167 */
168static struct snd_dma_buffer *get_dmabuf(struct snd_dma_buffer *buf, unsigned long size)
169{
170 if (buf) {
171 if (snd_dma_alloc_pages_fallback(SNDRV_DMA_TYPE_DEV, snd_dma_isa_data(),
172 size, buf) < 0) {
173 snd_printk(KERN_ERR "sscape: Failed to allocate %lu bytes for DMA\n", size);
174 return NULL;
175 }
176 }
177
178 return buf;
179}
180
181/*
182 * Release the DMA-able kernel memory ...
183 */
184static void free_dmabuf(struct snd_dma_buffer *buf)
185{
186 if (buf && buf->area)
187 snd_dma_free_pages(buf);
188}
189
190
191/*
192 * This function writes to the SoundScape's control registers,
193 * but doesn't do any locking. It's up to the caller to do that.
194 * This is why this function is "unsafe" ...
195 */
196static inline void sscape_write_unsafe(unsigned io_base, enum GA_REG reg, unsigned char val)
197{
198 outb(reg, ODIE_ADDR_IO(io_base));
199 outb(val, ODIE_DATA_IO(io_base));
200}
201
202/*
203 * Write to the SoundScape's control registers, and do the
204 * necessary locking ...
205 */
206static void sscape_write(struct soundscape *s, enum GA_REG reg, unsigned char val)
207{
208 unsigned long flags;
209
210 spin_lock_irqsave(&s->lock, flags);
211 sscape_write_unsafe(s->io_base, reg, val);
212 spin_unlock_irqrestore(&s->lock, flags);
213}
214
215/*
216 * Read from the SoundScape's control registers, but leave any
217 * locking to the caller. This is why the function is "unsafe" ...
218 */
219static inline unsigned char sscape_read_unsafe(unsigned io_base, enum GA_REG reg)
220{
221 outb(reg, ODIE_ADDR_IO(io_base));
222 return inb(ODIE_DATA_IO(io_base));
223}
224
225/*
226 * Puts the SoundScape into "host" mode, as compared to "MIDI" mode
227 */
228static inline void set_host_mode_unsafe(unsigned io_base)
229{
230 outb(0x0, HOST_CTRL_IO(io_base));
231}
232
233/*
234 * Puts the SoundScape into "MIDI" mode, as compared to "host" mode
235 */
236static inline void set_midi_mode_unsafe(unsigned io_base)
237{
238 outb(0x3, HOST_CTRL_IO(io_base));
239}
240
241/*
242 * Read the SoundScape's host-mode control register, but leave
243 * any locking issues to the caller ...
244 */
245static inline int host_read_unsafe(unsigned io_base)
246{
247 int data = -1;
248 if ((inb(HOST_CTRL_IO(io_base)) & RX_READY) != 0) {
249 data = inb(HOST_DATA_IO(io_base));
250 }
251
252 return data;
253}
254
255/*
256 * Read the SoundScape's host-mode control register, performing
257 * a limited amount of busy-waiting if the register isn't ready.
258 * Also leaves all locking-issues to the caller ...
259 */
260static int host_read_ctrl_unsafe(unsigned io_base, unsigned timeout)
261{
262 int data;
263
264 while (((data = host_read_unsafe(io_base)) < 0) && (timeout != 0)) {
265 udelay(100);
266 --timeout;
267 } /* while */
268
269 return data;
270}
271
272/*
273 * Write to the SoundScape's host-mode control registers, but
274 * leave any locking issues to the caller ...
275 */
276static inline int host_write_unsafe(unsigned io_base, unsigned char data)
277{
278 if ((inb(HOST_CTRL_IO(io_base)) & TX_READY) != 0) {
279 outb(data, HOST_DATA_IO(io_base));
280 return 1;
281 }
282
283 return 0;
284}
285
286/*
287 * Write to the SoundScape's host-mode control registers, performing
288 * a limited amount of busy-waiting if the register isn't ready.
289 * Also leaves all locking-issues to the caller ...
290 */
291static int host_write_ctrl_unsafe(unsigned io_base, unsigned char data,
292 unsigned timeout)
293{
294 int err;
295
296 while (!(err = host_write_unsafe(io_base, data)) && (timeout != 0)) {
297 udelay(100);
298 --timeout;
299 } /* while */
300
301 return err;
302}
303
304
305/*
306 * Check that the MIDI subsystem is operational. If it isn't,
307 * then we will hang the computer if we try to use it ...
308 *
309 * NOTE: This check is based upon observation, not documentation.
310 */
311static inline int verify_mpu401(const mpu401_t * mpu)
312{
313 return ((inb(MIDI_CTRL_IO(mpu->port)) & 0xc0) == 0x80);
314}
315
316/*
317 * This is apparently the standard way to initailise an MPU-401
318 */
319static inline void initialise_mpu401(const mpu401_t * mpu)
320{
321 outb(0, MIDI_DATA_IO(mpu->port));
322}
323
324/*
325 * Tell the SoundScape to activate the AD1845 chip (I think).
326 * The AD1845 detection fails if we *don't* do this, so I
327 * think that this is a good idea ...
328 */
329static inline void activate_ad1845_unsafe(unsigned io_base)
330{
331 sscape_write_unsafe(io_base, GA_HMCTL_REG, (sscape_read_unsafe(io_base, GA_HMCTL_REG) & 0xcf) | 0x10);
332 sscape_write_unsafe(io_base, GA_CDCFG_REG, 0x80);
333}
334
335/*
336 * Do the necessary ALSA-level cleanup to deallocate our driver ...
337 */
338static void soundscape_free(snd_card_t * c)
339{
340 register struct soundscape *sscape = get_card_soundscape(c);
341 release_resource(sscape->io_res);
342 kfree_nocheck(sscape->io_res);
343 free_dma(sscape->chip->dma1);
344}
345
346/*
347 * Put this process into an idle wait-state for a certain number
348 * of "jiffies". The process can almost certainly be rescheduled
349 * while we're waiting, and so we must NOT be holding any spinlocks
350 * when we call this function. If we are then we risk DEADLOCK in
351 * SMP (Ha!) or pre-emptible kernels.
352 */
353static inline void sleep(long jiffs, int state)
354{
355 set_current_state(state);
356 schedule_timeout(jiffs);
357}
358
359/*
360 * Tell the SoundScape to begin a DMA tranfer using the given channel.
361 * All locking issues are left to the caller.
362 */
363static inline void sscape_start_dma_unsafe(unsigned io_base, enum GA_REG reg)
364{
365 sscape_write_unsafe(io_base, reg, sscape_read_unsafe(io_base, reg) | 0x01);
366 sscape_write_unsafe(io_base, reg, sscape_read_unsafe(io_base, reg) & 0xfe);
367}
368
369/*
370 * Wait for a DMA transfer to complete. This is a "limited busy-wait",
371 * and all locking issues are left to the caller.
372 */
373static int sscape_wait_dma_unsafe(unsigned io_base, enum GA_REG reg, unsigned timeout)
374{
375 while (!(sscape_read_unsafe(io_base, reg) & 0x01) && (timeout != 0)) {
376 udelay(100);
377 --timeout;
378 } /* while */
379
380 return (sscape_read_unsafe(io_base, reg) & 0x01);
381}
382
383/*
384 * Wait for the On-Board Processor to return its start-up
385 * acknowledgement sequence. This wait is too long for
386 * us to perform "busy-waiting", and so we must sleep.
387 * This in turn means that we must not be holding any
388 * spinlocks when we call this function.
389 */
390static int obp_startup_ack(struct soundscape *s, unsigned timeout)
391{
392 while (timeout != 0) {
393 unsigned long flags;
394 unsigned char x;
395
396 sleep(1, TASK_INTERRUPTIBLE);
397
398 spin_lock_irqsave(&s->lock, flags);
399 x = inb(HOST_DATA_IO(s->io_base));
400 spin_unlock_irqrestore(&s->lock, flags);
401 if ((x & 0xfe) == 0xfe)
402 return 1;
403
404 --timeout;
405 } /* while */
406
407 return 0;
408}
409
410/*
411 * Wait for the host to return its start-up acknowledgement
412 * sequence. This wait is too long for us to perform
413 * "busy-waiting", and so we must sleep. This in turn means
414 * that we must not be holding any spinlocks when we call
415 * this function.
416 */
417static int host_startup_ack(struct soundscape *s, unsigned timeout)
418{
419 while (timeout != 0) {
420 unsigned long flags;
421 unsigned char x;
422
423 sleep(1, TASK_INTERRUPTIBLE);
424
425 spin_lock_irqsave(&s->lock, flags);
426 x = inb(HOST_DATA_IO(s->io_base));
427 spin_unlock_irqrestore(&s->lock, flags);
428 if (x == 0xfe)
429 return 1;
430
431 --timeout;
432 } /* while */
433
434 return 0;
435}
436
437/*
438 * Upload a byte-stream into the SoundScape using DMA channel A.
439 */
440static int upload_dma_data(struct soundscape *s,
441 const unsigned char __user *data,
442 size_t size)
443{
444 unsigned long flags;
445 struct snd_dma_buffer dma;
446 int ret;
447
448 if (!get_dmabuf(&dma, PAGE_ALIGN(size)))
449 return -ENOMEM;
450
451 spin_lock_irqsave(&s->lock, flags);
452
453 /*
454 * Reset the board ...
455 */
456 sscape_write_unsafe(s->io_base, GA_HMCTL_REG, sscape_read_unsafe(s->io_base, GA_HMCTL_REG) & 0x3f);
457
458 /*
459 * Enable the DMA channels and configure them ...
460 */
461 sscape_write_unsafe(s->io_base, GA_DMACFG_REG, 0x50);
462 sscape_write_unsafe(s->io_base, GA_DMAA_REG, (s->chip->dma1 << 4) | DMA_8BIT);
463 sscape_write_unsafe(s->io_base, GA_DMAB_REG, 0x20);
464
465 /*
466 * Take the board out of reset ...
467 */
468 sscape_write_unsafe(s->io_base, GA_HMCTL_REG, sscape_read_unsafe(s->io_base, GA_HMCTL_REG) | 0x80);
469
470 /*
471 * Upload the user's data (firmware?) to the SoundScape
472 * board through the DMA channel ...
473 */
474 while (size != 0) {
475 unsigned long len;
476
477 /*
478 * Apparently, copying to/from userspace can sleep.
479 * We are therefore forbidden from holding any
480 * spinlocks while we copy ...
481 */
482 spin_unlock_irqrestore(&s->lock, flags);
483
484 /*
485 * Remember that the data that we want to DMA
486 * comes from USERSPACE. We have already verified
487 * the userspace pointer ...
488 */
489 len = min(size, dma.bytes);
490 len -= __copy_from_user(dma.area, data, len);
491 data += len;
492 size -= len;
493
494 /*
495 * Grab that spinlock again, now that we've
496 * finished copying!
497 */
498 spin_lock_irqsave(&s->lock, flags);
499
500 snd_dma_program(s->chip->dma1, dma.addr, len, DMA_MODE_WRITE);
501 sscape_start_dma_unsafe(s->io_base, GA_DMAA_REG);
502 if (!sscape_wait_dma_unsafe(s->io_base, GA_DMAA_REG, 5000)) {
503 /*
504 * Don't forget to release this spinlock we're holding ...
505 */
506 spin_unlock_irqrestore(&s->lock, flags);
507
508 snd_printk(KERN_ERR "sscape: DMA upload has timed out\n");
509 ret = -EAGAIN;
510 goto _release_dma;
511 }
512 } /* while */
513
514 set_host_mode_unsafe(s->io_base);
515
516 /*
517 * Boot the board ... (I think)
518 */
519 sscape_write_unsafe(s->io_base, GA_HMCTL_REG, sscape_read_unsafe(s->io_base, GA_HMCTL_REG) | 0x40);
520 spin_unlock_irqrestore(&s->lock, flags);
521
522 /*
523 * If all has gone well, then the board should acknowledge
524 * the new upload and tell us that it has rebooted OK. We
525 * give it 5 seconds (max) ...
526 */
527 ret = 0;
528 if (!obp_startup_ack(s, 5)) {
529 snd_printk(KERN_ERR "sscape: No response from on-board processor after upload\n");
530 ret = -EAGAIN;
531 } else if (!host_startup_ack(s, 5)) {
532 snd_printk(KERN_ERR "sscape: SoundScape failed to initialise\n");
533 ret = -EAGAIN;
534 }
535
536 _release_dma:
537 /*
538 * NOTE!!! We are NOT holding any spinlocks at this point !!!
539 */
540 sscape_write(s, GA_DMAA_REG, (s->ic_type == IC_ODIE ? 0x70 : 0x40));
541 free_dmabuf(&dma);
542
543 return ret;
544}
545
546/*
547 * Upload the bootblock(?) into the SoundScape. The only
548 * purpose of this block of code seems to be to tell
549 * us which version of the microcode we should be using.
550 *
551 * NOTE: The boot-block data resides in USER-SPACE!!!
552 * However, we have already verified its memory
553 * addresses by the time we get here.
554 */
555static int sscape_upload_bootblock(struct soundscape *sscape, struct sscape_bootblock __user *bb)
556{
557 unsigned long flags;
558 int data = 0;
559 int ret;
560
561 ret = upload_dma_data(sscape, bb->code, sizeof(bb->code));
562
563 spin_lock_irqsave(&sscape->lock, flags);
564 if (ret == 0) {
565 data = host_read_ctrl_unsafe(sscape->io_base, 100);
566 }
567 set_midi_mode_unsafe(sscape->io_base);
568 spin_unlock_irqrestore(&sscape->lock, flags);
569
570 if (ret == 0) {
571 if (data < 0) {
572 snd_printk(KERN_ERR "sscape: timeout reading firmware version\n");
573 ret = -EAGAIN;
574 }
575 else if (__copy_to_user(&bb->version, &data, sizeof(bb->version))) {
576 ret = -EFAULT;
577 }
578 }
579
580 return ret;
581}
582
583/*
584 * Upload the microcode into the SoundScape. The
585 * microcode is 64K of data, and if we try to copy
586 * it into a local variable then we will SMASH THE
587 * KERNEL'S STACK! We therefore leave it in USER
588 * SPACE, and save ourselves from copying it at all.
589 */
590static int sscape_upload_microcode(struct soundscape *sscape,
591 const struct sscape_microcode __user *mc)
592{
593 unsigned long flags;
594 char __user *code;
595 int err;
596
597 /*
598 * We are going to have to copy this data into a special
599 * DMA-able buffer before we can upload it. We shall therefore
600 * just check that the data pointer is valid for now.
601 *
602 * NOTE: This buffer is 64K long! That's WAY too big to
603 * copy into a stack-temporary anyway.
604 */
605 if ( get_user(code, &mc->code) ||
606 !access_ok(VERIFY_READ, code, SSCAPE_MICROCODE_SIZE) )
607 return -EFAULT;
608
609 if ((err = upload_dma_data(sscape, code, SSCAPE_MICROCODE_SIZE)) == 0) {
610 snd_printk(KERN_INFO "sscape: MIDI firmware loaded\n");
611 }
612
613 spin_lock_irqsave(&sscape->lock, flags);
614 set_midi_mode_unsafe(sscape->io_base);
615 spin_unlock_irqrestore(&sscape->lock, flags);
616
617 initialise_mpu401(sscape->mpu);
618
619 return err;
620}
621
622/*
623 * Hardware-specific device functions, to implement special
624 * IOCTLs for the SoundScape card. This is how we upload
625 * the microcode into the card, for example, and so we
626 * must ensure that no two processes can open this device
627 * simultaneously, and that we can't open it at all if
628 * someone is using the MIDI device.
629 */
630static int sscape_hw_open(snd_hwdep_t * hw, struct file *file)
631{
632 register struct soundscape *sscape = get_hwdep_soundscape(hw);
633 unsigned long flags;
634 int err;
635
636 spin_lock_irqsave(&sscape->fwlock, flags);
637
638 if ((sscape->midi_usage != 0) || sscape->hw_in_use) {
639 err = -EBUSY;
640 } else {
641 sscape->hw_in_use = 1;
642 err = 0;
643 }
644
645 spin_unlock_irqrestore(&sscape->fwlock, flags);
646 return err;
647}
648
649static int sscape_hw_release(snd_hwdep_t * hw, struct file *file)
650{
651 register struct soundscape *sscape = get_hwdep_soundscape(hw);
652 unsigned long flags;
653
654 spin_lock_irqsave(&sscape->fwlock, flags);
655 sscape->hw_in_use = 0;
656 spin_unlock_irqrestore(&sscape->fwlock, flags);
657 return 0;
658}
659
660static int sscape_hw_ioctl(snd_hwdep_t * hw, struct file *file,
661 unsigned int cmd, unsigned long arg)
662{
663 struct soundscape *sscape = get_hwdep_soundscape(hw);
664 int err = -EBUSY;
665
666 switch (cmd) {
667 case SND_SSCAPE_LOAD_BOOTB:
668 {
669 register struct sscape_bootblock __user *bb = (struct sscape_bootblock __user *) arg;
670
671 /*
672 * We are going to have to copy this data into a special
673 * DMA-able buffer before we can upload it. We shall therefore
674 * just check that the data pointer is valid for now ...
675 */
676 if ( !access_ok(VERIFY_READ, bb->code, sizeof(bb->code)) )
677 return -EFAULT;
678
679 /*
680 * Now check that we can write the firmware version number too...
681 */
682 if ( !access_ok(VERIFY_WRITE, &bb->version, sizeof(bb->version)) )
683 return -EFAULT;
684
685 err = sscape_upload_bootblock(sscape, bb);
686 }
687 break;
688
689 case SND_SSCAPE_LOAD_MCODE:
690 {
691 register const struct sscape_microcode __user *mc = (const struct sscape_microcode __user *) arg;
692
693 err = sscape_upload_microcode(sscape, mc);
694 }
695 break;
696
697 default:
698 err = -EINVAL;
699 break;
700 } /* switch */
701
702 return err;
703}
704
705
706/*
707 * Mixer control for the SoundScape's MIDI device.
708 */
709static int sscape_midi_info(snd_kcontrol_t * ctl,
710 snd_ctl_elem_info_t * uinfo)
711{
712 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
713 uinfo->count = 1;
714 uinfo->value.integer.min = 0;
715 uinfo->value.integer.max = 127;
716 return 0;
717}
718
719static int sscape_midi_get(snd_kcontrol_t * kctl,
720 snd_ctl_elem_value_t * uctl)
721{
722 cs4231_t *chip = snd_kcontrol_chip(kctl);
723 snd_card_t *card = chip->card;
724 register struct soundscape *s = get_card_soundscape(card);
725 unsigned long flags;
726
727 spin_lock_irqsave(&s->lock, flags);
728 set_host_mode_unsafe(s->io_base);
729
730 if (host_write_ctrl_unsafe(s->io_base, CMD_GET_MIDI_VOL, 100)) {
731 uctl->value.integer.value[0] = host_read_ctrl_unsafe(s->io_base, 100);
732 }
733
734 set_midi_mode_unsafe(s->io_base);
735 spin_unlock_irqrestore(&s->lock, flags);
736 return 0;
737}
738
739static int sscape_midi_put(snd_kcontrol_t * kctl,
740 snd_ctl_elem_value_t * uctl)
741{
742 cs4231_t *chip = snd_kcontrol_chip(kctl);
743 snd_card_t *card = chip->card;
744 register struct soundscape *s = get_card_soundscape(card);
745 unsigned long flags;
746 int change;
747
748 spin_lock_irqsave(&s->lock, flags);
749
750 /*
751 * We need to put the board into HOST mode before we
752 * can send any volume-changing HOST commands ...
753 */
754 set_host_mode_unsafe(s->io_base);
755
756 /*
757 * To successfully change the MIDI volume setting, you seem to
758 * have to write a volume command, write the new volume value,
759 * and then perform another volume-related command. Perhaps the
760 * first command is an "open" and the second command is a "close"?
761 */
762 if (s->midi_vol == ((unsigned char) uctl->value.integer. value[0] & 127)) {
763 change = 0;
764 goto __skip_change;
765 }
766 change = (host_write_ctrl_unsafe(s->io_base, CMD_SET_MIDI_VOL, 100)
767 && host_write_ctrl_unsafe(s->io_base, ((unsigned char) uctl->value.integer. value[0]) & 127, 100)
768 && host_write_ctrl_unsafe(s->io_base, CMD_XXX_MIDI_VOL, 100));
769 __skip_change:
770
771 /*
772 * Take the board out of HOST mode and back into MIDI mode ...
773 */
774 set_midi_mode_unsafe(s->io_base);
775
776 spin_unlock_irqrestore(&s->lock, flags);
777 return change;
778}
779
780static snd_kcontrol_new_t midi_mixer_ctl = {
781 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
782 .name = "MIDI",
783 .info = sscape_midi_info,
784 .get = sscape_midi_get,
785 .put = sscape_midi_put
786};
787
788/*
789 * The SoundScape can use two IRQs from a possible set of four.
790 * These IRQs are encoded as bit patterns so that they can be
791 * written to the control registers.
792 */
793static unsigned __devinit get_irq_config(int irq)
794{
795 static const int valid_irq[] = { 9, 5, 7, 10 };
796 unsigned cfg;
797
798 for (cfg = 0; cfg < ARRAY_SIZE(valid_irq); ++cfg) {
799 if (irq == valid_irq[cfg])
800 return cfg;
801 } /* for */
802
803 return INVALID_IRQ;
804}
805
806
807/*
808 * Perform certain arcane port-checks to see whether there
809 * is a SoundScape board lurking behind the given ports.
810 */
811static int __devinit detect_sscape(struct soundscape *s)
812{
813 unsigned long flags;
814 unsigned d;
815 int retval = 0;
816
817 spin_lock_irqsave(&s->lock, flags);
818
819 /*
820 * The following code is lifted from the original OSS driver,
821 * and as I don't have a datasheet I cannot really comment
822 * on what it is doing...
823 */
824 if ((inb(HOST_CTRL_IO(s->io_base)) & 0x78) != 0)
825 goto _done;
826
827 d = inb(ODIE_ADDR_IO(s->io_base)) & 0xf0;
828 if ((d & 0x80) != 0)
829 goto _done;
830
831 if (d == 0) {
832 s->codec_type = 1;
833 s->ic_type = IC_ODIE;
834 } else if ((d & 0x60) != 0) {
835 s->codec_type = 2;
836 s->ic_type = IC_OPUS;
837 } else
838 goto _done;
839
840 outb(0xfa, ODIE_ADDR_IO(s->io_base));
841 if ((inb(ODIE_ADDR_IO(s->io_base)) & 0x9f) != 0x0a)
842 goto _done;
843
844 outb(0xfe, ODIE_ADDR_IO(s->io_base));
845 if ((inb(ODIE_ADDR_IO(s->io_base)) & 0x9f) != 0x0e)
846 goto _done;
847 if ((inb(ODIE_DATA_IO(s->io_base)) & 0x9f) != 0x0e)
848 goto _done;
849
850 /*
851 * SoundScape successfully detected!
852 */
853 retval = 1;
854
855 _done:
856 spin_unlock_irqrestore(&s->lock, flags);
857 return retval;
858}
859
860/*
861 * ALSA callback function, called when attempting to open the MIDI device.
862 * Check that the MIDI firmware has been loaded, because we don't want
863 * to crash the machine. Also check that someone isn't using the hardware
864 * IOCTL device.
865 */
866static int mpu401_open(mpu401_t * mpu)
867{
868 int err;
869
870 if (!verify_mpu401(mpu)) {
871 snd_printk(KERN_ERR "sscape: MIDI disabled, please load firmware\n");
872 err = -ENODEV;
873 } else {
874 register struct soundscape *sscape = get_mpu401_soundscape(mpu);
875 unsigned long flags;
876
877 spin_lock_irqsave(&sscape->fwlock, flags);
878
879 if (sscape->hw_in_use || (sscape->midi_usage == ULONG_MAX)) {
880 err = -EBUSY;
881 } else {
882 ++(sscape->midi_usage);
883 err = 0;
884 }
885
886 spin_unlock_irqrestore(&sscape->fwlock, flags);
887 }
888
889 return err;
890}
891
892static void mpu401_close(mpu401_t * mpu)
893{
894 register struct soundscape *sscape = get_mpu401_soundscape(mpu);
895 unsigned long flags;
896
897 spin_lock_irqsave(&sscape->fwlock, flags);
898 --(sscape->midi_usage);
899 spin_unlock_irqrestore(&sscape->fwlock, flags);
900}
901
902/*
903 * Initialse an MPU-401 subdevice for MIDI support on the SoundScape.
904 */
905static int __devinit create_mpu401(snd_card_t * card, int devnum, unsigned long port, int irq)
906{
907 struct soundscape *sscape = get_card_soundscape(card);
908 snd_rawmidi_t *rawmidi;
909 int err;
910
911#define MPU401_SHARE_HARDWARE 1
912 if ((err = snd_mpu401_uart_new(card, devnum,
913 MPU401_HW_MPU401,
914 port, MPU401_SHARE_HARDWARE,
915 irq, SA_INTERRUPT,
916 &rawmidi)) == 0) {
917 mpu401_t *mpu = (mpu401_t *) rawmidi->private_data;
918 mpu->open_input = mpu401_open;
919 mpu->open_output = mpu401_open;
920 mpu->close_input = mpu401_close;
921 mpu->close_output = mpu401_close;
922 mpu->private_data = sscape;
923 sscape->mpu = mpu;
924
925 initialise_mpu401(mpu);
926 }
927
928 return err;
929}
930
931
932/*
933 * Override for the CS4231 playback format function.
934 * The AD1845 has much simpler format and rate selection.
935 */
936static void ad1845_playback_format(cs4231_t * chip, snd_pcm_hw_params_t * params, unsigned char format)
937{
938 unsigned long flags;
939 unsigned rate = params_rate(params);
940
941 /*
942 * The AD1845 can't handle sample frequencies
943 * outside of 4 kHZ to 50 kHZ
944 */
945 if (rate > 50000)
946 rate = 50000;
947 else if (rate < 4000)
948 rate = 4000;
949
950 spin_lock_irqsave(&chip->reg_lock, flags);
951
952 /*
953 * Program the AD1845 correctly for the playback stream.
954 * Note that we do NOT need to toggle the MCE bit because
955 * the PLAYBACK_ENABLE bit of the Interface Configuration
956 * register is set.
957 *
958 * NOTE: We seem to need to write to the MSB before the LSB
959 * to get the correct sample frequency.
960 */
961 snd_cs4231_out(chip, CS4231_PLAYBK_FORMAT, (format & 0xf0));
962 snd_cs4231_out(chip, AD1845_FREQ_SEL_MSB, (unsigned char) (rate >> 8));
963 snd_cs4231_out(chip, AD1845_FREQ_SEL_LSB, (unsigned char) rate);
964
965 spin_unlock_irqrestore(&chip->reg_lock, flags);
966}
967
968/*
969 * Override for the CS4231 capture format function.
970 * The AD1845 has much simpler format and rate selection.
971 */
972static void ad1845_capture_format(cs4231_t * chip, snd_pcm_hw_params_t * params, unsigned char format)
973{
974 unsigned long flags;
975 unsigned rate = params_rate(params);
976
977 /*
978 * The AD1845 can't handle sample frequencies
979 * outside of 4 kHZ to 50 kHZ
980 */
981 if (rate > 50000)
982 rate = 50000;
983 else if (rate < 4000)
984 rate = 4000;
985
986 spin_lock_irqsave(&chip->reg_lock, flags);
987
988 /*
989 * Program the AD1845 correctly for the playback stream.
990 * Note that we do NOT need to toggle the MCE bit because
991 * the CAPTURE_ENABLE bit of the Interface Configuration
992 * register is set.
993 *
994 * NOTE: We seem to need to write to the MSB before the LSB
995 * to get the correct sample frequency.
996 */
997 snd_cs4231_out(chip, CS4231_REC_FORMAT, (format & 0xf0));
998 snd_cs4231_out(chip, AD1845_FREQ_SEL_MSB, (unsigned char) (rate >> 8));
999 snd_cs4231_out(chip, AD1845_FREQ_SEL_LSB, (unsigned char) rate);
1000
1001 spin_unlock_irqrestore(&chip->reg_lock, flags);
1002}
1003
1004/*
1005 * Create an AD1845 PCM subdevice on the SoundScape. The AD1845
1006 * is very much like a CS4231, with a few extra bits. We will
1007 * try to support at least some of the extra bits by overriding
1008 * some of the CS4231 callback.
1009 */
1010static int __devinit create_ad1845(snd_card_t * card, unsigned port, int irq, int dma1)
1011{
1012 register struct soundscape *sscape = get_card_soundscape(card);
1013 cs4231_t *chip;
1014 int err;
1015
1016#define CS4231_SHARE_HARDWARE (CS4231_HWSHARE_DMA1 | CS4231_HWSHARE_DMA2)
1017 /*
1018 * The AD1845 PCM device is only half-duplex, and so
1019 * we only give it one DMA channel ...
1020 */
1021 if ((err = snd_cs4231_create(card,
1022 port, -1, irq, dma1, dma1,
1023 CS4231_HW_DETECT,
1024 CS4231_HWSHARE_DMA1, &chip)) == 0) {
1025 unsigned long flags;
1026 snd_pcm_t *pcm;
1027
1028#define AD1845_FREQ_SEL_ENABLE 0x08
1029
1030#define AD1845_PWR_DOWN_CTRL 0x1b
1031#define AD1845_CRYS_CLOCK_SEL 0x1d
1032
1033/*
1034 * It turns out that the PLAYBACK_ENABLE bit is set
1035 * by the lowlevel driver ...
1036 *
1037#define AD1845_IFACE_CONFIG \
1038 (CS4231_AUTOCALIB | CS4231_RECORD_ENABLE | CS4231_PLAYBACK_ENABLE)
1039 snd_cs4231_mce_up(chip);
1040 spin_lock_irqsave(&chip->reg_lock, flags);
1041 snd_cs4231_out(chip, CS4231_IFACE_CTRL, AD1845_IFACE_CONFIG);
1042 spin_unlock_irqrestore(&chip->reg_lock, flags);
1043 snd_cs4231_mce_down(chip);
1044 */
1045
1046 /*
1047 * The input clock frequency on the SoundScape must
1048 * be 14.31818 MHz, because we must set this register
1049 * to get the playback to sound correct ...
1050 */
1051 snd_cs4231_mce_up(chip);
1052 spin_lock_irqsave(&chip->reg_lock, flags);
1053 snd_cs4231_out(chip, AD1845_CRYS_CLOCK_SEL, 0x20);
1054 spin_unlock_irqrestore(&chip->reg_lock, flags);
1055 snd_cs4231_mce_down(chip);
1056
1057 /*
1058 * More custom configuration:
1059 * a) select "mode 2", and provide a current drive of 8 mA
1060 * b) enable frequency selection (for capture/playback)
1061 */
1062 spin_lock_irqsave(&chip->reg_lock, flags);
1063 snd_cs4231_out(chip, CS4231_MISC_INFO, (CS4231_MODE2 | 0x10));
1064 snd_cs4231_out(chip, AD1845_PWR_DOWN_CTRL, snd_cs4231_in(chip, AD1845_PWR_DOWN_CTRL) | AD1845_FREQ_SEL_ENABLE);
1065 spin_unlock_irqrestore(&chip->reg_lock, flags);
1066
1067 if ((err = snd_cs4231_pcm(chip, 0, &pcm)) < 0) {
1068 snd_printk(KERN_ERR "sscape: No PCM device for AD1845 chip\n");
1069 goto _error;
1070 }
1071
1072 if ((err = snd_cs4231_mixer(chip)) < 0) {
1073 snd_printk(KERN_ERR "sscape: No mixer device for AD1845 chip\n");
1074 goto _error;
1075 }
1076
1077 if ((err = snd_ctl_add(card, snd_ctl_new1(&midi_mixer_ctl, chip))) < 0) {
1078 snd_printk(KERN_ERR "sscape: Could not create MIDI mixer control\n");
1079 goto _error;
1080 }
1081
1082 strcpy(card->driver, "SoundScape");
1083 strcpy(card->shortname, pcm->name);
1084 snprintf(card->longname, sizeof(card->longname),
1085 "%s at 0x%lx, IRQ %d, DMA %d\n",
1086 pcm->name, chip->port, chip->irq, chip->dma1);
1087 chip->set_playback_format = ad1845_playback_format;
1088 chip->set_capture_format = ad1845_capture_format;
1089 sscape->chip = chip;
1090 }
1091
1092 _error:
1093 return err;
1094}
1095
1096
1097struct params
1098{
1099 int index;
1100 const char *id;
1101 unsigned port;
1102 int irq;
1103 int mpu_irq;
1104 int dma1;
1105};
1106
1107
1108static inline struct params*
1109init_params(struct params *params,
1110 int index,
1111 const char *id,
1112 unsigned port,
1113 int irq,
1114 int mpu_irq,
1115 int dma1)
1116{
1117 params->index = index;
1118 params->id = id;
1119 params->port = port;
1120 params->irq = irq;
1121 params->mpu_irq = mpu_irq;
1122 params->dma1 = (dma1 & 0x03);
1123
1124 return params;
1125}
1126
1127
1128/*
1129 * Create an ALSA soundcard entry for the SoundScape, using
1130 * the given list of port, IRQ and DMA resources.
1131 */
1132static int __devinit create_sscape(const struct params *params, snd_card_t **rcardp)
1133{
1134 snd_card_t *card;
1135 register struct soundscape *sscape;
1136 register unsigned dma_cfg;
1137 unsigned irq_cfg;
1138 unsigned mpu_irq_cfg;
1139 struct resource *io_res;
1140 unsigned long flags;
1141 int err;
1142
1143 /*
1144 * Check that the user didn't pass us garbage data ...
1145 */
1146 irq_cfg = get_irq_config(params->irq);
1147 if (irq_cfg == INVALID_IRQ) {
1148 snd_printk(KERN_ERR "sscape: Invalid IRQ %d\n", params->irq);
1149 return -ENXIO;
1150 }
1151
1152 mpu_irq_cfg = get_irq_config(params->mpu_irq);
1153 if (mpu_irq_cfg == INVALID_IRQ) {
1154 printk(KERN_ERR "sscape: Invalid IRQ %d\n", params->mpu_irq);
1155 return -ENXIO;
1156 }
1157
1158 /*
1159 * Grab IO ports that we will need to probe so that we
1160 * can detect and control this hardware ...
1161 */
1162 if ((io_res = request_region(params->port, 8, "SoundScape")) == NULL) {
1163 snd_printk(KERN_ERR "sscape: can't grab port 0x%x\n", params->port);
1164 return -EBUSY;
1165 }
1166
1167 /*
1168 * Grab both DMA channels (OK, only one for now) ...
1169 */
1170 if ((err = request_dma(params->dma1, "SoundScape")) < 0) {
1171 snd_printk(KERN_ERR "sscape: can't grab DMA %d\n", params->dma1);
1172 goto _release_region;
1173 }
1174
1175 /*
1176 * Create a new ALSA sound card entry, in anticipation
1177 * of detecting our hardware ...
1178 */
1179 if ((card = snd_card_new(params->index, params->id, THIS_MODULE, sizeof(struct soundscape))) == NULL) {
1180 err = -ENOMEM;
1181 goto _release_dma;
1182 }
1183
1184 sscape = get_card_soundscape(card);
1185 spin_lock_init(&sscape->lock);
1186 spin_lock_init(&sscape->fwlock);
1187 sscape->io_res = io_res;
1188 sscape->io_base = params->port;
1189
1190 if (!detect_sscape(sscape)) {
1191 printk(KERN_ERR "sscape: hardware not detected at 0x%x\n", sscape->io_base);
1192 err = -ENODEV;
1193 goto _release_card;
1194 }
1195
1196 printk(KERN_INFO "sscape: hardware detected at 0x%x, using IRQ %d, DMA %d\n",
1197 sscape->io_base, params->irq, params->dma1);
1198
1199 /*
1200 * Now create the hardware-specific device so that we can
1201 * load the microcode into the on-board processor.
1202 * We cannot use the MPU-401 MIDI system until this firmware
1203 * has been loaded into the card.
1204 */
1205 if ((err = snd_hwdep_new(card, "MC68EC000", 0, &(sscape->hw))) < 0) {
1206 printk(KERN_ERR "sscape: Failed to create firmware device\n");
1207 goto _release_card;
1208 }
1209 strlcpy(sscape->hw->name, "SoundScape M68K", sizeof(sscape->hw->name));
1210 sscape->hw->name[sizeof(sscape->hw->name) - 1] = '\0';
1211 sscape->hw->iface = SNDRV_HWDEP_IFACE_SSCAPE;
1212 sscape->hw->ops.open = sscape_hw_open;
1213 sscape->hw->ops.release = sscape_hw_release;
1214 sscape->hw->ops.ioctl = sscape_hw_ioctl;
1215 sscape->hw->private_data = sscape;
1216
1217 /*
1218 * Tell the on-board devices where their resources are (I think -
1219 * I can't be sure without a datasheet ... So many magic values!)
1220 */
1221 spin_lock_irqsave(&sscape->lock, flags);
1222
1223 activate_ad1845_unsafe(sscape->io_base);
1224
1225 sscape_write_unsafe(sscape->io_base, GA_INTENA_REG, 0x00); /* disable */
1226 sscape_write_unsafe(sscape->io_base, GA_SMCFGA_REG, 0x2e);
1227 sscape_write_unsafe(sscape->io_base, GA_SMCFGB_REG, 0x00);
1228
1229 /*
1230 * Enable and configure the DMA channels ...
1231 */
1232 sscape_write_unsafe(sscape->io_base, GA_DMACFG_REG, 0x50);
1233 dma_cfg = (sscape->ic_type == IC_ODIE ? 0x70 : 0x40);
1234 sscape_write_unsafe(sscape->io_base, GA_DMAA_REG, dma_cfg);
1235 sscape_write_unsafe(sscape->io_base, GA_DMAB_REG, 0x20);
1236
1237 sscape_write_unsafe(sscape->io_base,
1238 GA_INTCFG_REG, 0xf0 | (mpu_irq_cfg << 2) | mpu_irq_cfg);
1239 sscape_write_unsafe(sscape->io_base,
1240 GA_CDCFG_REG, 0x09 | DMA_8BIT | (params->dma1 << 4) | (irq_cfg << 1));
1241
1242 spin_unlock_irqrestore(&sscape->lock, flags);
1243
1244 /*
1245 * We have now enabled the codec chip, and so we should
1246 * detect the AD1845 device ...
1247 */
1248 if ((err = create_ad1845(card, CODEC_IO(params->port), params->irq, params->dma1)) < 0) {
1249 printk(KERN_ERR "sscape: No AD1845 device at 0x%x, IRQ %d\n",
1250 CODEC_IO(params->port), params->irq);
1251 goto _release_card;
1252 }
1253#define MIDI_DEVNUM 0
1254 if ((err = create_mpu401(card, MIDI_DEVNUM, MPU401_IO(params->port), params->mpu_irq)) < 0) {
1255 printk(KERN_ERR "sscape: Failed to create MPU-401 device at 0x%x\n",
1256 MPU401_IO(params->port));
1257 goto _release_card;
1258 }
1259
1260 /*
1261 * Enable the master IRQ ...
1262 */
1263 sscape_write(sscape, GA_INTENA_REG, 0x80);
1264
1265 if ((err = snd_card_register(card)) < 0) {
1266 printk(KERN_ERR "sscape: Failed to register sound card\n");
1267 goto _release_card;
1268 }
1269
1270 /*
1271 * Initialize mixer
1272 */
1273 sscape->midi_vol = 0;
1274 host_write_ctrl_unsafe(sscape->io_base, CMD_SET_MIDI_VOL, 100);
1275 host_write_ctrl_unsafe(sscape->io_base, 0, 100);
1276 host_write_ctrl_unsafe(sscape->io_base, CMD_XXX_MIDI_VOL, 100);
1277
1278 /*
1279 * Now that we have successfully created this sound card,
1280 * it is safe to store the pointer.
1281 * NOTE: we only register the sound card's "destructor"
1282 * function now that our "constructor" has completed.
1283 */
1284 card->private_free = soundscape_free;
1285 *rcardp = card;
1286
1287 return 0;
1288
1289 _release_card:
1290 snd_card_free(card);
1291
1292 _release_dma:
1293 free_dma(params->dma1);
1294
1295 _release_region:
1296 release_resource(io_res);
1297 kfree_nocheck(io_res);
1298
1299 return err;
1300}
1301
1302
1303static int sscape_cards __devinitdata;
1304static struct params sscape_params[SNDRV_CARDS] __devinitdata;
1305
1306#ifdef CONFIG_PNP
1307static inline int __devinit get_next_autoindex(int i)
1308{
1309 while ((i < SNDRV_CARDS) && (port[i] != SNDRV_AUTO_PORT)) {
1310 ++i;
1311 } /* while */
1312
1313 return i;
1314}
1315
1316
1317static inline int __devinit is_port_known(unsigned io, struct params *params, int cards)
1318{
1319 while (--cards >= 0) {
1320 if (params[cards].port == io)
1321 return 1;
1322 } /* while */
1323
1324 return 0;
1325}
1326
1327static int __devinit sscape_pnp_detect(struct pnp_card_link *pcard,
1328 const struct pnp_card_device_id *pid)
1329{
1330 struct pnp_dev *dev;
1331 static int idx = 0;
1332 int ret;
1333
1334 /*
1335 * Allow this function to fail *quietly* if all the ISA PnP
1336 * devices were configured using module parameters instead.
1337 */
1338 if ((idx = get_next_autoindex(idx)) >= SNDRV_CARDS) {
1339 return -ENOSPC;
1340 }
1341
1342 /*
1343 * We have found a candidate ISA PnP card. Now we
1344 * have to check that it has the devices that we
1345 * expect it to have.
1346 *
1347 * We will NOT try and autoconfigure all of the resources
1348 * needed and then activate the card as we are assuming that
1349 * has already been done at boot-time using /proc/isapnp.
1350 * We shall simply try to give each active card the resources
1351 * that it wants. This is a sensible strategy for a modular
1352 * system where unused modules are unloaded regularly.
1353 *
1354 * This strategy is utterly useless if we compile the driver
1355 * into the kernel, of course.
1356 */
1357 // printk(KERN_INFO "sscape: %s\n", card->name);
1358
1359 /*
1360 * Check that we still have room for another sound card ...
1361 */
1362 if (sscape_cards >= SNDRV_CARDS) {
1363 printk(KERN_ERR "sscape: No room for another ALSA device\n");
1364 return -ENOSPC;
1365 }
1366
1367 ret = -ENODEV;
1368
1369 dev = pnp_request_card_device(pcard, pid->devs[0].id, NULL);
1370 if (dev) {
1371 struct params *this;
1372 if (!pnp_is_active(dev)) {
1373 if (pnp_activate_dev(dev) < 0) {
1374 printk(KERN_INFO "sscape: device is inactive\n");
1375 return -EBUSY;
1376 }
1377 }
1378 /*
1379 * Read the correct parameters off the ISA PnP bus ...
1380 */
1381 this = init_params(&sscape_params[sscape_cards],
1382 index[idx],
1383 id[idx],
1384 pnp_port_start(dev, 0),
1385 pnp_irq(dev, 0),
1386 pnp_irq(dev, 1),
1387 pnp_dma(dev, 0));
1388
1389 /*
1390 * Do we know about this sound card already?
1391 */
1392 if ( !is_port_known(this->port, sscape_params, sscape_cards) ) {
1393 snd_card_t *card;
1394
1395 ret = create_sscape(this, &card);
1396 if (ret < 0)
1397 return ret;
1398 snd_card_set_dev(card, &pcard->card->dev);
1399 pnp_set_card_drvdata(pcard, card);
1400 ++sscape_cards;
1401 ++idx;
1402 }
1403 }
1404
1405 return ret;
1406}
1407
1408static void __devexit sscape_pnp_remove(struct pnp_card_link * pcard)
1409{
1410 snd_card_t *card = (snd_card_t *) pnp_get_card_drvdata(pcard);
1411
1412 pnp_set_card_drvdata(pcard, NULL);
1413 snd_card_disconnect(card);
1414 snd_card_free_in_thread(card);
1415}
1416
1417static struct pnp_card_driver sscape_pnpc_driver = {
1418 .flags = PNP_DRIVER_RES_DO_NOT_CHANGE,
1419 .name = "sscape",
1420 .id_table = sscape_pnpids,
1421 .probe = sscape_pnp_detect,
1422 .remove = __devexit_p(sscape_pnp_remove),
1423};
1424
1425#endif /* CONFIG_PNP */
1426
1427static int __init sscape_manual_probe(struct params *params)
1428{
1429 int ret;
1430 unsigned i;
1431 snd_card_t *card;
1432
1433 for (i = 0; i < SNDRV_CARDS; ++i) {
1434 /*
1435 * We do NOT probe for ports.
1436 * If we're not given a port number for this
1437 * card then we completely ignore this line
1438 * of parameters.
1439 */
1440 if (port[i] == SNDRV_AUTO_PORT)
1441 continue;
1442
1443 /*
1444 * Make sure we were given ALL of the other parameters.
1445 */
1446 if ( (irq[i] == SNDRV_AUTO_IRQ) ||
1447 (mpu_irq[i] == SNDRV_AUTO_IRQ) ||
1448 (dma[i] == SNDRV_AUTO_DMA) ) {
1449 printk(KERN_INFO
1450 "sscape: insufficient parameters, need IO, IRQ, MPU-IRQ and DMA\n");
1451 return -ENXIO;
1452 }
1453
1454 /*
1455 * This cards looks OK ...
1456 */
1457 init_params(params, index[i], id[i], port[i], irq[i], mpu_irq[i], dma[i]);
1458
1459 ret = create_sscape(params, &card);
1460 if (ret < 0)
1461 return ret;
1462
1463 sscape_card[sscape_cards] = card;
1464 params++;
1465 sscape_cards++;
1466 } /* for */
1467
1468 return 0;
1469}
1470
1471
1472static void sscape_exit(void)
1473{
1474 unsigned i;
1475
1476#ifdef CONFIG_PNP
1477 pnp_unregister_card_driver(&sscape_pnpc_driver);
1478#endif
1479 for (i = 0; i < ARRAY_SIZE(sscape_card); ++i) {
1480 snd_card_free(sscape_card[i]);
1481 } /* for */
1482}
1483
1484
1485static int __init sscape_init(void)
1486{
1487 int ret;
1488
1489 /*
1490 * First check whether we were passed any parameters.
1491 * These MUST take precedence over ANY automatic way
1492 * of allocating cards, because the operator is
1493 * S-P-E-L-L-I-N-G it out for us...
1494 */
1495 ret = sscape_manual_probe(sscape_params);
1496 if (ret < 0) {
1497 int i;
1498 for (i = 0; i < sscape_cards; ++i)
1499 snd_card_free(sscape_card[i]);
1500 return ret;
1501 }
1502
1503#ifdef CONFIG_PNP
1504 if (sscape_cards < SNDRV_CARDS) {
1505 ret = pnp_register_card_driver(&sscape_pnpc_driver);
1506 if (ret < 0) {
1507 sscape_exit();
1508 return ret;
1509 }
1510 }
1511#endif
1512
1513 return 0;
1514}
1515
1516module_init(sscape_init);
1517module_exit(sscape_exit);
diff --git a/sound/isa/wavefront/Makefile b/sound/isa/wavefront/Makefile
new file mode 100644
index 000000000000..b4cb28422db0
--- /dev/null
+++ b/sound/isa/wavefront/Makefile
@@ -0,0 +1,9 @@
1#
2# Makefile for ALSA
3# Copyright (c) 2001 by Jaroslav Kysela <perex@suse.cz>
4#
5
6snd-wavefront-objs := wavefront.o wavefront_fx.o wavefront_synth.o wavefront_midi.o
7
8# Toplevel Module Dependency
9obj-$(CONFIG_SND_WAVEFRONT) += snd-wavefront.o
diff --git a/sound/isa/wavefront/wavefront.c b/sound/isa/wavefront/wavefront.c
new file mode 100644
index 000000000000..79b022070ba3
--- /dev/null
+++ b/sound/isa/wavefront/wavefront.c
@@ -0,0 +1,716 @@
1/*
2 * ALSA card-level driver for Turtle Beach Wavefront cards
3 * (Maui,Tropez,Tropez+)
4 *
5 * Copyright (c) 1997-1999 by Paul Barton-Davis <pbd@op.net>
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 */
21
22#include <sound/driver.h>
23#include <linux/init.h>
24#include <linux/interrupt.h>
25#include <linux/slab.h>
26#include <linux/pnp.h>
27#include <linux/moduleparam.h>
28#include <sound/core.h>
29#include <sound/initval.h>
30#include <sound/opl3.h>
31#include <sound/snd_wavefront.h>
32
33MODULE_AUTHOR("Paul Barton-Davis <pbd@op.net>");
34MODULE_DESCRIPTION("Turtle Beach Wavefront");
35MODULE_LICENSE("GPL");
36MODULE_SUPPORTED_DEVICE("{{Turtle Beach,Maui/Tropez/Tropez+}}");
37
38static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-MAX */
39static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* ID for this card */
40static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE; /* Enable this card */
41static int isapnp[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 1};
42static long cs4232_pcm_port[SNDRV_CARDS] = SNDRV_DEFAULT_PORT; /* PnP setup */
43static int cs4232_pcm_irq[SNDRV_CARDS] = SNDRV_DEFAULT_IRQ; /* 5,7,9,11,12,15 */
44static long cs4232_mpu_port[SNDRV_CARDS] = SNDRV_DEFAULT_PORT; /* PnP setup */
45static int cs4232_mpu_irq[SNDRV_CARDS] = SNDRV_DEFAULT_IRQ; /* 9,11,12,15 */
46static long ics2115_port[SNDRV_CARDS] = SNDRV_DEFAULT_PORT; /* PnP setup */
47static int ics2115_irq[SNDRV_CARDS] = SNDRV_DEFAULT_IRQ; /* 2,9,11,12,15 */
48static long fm_port[SNDRV_CARDS] = SNDRV_DEFAULT_PORT; /* PnP setup */
49static int dma1[SNDRV_CARDS] = SNDRV_DEFAULT_DMA; /* 0,1,3,5,6,7 */
50static int dma2[SNDRV_CARDS] = SNDRV_DEFAULT_DMA; /* 0,1,3,5,6,7 */
51static int use_cs4232_midi[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 0};
52
53module_param_array(index, int, NULL, 0444);
54MODULE_PARM_DESC(index, "Index value for WaveFront soundcard.");
55module_param_array(id, charp, NULL, 0444);
56MODULE_PARM_DESC(id, "ID string for WaveFront soundcard.");
57module_param_array(enable, bool, NULL, 0444);
58MODULE_PARM_DESC(enable, "Enable WaveFront soundcard.");
59#ifdef CONFIG_PNP
60module_param_array(isapnp, bool, NULL, 0444);
61MODULE_PARM_DESC(isapnp, "ISA PnP detection for WaveFront soundcards.");
62#endif
63module_param_array(cs4232_pcm_port, long, NULL, 0444);
64MODULE_PARM_DESC(cs4232_pcm_port, "Port # for CS4232 PCM interface.");
65module_param_array(cs4232_pcm_irq, int, NULL, 0444);
66MODULE_PARM_DESC(cs4232_pcm_irq, "IRQ # for CS4232 PCM interface.");
67module_param_array(dma1, int, NULL, 0444);
68MODULE_PARM_DESC(dma1, "DMA1 # for CS4232 PCM interface.");
69module_param_array(dma2, int, NULL, 0444);
70MODULE_PARM_DESC(dma2, "DMA2 # for CS4232 PCM interface.");
71module_param_array(cs4232_mpu_port, long, NULL, 0444);
72MODULE_PARM_DESC(cs4232_mpu_port, "port # for CS4232 MPU-401 interface.");
73module_param_array(cs4232_mpu_irq, int, NULL, 0444);
74MODULE_PARM_DESC(cs4232_mpu_irq, "IRQ # for CS4232 MPU-401 interface.");
75module_param_array(ics2115_irq, int, NULL, 0444);
76MODULE_PARM_DESC(ics2115_irq, "IRQ # for ICS2115.");
77module_param_array(ics2115_port, long, NULL, 0444);
78MODULE_PARM_DESC(ics2115_port, "Port # for ICS2115.");
79module_param_array(fm_port, long, NULL, 0444);
80MODULE_PARM_DESC(fm_port, "FM port #.");
81module_param_array(use_cs4232_midi, bool, NULL, 0444);
82MODULE_PARM_DESC(use_cs4232_midi, "Use CS4232 MPU-401 interface (inaccessibly located inside your computer)");
83
84static snd_card_t *snd_wavefront_legacy[SNDRV_CARDS] = SNDRV_DEFAULT_PTR;
85
86#ifdef CONFIG_PNP
87
88static struct pnp_card_device_id snd_wavefront_pnpids[] = {
89 /* Tropez */
90 { .id = "CSC7532", .devs = { { "CSC0000" }, { "CSC0010" }, { "PnPb006" }, { "CSC0004" } } },
91 /* Tropez+ */
92 { .id = "CSC7632", .devs = { { "CSC0000" }, { "CSC0010" }, { "PnPb006" }, { "CSC0004" } } },
93 { .id = "" }
94};
95
96MODULE_DEVICE_TABLE(pnp_card, snd_wavefront_pnpids);
97
98static int __devinit
99snd_wavefront_pnp (int dev, snd_wavefront_card_t *acard, struct pnp_card_link *card,
100 const struct pnp_card_device_id *id)
101{
102 struct pnp_dev *pdev;
103 struct pnp_resource_table *cfg = kmalloc(sizeof(*cfg), GFP_KERNEL);
104 int err;
105
106 if (!cfg)
107 return -ENOMEM;
108
109 /* Check for each logical device. */
110
111 /* CS4232 chip (aka "windows sound system") is logical device 0 */
112
113 acard->wss = pnp_request_card_device(card, id->devs[0].id, NULL);
114 if (acard->wss == NULL) {
115 kfree(cfg);
116 return -EBUSY;
117 }
118
119 /* there is a game port at logical device 1, but we ignore it completely */
120
121 /* the control interface is logical device 2, but we ignore it
122 completely. in fact, nobody even seems to know what it
123 does.
124 */
125
126 /* Only configure the CS4232 MIDI interface if its been
127 specifically requested. It is logical device 3.
128 */
129
130 if (use_cs4232_midi[dev]) {
131 acard->mpu = pnp_request_card_device(card, id->devs[2].id, NULL);
132 if (acard->mpu == NULL) {
133 kfree(cfg);
134 return -EBUSY;
135 }
136 }
137
138 /* The ICS2115 synth is logical device 4 */
139
140 acard->synth = pnp_request_card_device(card, id->devs[3].id, NULL);
141 if (acard->synth == NULL) {
142 kfree(cfg);
143 return -EBUSY;
144 }
145
146 /* PCM/FM initialization */
147
148 pdev = acard->wss;
149
150 pnp_init_resource_table(cfg);
151
152 /* An interesting note from the Tropez+ FAQ:
153
154 Q. [Ports] Why is the base address of the WSS I/O ports off by 4?
155
156 A. WSS I/O requires a block of 8 I/O addresses ("ports"). Of these, the first
157 4 are used to identify and configure the board. With the advent of PnP,
158 these first 4 addresses have become obsolete, and software applications
159 only use the last 4 addresses to control the codec chip. Therefore, the
160 base address setting "skips past" the 4 unused addresses.
161
162 */
163
164 if (cs4232_pcm_port[dev] != SNDRV_AUTO_PORT)
165 pnp_resource_change(&cfg->port_resource[0], cs4232_pcm_port[dev], 4);
166 if (fm_port[dev] != SNDRV_AUTO_PORT)
167 pnp_resource_change(&cfg->port_resource[1], fm_port[dev], 4);
168 if (dma1[dev] != SNDRV_AUTO_DMA)
169 pnp_resource_change(&cfg->dma_resource[0], dma1[dev], 1);
170 if (dma2[dev] != SNDRV_AUTO_DMA)
171 pnp_resource_change(&cfg->dma_resource[1], dma2[dev], 1);
172 if (cs4232_pcm_irq[dev] != SNDRV_AUTO_IRQ)
173 pnp_resource_change(&cfg->irq_resource[0], cs4232_pcm_irq[dev], 1);
174
175 if (pnp_manual_config_dev(pdev, cfg, 0) < 0)
176 snd_printk(KERN_ERR "PnP WSS the requested resources are invalid, using auto config\n");
177 err = pnp_activate_dev(pdev);
178 if (err < 0) {
179 snd_printk(KERN_ERR "PnP WSS pnp configure failure\n");
180 kfree(cfg);
181 return err;
182 }
183
184 cs4232_pcm_port[dev] = pnp_port_start(pdev, 0);
185 fm_port[dev] = pnp_port_start(pdev, 1);
186 dma1[dev] = pnp_dma(pdev, 0);
187 dma2[dev] = pnp_dma(pdev, 1);
188 cs4232_pcm_irq[dev] = pnp_irq(pdev, 0);
189
190 /* Synth initialization */
191
192 pdev = acard->synth;
193
194 pnp_init_resource_table(cfg);
195
196 if (ics2115_port[dev] != SNDRV_AUTO_PORT) {
197 pnp_resource_change(&cfg->port_resource[0], ics2115_port[dev], 16);
198 }
199
200 if (ics2115_port[dev] != SNDRV_AUTO_IRQ) {
201 pnp_resource_change(&cfg->irq_resource[0], ics2115_irq[dev], 1);
202 }
203
204 if (pnp_manual_config_dev(pdev, cfg, 0) < 0)
205 snd_printk(KERN_ERR "PnP ICS2115 the requested resources are invalid, using auto config\n");
206 err = pnp_activate_dev(pdev);
207 if (err < 0) {
208 snd_printk(KERN_ERR "PnP ICS2115 pnp configure failure\n");
209 kfree(cfg);
210 return err;
211 }
212
213 ics2115_port[dev] = pnp_port_start(pdev, 0);
214 ics2115_irq[dev] = pnp_irq(pdev, 0);
215
216 /* CS4232 MPU initialization. Configure this only if
217 explicitly requested, since its physically inaccessible and
218 consumes another IRQ.
219 */
220
221 if (use_cs4232_midi[dev]) {
222
223 pdev = acard->mpu;
224
225 pnp_init_resource_table(cfg);
226
227 if (cs4232_mpu_port[dev] != SNDRV_AUTO_PORT)
228 pnp_resource_change(&cfg->port_resource[0], cs4232_mpu_port[dev], 2);
229 if (cs4232_mpu_irq[dev] != SNDRV_AUTO_IRQ)
230 pnp_resource_change(&cfg->port_resource[0], cs4232_mpu_irq[dev], 1);
231
232 if (pnp_manual_config_dev(pdev, cfg, 0) < 0)
233 snd_printk(KERN_ERR "PnP MPU401 the requested resources are invalid, using auto config\n");
234 err = pnp_activate_dev(pdev);
235 if (err < 0) {
236 snd_printk(KERN_ERR "PnP MPU401 pnp configure failure\n");
237 cs4232_mpu_port[dev] = SNDRV_AUTO_PORT;
238 } else {
239 cs4232_mpu_port[dev] = pnp_port_start(pdev, 0);
240 cs4232_mpu_irq[dev] = pnp_irq(pdev, 0);
241 }
242
243 snd_printk ("CS4232 MPU: port=0x%lx, irq=%i\n",
244 cs4232_mpu_port[dev],
245 cs4232_mpu_irq[dev]);
246 }
247
248 snd_printdd ("CS4232: pcm port=0x%lx, fm port=0x%lx, dma1=%i, dma2=%i, irq=%i\nICS2115: port=0x%lx, irq=%i\n",
249 cs4232_pcm_port[dev],
250 fm_port[dev],
251 dma1[dev],
252 dma2[dev],
253 cs4232_pcm_irq[dev],
254 ics2115_port[dev],
255 ics2115_irq[dev]);
256
257 kfree(cfg);
258 return 0;
259}
260
261#endif /* CONFIG_PNP */
262
263static irqreturn_t snd_wavefront_ics2115_interrupt(int irq,
264 void *dev_id,
265 struct pt_regs *regs)
266{
267 snd_wavefront_card_t *acard;
268
269 acard = (snd_wavefront_card_t *) dev_id;
270
271 if (acard == NULL)
272 return IRQ_NONE;
273
274 if (acard->wavefront.interrupts_are_midi) {
275 snd_wavefront_midi_interrupt (acard);
276 } else {
277 snd_wavefront_internal_interrupt (acard);
278 }
279 return IRQ_HANDLED;
280}
281
282static snd_hwdep_t * __devinit
283snd_wavefront_new_synth (snd_card_t *card,
284 int hw_dev,
285 snd_wavefront_card_t *acard)
286{
287 snd_hwdep_t *wavefront_synth;
288
289 if (snd_wavefront_detect (acard) < 0) {
290 return NULL;
291 }
292
293 if (snd_wavefront_start (&acard->wavefront) < 0) {
294 return NULL;
295 }
296
297 if (snd_hwdep_new(card, "WaveFront", hw_dev, &wavefront_synth) < 0)
298 return NULL;
299 strcpy (wavefront_synth->name,
300 "WaveFront (ICS2115) wavetable synthesizer");
301 wavefront_synth->ops.open = snd_wavefront_synth_open;
302 wavefront_synth->ops.release = snd_wavefront_synth_release;
303 wavefront_synth->ops.ioctl = snd_wavefront_synth_ioctl;
304
305 return wavefront_synth;
306}
307
308static snd_hwdep_t * __devinit
309snd_wavefront_new_fx (snd_card_t *card,
310 int hw_dev,
311 snd_wavefront_card_t *acard,
312 unsigned long port)
313
314{
315 snd_hwdep_t *fx_processor;
316
317 if (snd_wavefront_fx_start (&acard->wavefront)) {
318 snd_printk ("cannot initialize YSS225 FX processor");
319 return NULL;
320 }
321
322 if (snd_hwdep_new (card, "YSS225", hw_dev, &fx_processor) < 0)
323 return NULL;
324 sprintf (fx_processor->name, "YSS225 FX Processor at 0x%lx", port);
325 fx_processor->ops.open = snd_wavefront_fx_open;
326 fx_processor->ops.release = snd_wavefront_fx_release;
327 fx_processor->ops.ioctl = snd_wavefront_fx_ioctl;
328
329 return fx_processor;
330}
331
332static snd_wavefront_mpu_id internal_id = internal_mpu;
333static snd_wavefront_mpu_id external_id = external_mpu;
334
335static snd_rawmidi_t * __devinit
336snd_wavefront_new_midi (snd_card_t *card,
337 int midi_dev,
338 snd_wavefront_card_t *acard,
339 unsigned long port,
340 snd_wavefront_mpu_id mpu)
341
342{
343 snd_rawmidi_t *rmidi;
344 static int first = 1;
345
346 if (first) {
347 first = 0;
348 acard->wavefront.midi.base = port;
349 if (snd_wavefront_midi_start (acard)) {
350 snd_printk ("cannot initialize MIDI interface\n");
351 return NULL;
352 }
353 }
354
355 if (snd_rawmidi_new (card, "WaveFront MIDI", midi_dev, 1, 1, &rmidi) < 0)
356 return NULL;
357
358 if (mpu == internal_mpu) {
359 strcpy(rmidi->name, "WaveFront MIDI (Internal)");
360 rmidi->private_data = &internal_id;
361 } else {
362 strcpy(rmidi->name, "WaveFront MIDI (External)");
363 rmidi->private_data = &external_id;
364 }
365
366 snd_rawmidi_set_ops(rmidi, SNDRV_RAWMIDI_STREAM_OUTPUT, &snd_wavefront_midi_output);
367 snd_rawmidi_set_ops(rmidi, SNDRV_RAWMIDI_STREAM_INPUT, &snd_wavefront_midi_input);
368
369 rmidi->info_flags |= SNDRV_RAWMIDI_INFO_OUTPUT |
370 SNDRV_RAWMIDI_INFO_INPUT |
371 SNDRV_RAWMIDI_INFO_DUPLEX;
372
373 return rmidi;
374}
375
376static void
377snd_wavefront_free(snd_card_t *card)
378{
379 snd_wavefront_card_t *acard = (snd_wavefront_card_t *)card->private_data;
380
381 if (acard) {
382 if (acard->wavefront.res_base != NULL) {
383 release_resource(acard->wavefront.res_base);
384 kfree_nocheck(acard->wavefront.res_base);
385 }
386 if (acard->wavefront.irq > 0)
387 free_irq(acard->wavefront.irq, (void *)acard);
388 }
389}
390
391static int __devinit
392snd_wavefront_probe (int dev, struct pnp_card_link *pcard,
393 const struct pnp_card_device_id *pid)
394{
395 snd_card_t *card;
396 snd_wavefront_card_t *acard;
397 cs4231_t *chip;
398 snd_hwdep_t *wavefront_synth;
399 snd_rawmidi_t *ics2115_internal_rmidi = NULL;
400 snd_rawmidi_t *ics2115_external_rmidi = NULL;
401 snd_hwdep_t *fx_processor;
402 int hw_dev = 0, midi_dev = 0, err;
403
404#ifdef CONFIG_PNP
405 if (!isapnp[dev]) {
406#endif
407 if (cs4232_pcm_port[dev] == SNDRV_AUTO_PORT) {
408 snd_printk("specify CS4232 port\n");
409 return -EINVAL;
410 }
411 if (ics2115_port[dev] == SNDRV_AUTO_PORT) {
412 snd_printk("specify ICS2115 port\n");
413 return -ENODEV;
414 }
415#ifdef CONFIG_PNP
416 }
417#endif
418 card = snd_card_new (index[dev],
419 id[dev],
420 THIS_MODULE,
421 sizeof(snd_wavefront_card_t));
422
423 if (card == NULL) {
424 return -ENOMEM;
425 }
426 acard = (snd_wavefront_card_t *)card->private_data;
427 acard->wavefront.irq = -1;
428 spin_lock_init(&acard->wavefront.irq_lock);
429 init_waitqueue_head(&acard->wavefront.interrupt_sleeper);
430 spin_lock_init(&acard->wavefront.midi.open);
431 spin_lock_init(&acard->wavefront.midi.virtual);
432 card->private_free = snd_wavefront_free;
433
434#ifdef CONFIG_PNP
435 if (isapnp[dev]) {
436 if (snd_wavefront_pnp (dev, acard, pcard, pid) < 0) {
437 if (cs4232_pcm_port[dev] == SNDRV_AUTO_PORT) {
438 snd_printk ("isapnp detection failed\n");
439 snd_card_free (card);
440 return -ENODEV;
441 }
442 }
443 snd_card_set_dev(card, &pcard->card->dev);
444 }
445#endif /* CONFIG_PNP */
446
447 /* --------- PCM --------------- */
448
449 if ((err = snd_cs4231_create (card,
450 cs4232_pcm_port[dev],
451 -1,
452 cs4232_pcm_irq[dev],
453 dma1[dev],
454 dma2[dev],
455 CS4231_HW_DETECT, 0, &chip)) < 0) {
456 snd_card_free(card);
457 snd_printk ("can't allocate CS4231 device\n");
458 return err;
459 }
460
461 if ((err = snd_cs4231_pcm (chip, 0, NULL)) < 0) {
462 snd_card_free(card);
463 return err;
464 }
465 if ((err = snd_cs4231_timer (chip, 0, NULL)) < 0) {
466 snd_card_free(card);
467 return err;
468 }
469
470 /* ---------- OPL3 synth --------- */
471
472 if (fm_port[dev] > 0 && fm_port[dev] != SNDRV_AUTO_PORT) {
473 opl3_t *opl3;
474
475 if ((err = snd_opl3_create(card,
476 fm_port[dev],
477 fm_port[dev] + 2,
478 OPL3_HW_OPL3_CS,
479 0, &opl3)) < 0) {
480 snd_printk ("can't allocate or detect OPL3 synth\n");
481 snd_card_free(card);
482 return err;
483 }
484
485 if ((err = snd_opl3_hwdep_new(opl3, hw_dev, 1, NULL)) < 0) {
486 snd_card_free(card);
487 return err;
488 }
489 hw_dev++;
490 }
491
492 /* ------- ICS2115 Wavetable synth ------- */
493
494 if ((acard->wavefront.res_base = request_region(ics2115_port[dev], 16, "ICS2115")) == NULL) {
495 snd_printk("unable to grab ICS2115 i/o region 0x%lx-0x%lx\n", ics2115_port[dev], ics2115_port[dev] + 16 - 1);
496 snd_card_free(card);
497 return -EBUSY;
498 }
499 if (request_irq(ics2115_irq[dev], snd_wavefront_ics2115_interrupt, SA_INTERRUPT, "ICS2115", (void *)acard)) {
500 snd_printk("unable to use ICS2115 IRQ %d\n", ics2115_irq[dev]);
501 snd_card_free(card);
502 return -EBUSY;
503 }
504
505 acard->wavefront.irq = ics2115_irq[dev];
506 acard->wavefront.base = ics2115_port[dev];
507
508 if ((wavefront_synth = snd_wavefront_new_synth (card, hw_dev, acard)) == NULL) {
509 snd_printk ("can't create WaveFront synth device\n");
510 snd_card_free(card);
511 return -ENOMEM;
512 }
513
514 strcpy (wavefront_synth->name, "ICS2115 Wavetable MIDI Synthesizer");
515 wavefront_synth->iface = SNDRV_HWDEP_IFACE_ICS2115;
516 hw_dev++;
517
518 /* --------- Mixer ------------ */
519
520 if ((err = snd_cs4231_mixer(chip)) < 0) {
521 snd_printk ("can't allocate mixer device\n");
522 snd_card_free(card);
523 return err;
524 }
525
526 /* -------- CS4232 MPU-401 interface -------- */
527
528 if (cs4232_mpu_port[dev] > 0 && cs4232_mpu_port[dev] != SNDRV_AUTO_PORT) {
529 if ((err = snd_mpu401_uart_new(card, midi_dev, MPU401_HW_CS4232,
530 cs4232_mpu_port[dev], 0,
531 cs4232_mpu_irq[dev],
532 SA_INTERRUPT,
533 NULL)) < 0) {
534 snd_printk ("can't allocate CS4232 MPU-401 device\n");
535 snd_card_free(card);
536 return err;
537 }
538 midi_dev++;
539 }
540
541 /* ------ ICS2115 internal MIDI ------------ */
542
543 if (ics2115_port[dev] > 0 && ics2115_port[dev] != SNDRV_AUTO_PORT) {
544 ics2115_internal_rmidi =
545 snd_wavefront_new_midi (card,
546 midi_dev,
547 acard,
548 ics2115_port[dev],
549 internal_mpu);
550 if (ics2115_internal_rmidi == NULL) {
551 snd_printk ("can't setup ICS2115 internal MIDI device\n");
552 snd_card_free(card);
553 return -ENOMEM;
554 }
555 midi_dev++;
556 }
557
558 /* ------ ICS2115 external MIDI ------------ */
559
560 if (ics2115_port[dev] > 0 && ics2115_port[dev] != SNDRV_AUTO_PORT) {
561 ics2115_external_rmidi =
562 snd_wavefront_new_midi (card,
563 midi_dev,
564 acard,
565 ics2115_port[dev],
566 external_mpu);
567 if (ics2115_external_rmidi == NULL) {
568 snd_printk ("can't setup ICS2115 external MIDI device\n");
569 snd_card_free(card);
570 return -ENOMEM;
571 }
572 midi_dev++;
573 }
574
575 /* FX processor for Tropez+ */
576
577 if (acard->wavefront.has_fx) {
578 fx_processor = snd_wavefront_new_fx (card,
579 hw_dev,
580 acard,
581 ics2115_port[dev]);
582 if (fx_processor == NULL) {
583 snd_printk ("can't setup FX device\n");
584 snd_card_free(card);
585 return -ENOMEM;
586 }
587
588 hw_dev++;
589
590 strcpy(card->driver, "Tropez+");
591 strcpy(card->shortname, "Turtle Beach Tropez+");
592 } else {
593 /* Need a way to distinguish between Maui and Tropez */
594 strcpy(card->driver, "WaveFront");
595 strcpy(card->shortname, "Turtle Beach WaveFront");
596 }
597
598 /* ----- Register the card --------- */
599
600 /* Not safe to include "Turtle Beach" in longname, due to
601 length restrictions
602 */
603
604 sprintf(card->longname, "%s PCM 0x%lx irq %d dma %d",
605 card->driver,
606 chip->port,
607 cs4232_pcm_irq[dev],
608 dma1[dev]);
609
610 if (dma2[dev] >= 0 && dma2[dev] < 8)
611 sprintf(card->longname + strlen(card->longname), "&%d", dma2[dev]);
612
613 if (cs4232_mpu_port[dev] > 0 && cs4232_mpu_port[dev] != SNDRV_AUTO_PORT) {
614 sprintf (card->longname + strlen (card->longname),
615 " MPU-401 0x%lx irq %d",
616 cs4232_mpu_port[dev],
617 cs4232_mpu_irq[dev]);
618 }
619
620 sprintf (card->longname + strlen (card->longname),
621 " SYNTH 0x%lx irq %d",
622 ics2115_port[dev],
623 ics2115_irq[dev]);
624
625 if ((err = snd_card_register(card)) < 0) {
626 snd_card_free(card);
627 return err;
628 }
629 if (pcard)
630 pnp_set_card_drvdata(pcard, card);
631 else
632 snd_wavefront_legacy[dev] = card;
633 return 0;
634}
635
636#ifdef CONFIG_PNP
637
638static int __devinit snd_wavefront_pnp_detect(struct pnp_card_link *card,
639 const struct pnp_card_device_id *id)
640{
641 static int dev;
642 int res;
643
644 for ( ; dev < SNDRV_CARDS; dev++) {
645 if (!enable[dev] || !isapnp[dev])
646 continue;
647 res = snd_wavefront_probe(dev, card, id);
648 if (res < 0)
649 return res;
650 dev++;
651 return 0;
652 }
653
654 return -ENODEV;
655}
656
657static void __devexit snd_wavefront_pnp_remove(struct pnp_card_link * pcard)
658{
659 snd_card_t *card = (snd_card_t *) pnp_get_card_drvdata(pcard);
660
661 snd_card_disconnect(card);
662 snd_card_free_in_thread(card);
663}
664
665static struct pnp_card_driver wavefront_pnpc_driver = {
666 .flags = PNP_DRIVER_RES_DISABLE,
667 .name = "wavefront",
668 .id_table = snd_wavefront_pnpids,
669 .probe = snd_wavefront_pnp_detect,
670 .remove = __devexit_p(snd_wavefront_pnp_remove),
671};
672
673#endif /* CONFIG_PNP */
674
675static int __init alsa_card_wavefront_init(void)
676{
677 int cards = 0;
678 int dev;
679 for (dev = 0; dev < SNDRV_CARDS; dev++) {
680 if (!enable[dev])
681 continue;
682#ifdef CONFIG_PNP
683 if (isapnp[dev])
684 continue;
685#endif
686 if (snd_wavefront_probe(dev, NULL, NULL) >= 0)
687 cards++;
688 }
689#ifdef CONFIG_PNP
690 cards += pnp_register_card_driver(&wavefront_pnpc_driver);
691#endif
692 if (!cards) {
693#ifdef CONFIG_PNP
694 pnp_unregister_card_driver(&wavefront_pnpc_driver);
695#endif
696#ifdef MODULE
697 printk (KERN_ERR "No WaveFront cards found or devices busy\n");
698#endif
699 return -ENODEV;
700 }
701 return 0;
702}
703
704static void __exit alsa_card_wavefront_exit(void)
705{
706 int idx;
707
708#ifdef CONFIG_PNP
709 pnp_unregister_card_driver(&wavefront_pnpc_driver);
710#endif
711 for (idx = 0; idx < SNDRV_CARDS; idx++)
712 snd_card_free(snd_wavefront_legacy[idx]);
713}
714
715module_init(alsa_card_wavefront_init)
716module_exit(alsa_card_wavefront_exit)
diff --git a/sound/isa/wavefront/wavefront_fx.c b/sound/isa/wavefront/wavefront_fx.c
new file mode 100644
index 000000000000..0e13623f69f0
--- /dev/null
+++ b/sound/isa/wavefront/wavefront_fx.c
@@ -0,0 +1,1019 @@
1/*
2 * Copyright (c) 1998-2002 by Paul Davis <pbd@op.net>
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 */
18
19#include <sound/driver.h>
20#include <asm/io.h>
21#include <linux/init.h>
22#include <linux/time.h>
23#include <linux/wait.h>
24#include <sound/core.h>
25#include <sound/snd_wavefront.h>
26#include <sound/initval.h>
27
28/* Control bits for the Load Control Register
29 */
30
31#define FX_LSB_TRANSFER 0x01 /* transfer after DSP LSB byte written */
32#define FX_MSB_TRANSFER 0x02 /* transfer after DSP MSB byte written */
33#define FX_AUTO_INCR 0x04 /* auto-increment DSP address after transfer */
34
35/* weird stuff, derived from port I/O tracing with dosemu */
36
37unsigned char page_zero[] __initdata = {
380x01, 0x7c, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf5, 0x00,
390x11, 0x00, 0x20, 0x00, 0x32, 0x00, 0x40, 0x00, 0x13, 0x00, 0x00,
400x00, 0x14, 0x02, 0x76, 0x00, 0x60, 0x00, 0x80, 0x02, 0x00, 0x00,
410x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
420x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
430x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
440x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
450x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
460x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
470x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
480x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
490x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x19,
500x01, 0x1a, 0x01, 0x20, 0x01, 0x40, 0x01, 0x17, 0x00, 0x00, 0x01,
510x80, 0x01, 0x20, 0x00, 0x10, 0x01, 0xa0, 0x03, 0xd1, 0x00, 0x00,
520x01, 0xf2, 0x02, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, 0xf4, 0x02,
530xe0, 0x00, 0x15, 0x00, 0x00, 0x00, 0x16, 0x00, 0x00, 0x00, 0x17,
540x00, 0x20, 0x00, 0x00, 0x00, 0x20, 0x00, 0x50, 0x00, 0x00, 0x00,
550x40, 0x00, 0x00, 0x00, 0x71, 0x02, 0x00, 0x00, 0x60, 0x00, 0x00,
560x00, 0x92, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0xb3, 0x02,
570x00, 0x00, 0xa0, 0x00, 0x00, 0x00, 0xd4, 0x00, 0x00, 0x00, 0x40,
580x00, 0x80, 0x00, 0xf5, 0x00, 0x20, 0x00, 0x70, 0x00, 0xa0, 0x02,
590x11, 0x00, 0x16, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20,
600x02, 0x00, 0x00, 0x20, 0x00, 0x10, 0x00, 0x17, 0x00, 0x1b, 0x00,
610x1d, 0x02, 0xdf
62};
63
64unsigned char page_one[] __initdata = {
650x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x19, 0x00,
660x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xd8, 0x00, 0x00,
670x02, 0x20, 0x00, 0x19, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x01,
680xc0, 0x01, 0xfa, 0x00, 0x1a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
690x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
700x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
710x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
720x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
730x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
740x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
750x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
760x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x40, 0x02, 0x60,
770x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xc0, 0x02, 0x80, 0x00,
780x00, 0x02, 0xfb, 0x02, 0xa0, 0x00, 0x00, 0x00, 0x1b, 0x02, 0xd7,
790x00, 0x00, 0x02, 0xf7, 0x03, 0x20, 0x03, 0x00, 0x00, 0x00, 0x00,
800x1c, 0x03, 0x3c, 0x00, 0x00, 0x03, 0x3f, 0x00, 0x00, 0x03, 0xc0,
810x00, 0x00, 0x03, 0xdf, 0x00, 0x00, 0x00, 0x00, 0x03, 0x5d, 0x00,
820x00, 0x03, 0xc0, 0x00, 0x00, 0x03, 0x7d, 0x00, 0x00, 0x03, 0xc0,
830x00, 0x00, 0x03, 0x9e, 0x00, 0x00, 0x03, 0xc0, 0x00, 0x00, 0x03,
840xbe, 0x00, 0x00, 0x03, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
850x00, 0x00, 0x00, 0x1b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02,
860xdb, 0x00, 0x00, 0x02, 0xdb, 0x00, 0x00, 0x02, 0xe0, 0x00, 0x00,
870x02, 0xfb, 0x00, 0x00, 0x02, 0xc0, 0x02, 0x40, 0x02, 0xfb, 0x02,
880x60, 0x00, 0x1b
89};
90
91unsigned char page_two[] __initdata = {
920xc4, 0x00, 0x44, 0x07, 0x44, 0x00, 0x40, 0x25, 0x01, 0x06, 0xc4,
930x07, 0x40, 0x25, 0x01, 0x00, 0x46, 0x46, 0x00, 0x00, 0x00, 0x00,
940x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
950x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
960x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
970x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46, 0x07,
980x05, 0x05, 0x05, 0x04, 0x07, 0x05, 0x04, 0x07, 0x05, 0x44, 0x46,
990x44, 0x46, 0x46, 0x07, 0x05, 0x44, 0x46, 0x05, 0x46, 0x05, 0x46,
1000x05, 0x46, 0x05, 0x44, 0x46, 0x05, 0x07, 0x44, 0x46, 0x05, 0x07,
1010x44, 0x46, 0x05, 0x07, 0x44, 0x46, 0x05, 0x07, 0x44, 0x05, 0x05,
1020x05, 0x44, 0x05, 0x05, 0x05, 0x46, 0x05, 0x46, 0x05, 0x46, 0x05,
1030x46, 0x05, 0x46, 0x07, 0x46, 0x07, 0x44
104};
105
106unsigned char page_three[] __initdata = {
1070x07, 0x40, 0x00, 0x00, 0x00, 0x47, 0x00, 0x40, 0x00, 0x40, 0x06,
1080x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1090x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1100x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1110x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1120x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80,
1130xc0, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x40, 0x00, 0x40, 0x00,
1140x60, 0x00, 0x70, 0x00, 0x40, 0x00, 0x40, 0x00, 0x42, 0x00, 0x40,
1150x00, 0x02, 0x00, 0x40, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00,
1160x40, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00,
1170x00, 0x42, 0x00, 0x40, 0x00, 0x42, 0x00, 0x02, 0x00, 0x02, 0x00,
1180x02, 0x00, 0x42, 0x00, 0xc0, 0x00, 0x40
119};
120
121unsigned char page_four[] __initdata = {
1220x63, 0x03, 0x26, 0x02, 0x2c, 0x00, 0x24, 0x00, 0x2e, 0x02, 0x02,
1230x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1240x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1250x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1260x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1270x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
1280x20, 0x00, 0x60, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20,
1290x00, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x60, 0x00,
1300x20, 0x00, 0x60, 0x00, 0x20, 0x00, 0x60, 0x00, 0x20, 0x00, 0x60,
1310x00, 0x20, 0x00, 0x60, 0x00, 0x20, 0x00, 0x60, 0x00, 0x20, 0x00,
1320x20, 0x00, 0x22, 0x02, 0x22, 0x02, 0x20, 0x00, 0x60, 0x00, 0x22,
1330x02, 0x62, 0x02, 0x20, 0x01, 0x21, 0x01
134};
135
136unsigned char page_six[] __initdata = {
1370x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x04, 0x00, 0x00, 0x06, 0x00,
1380x00, 0x08, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x0e,
1390x00, 0x00, 0x10, 0x00, 0x00, 0x12, 0x00, 0x00, 0x14, 0x00, 0x00,
1400x16, 0x00, 0x00, 0x18, 0x00, 0x00, 0x1a, 0x00, 0x00, 0x1c, 0x00,
1410x00, 0x1e, 0x00, 0x00, 0x20, 0x00, 0x00, 0x22, 0x00, 0x00, 0x24,
1420x00, 0x00, 0x26, 0x00, 0x00, 0x28, 0x00, 0x00, 0x2a, 0x00, 0x00,
1430x2c, 0x00, 0x00, 0x2e, 0x00, 0x00, 0x30, 0x00, 0x00, 0x32, 0x00,
1440x00, 0x34, 0x00, 0x00, 0x36, 0x00, 0x00, 0x38, 0x00, 0x00, 0x3a,
1450x00, 0x00, 0x3c, 0x00, 0x00, 0x3e, 0x00, 0x00, 0x40, 0x00, 0x00,
1460x42, 0x03, 0x00, 0x44, 0x01, 0x00, 0x46, 0x0a, 0x21, 0x48, 0x0d,
1470x23, 0x4a, 0x23, 0x1b, 0x4c, 0x37, 0x8f, 0x4e, 0x45, 0x77, 0x50,
1480x52, 0xe2, 0x52, 0x1c, 0x92, 0x54, 0x1c, 0x52, 0x56, 0x07, 0x00,
1490x58, 0x2f, 0xc6, 0x5a, 0x0b, 0x00, 0x5c, 0x30, 0x06, 0x5e, 0x17,
1500x00, 0x60, 0x3d, 0xda, 0x62, 0x29, 0x00, 0x64, 0x3e, 0x41, 0x66,
1510x39, 0x00, 0x68, 0x4c, 0x48, 0x6a, 0x49, 0x00, 0x6c, 0x4c, 0x6c,
1520x6e, 0x11, 0xd2, 0x70, 0x16, 0x0c, 0x72, 0x00, 0x00, 0x74, 0x00,
1530x80, 0x76, 0x0f, 0x00, 0x78, 0x00, 0x80, 0x7a, 0x13, 0x00, 0x7c,
1540x80, 0x00, 0x7e, 0x80, 0x80
155};
156
157unsigned char page_seven[] __initdata = {
1580x0f, 0xff, 0x00, 0x00, 0x08, 0x00, 0x08, 0x00, 0x02, 0x00, 0x00,
1590x00, 0x00, 0x00, 0x0f, 0xff, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00,
1600x08, 0x00, 0x00, 0x00, 0x0f, 0xff, 0x00, 0x00, 0x00, 0x00, 0x0f,
1610xff, 0x0f, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1620x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1630x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1640x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1650x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1660x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1670x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1680x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1690x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1700x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1710x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0xff, 0x0f, 0xff,
1720x0f, 0xff, 0x0f, 0xff, 0x02, 0xe9, 0x06, 0x8c, 0x06, 0x8c, 0x0f,
1730xff, 0x1a, 0x75, 0x0d, 0x8b, 0x04, 0xe9, 0x0b, 0x16, 0x1a, 0x38,
1740x0d, 0xc8, 0x04, 0x6f, 0x0b, 0x91, 0x0f, 0xff, 0x06, 0x40, 0x06,
1750x40, 0x02, 0x8f, 0x0f, 0xff, 0x06, 0x62, 0x06, 0x62, 0x02, 0x7b,
1760x0f, 0xff, 0x06, 0x97, 0x06, 0x97, 0x02, 0x52, 0x0f, 0xff, 0x06,
1770xf6, 0x06, 0xf6, 0x02, 0x19, 0x05, 0x55, 0x05, 0x55, 0x05, 0x55,
1780x05, 0x55, 0x05, 0x55, 0x05, 0x55, 0x05, 0x55, 0x05, 0x55, 0x14,
1790xda, 0x0d, 0x93, 0x04, 0xda, 0x05, 0x93, 0x14, 0xda, 0x0d, 0x93,
1800x04, 0xda, 0x05, 0x93, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1810x00, 0x02, 0x00
182};
183
184unsigned char page_zero_v2[] __initdata = {
1850x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1860x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1870x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1880x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1890x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1900x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1910x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1920x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1930x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
194};
195
196unsigned char page_one_v2[] __initdata = {
1970x01, 0xc0, 0x01, 0xfa, 0x00, 0x1a, 0x00, 0x00, 0x00, 0x00, 0x00,
1980x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1990x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2000x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2010x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2020x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2030x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2040x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2050x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
206};
207
208unsigned char page_two_v2[] __initdata = {
2090x46, 0x46, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2100x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2110x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2120x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2130x00, 0x00, 0x00, 0x00
214};
215unsigned char page_three_v2[] __initdata = {
2160x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2170x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2180x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2190x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2200x00, 0x00, 0x00, 0x00
221};
222unsigned char page_four_v2[] __initdata = {
2230x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2240x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2250x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2260x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2270x00, 0x00, 0x00, 0x00
228};
229
230unsigned char page_seven_v2[] __initdata = {
2310x0f, 0xff, 0x0f, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2320x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2330x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2340x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2350x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2360x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2370x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2380x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2390x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
240};
241
242unsigned char mod_v2[] __initdata = {
2430x01, 0x00, 0x02, 0x00, 0x01, 0x01, 0x02, 0x00, 0x01, 0x02, 0x02,
2440x00, 0x01, 0x03, 0x02, 0x00, 0x01, 0x04, 0x02, 0x00, 0x01, 0x05,
2450x02, 0x00, 0x01, 0x06, 0x02, 0x00, 0x01, 0x07, 0x02, 0x00, 0xb0,
2460x20, 0xb1, 0x20, 0xb2, 0x20, 0xb3, 0x20, 0xb4, 0x20, 0xb5, 0x20,
2470xb6, 0x20, 0xb7, 0x20, 0xf0, 0x20, 0xf1, 0x20, 0xf2, 0x20, 0xf3,
2480x20, 0xf4, 0x20, 0xf5, 0x20, 0xf6, 0x20, 0xf7, 0x20, 0x10, 0xff,
2490x11, 0xff, 0x12, 0xff, 0x13, 0xff, 0x14, 0xff, 0x15, 0xff, 0x16,
2500xff, 0x17, 0xff, 0x20, 0xff, 0x21, 0xff, 0x22, 0xff, 0x23, 0xff,
2510x24, 0xff, 0x25, 0xff, 0x26, 0xff, 0x27, 0xff, 0x30, 0x00, 0x31,
2520x00, 0x32, 0x00, 0x33, 0x00, 0x34, 0x00, 0x35, 0x00, 0x36, 0x00,
2530x37, 0x00, 0x40, 0x00, 0x41, 0x00, 0x42, 0x00, 0x43, 0x00, 0x44,
2540x00, 0x45, 0x00, 0x46, 0x00, 0x47, 0x00, 0x50, 0x00, 0x51, 0x00,
2550x52, 0x00, 0x53, 0x00, 0x54, 0x00, 0x55, 0x00, 0x56, 0x00, 0x57,
2560x00, 0x60, 0x00, 0x61, 0x00, 0x62, 0x00, 0x63, 0x00, 0x64, 0x00,
2570x65, 0x00, 0x66, 0x00, 0x67, 0x00, 0x70, 0xc0, 0x71, 0xc0, 0x72,
2580xc0, 0x73, 0xc0, 0x74, 0xc0, 0x75, 0xc0, 0x76, 0xc0, 0x77, 0xc0,
2590x80, 0x00, 0x81, 0x00, 0x82, 0x00, 0x83, 0x00, 0x84, 0x00, 0x85,
2600x00, 0x86, 0x00, 0x87, 0x00, 0x90, 0x00, 0x91, 0x00, 0x92, 0x00,
2610x93, 0x00, 0x94, 0x00, 0x95, 0x00, 0x96, 0x00, 0x97, 0x00, 0xa0,
2620x00, 0xa1, 0x00, 0xa2, 0x00, 0xa3, 0x00, 0xa4, 0x00, 0xa5, 0x00,
2630xa6, 0x00, 0xa7, 0x00, 0xc0, 0x00, 0xc1, 0x00, 0xc2, 0x00, 0xc3,
2640x00, 0xc4, 0x00, 0xc5, 0x00, 0xc6, 0x00, 0xc7, 0x00, 0xd0, 0x00,
2650xd1, 0x00, 0xd2, 0x00, 0xd3, 0x00, 0xd4, 0x00, 0xd5, 0x00, 0xd6,
2660x00, 0xd7, 0x00, 0xe0, 0x00, 0xe1, 0x00, 0xe2, 0x00, 0xe3, 0x00,
2670xe4, 0x00, 0xe5, 0x00, 0xe6, 0x00, 0xe7, 0x00, 0x01, 0x00, 0x02,
2680x01, 0x01, 0x01, 0x02, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x03,
2690x02, 0x01, 0x01, 0x04, 0x02, 0x01, 0x01, 0x05, 0x02, 0x01, 0x01,
2700x06, 0x02, 0x01, 0x01, 0x07, 0x02, 0x01
271};
272unsigned char coefficients[] __initdata = {
2730x07, 0x46, 0x00, 0x00, 0x07, 0x49, 0x00, 0x00, 0x00, 0x4b, 0x03,
2740x11, 0x00, 0x4d, 0x01, 0x32, 0x07, 0x46, 0x00, 0x00, 0x07, 0x49,
2750x00, 0x00, 0x07, 0x40, 0x00, 0x00, 0x07, 0x41, 0x00, 0x00, 0x01,
2760x40, 0x02, 0x40, 0x01, 0x41, 0x02, 0x60, 0x07, 0x40, 0x00, 0x00,
2770x07, 0x41, 0x00, 0x00, 0x07, 0x47, 0x00, 0x00, 0x07, 0x4a, 0x00,
2780x00, 0x00, 0x47, 0x01, 0x00, 0x00, 0x4a, 0x01, 0x20, 0x07, 0x47,
2790x00, 0x00, 0x07, 0x4a, 0x00, 0x00, 0x07, 0x7c, 0x00, 0x00, 0x07,
2800x7e, 0x00, 0x00, 0x00, 0x00, 0x01, 0x1c, 0x07, 0x7c, 0x00, 0x00,
2810x07, 0x7e, 0x00, 0x00, 0x07, 0x44, 0x00, 0x00, 0x00, 0x44, 0x01,
2820x00, 0x07, 0x44, 0x00, 0x00, 0x07, 0x42, 0x00, 0x00, 0x07, 0x43,
2830x00, 0x00, 0x00, 0x42, 0x01, 0x1a, 0x00, 0x43, 0x01, 0x20, 0x07,
2840x42, 0x00, 0x00, 0x07, 0x43, 0x00, 0x00, 0x07, 0x40, 0x00, 0x00,
2850x07, 0x41, 0x00, 0x00, 0x01, 0x40, 0x02, 0x40, 0x01, 0x41, 0x02,
2860x60, 0x07, 0x40, 0x00, 0x00, 0x07, 0x41, 0x00, 0x00, 0x07, 0x44,
2870x0f, 0xff, 0x07, 0x42, 0x00, 0x00, 0x07, 0x43, 0x00, 0x00, 0x07,
2880x40, 0x00, 0x00, 0x07, 0x41, 0x00, 0x00, 0x07, 0x51, 0x06, 0x40,
2890x07, 0x50, 0x06, 0x40, 0x07, 0x4f, 0x03, 0x81, 0x07, 0x53, 0x1a,
2900x76, 0x07, 0x54, 0x0d, 0x8b, 0x07, 0x55, 0x04, 0xe9, 0x07, 0x56,
2910x0b, 0x17, 0x07, 0x57, 0x1a, 0x38, 0x07, 0x58, 0x0d, 0xc9, 0x07,
2920x59, 0x04, 0x6f, 0x07, 0x5a, 0x0b, 0x91, 0x07, 0x73, 0x14, 0xda,
2930x07, 0x74, 0x0d, 0x93, 0x07, 0x75, 0x04, 0xd9, 0x07, 0x76, 0x05,
2940x93, 0x07, 0x77, 0x14, 0xda, 0x07, 0x78, 0x0d, 0x93, 0x07, 0x79,
2950x04, 0xd9, 0x07, 0x7a, 0x05, 0x93, 0x07, 0x5e, 0x03, 0x68, 0x07,
2960x5c, 0x04, 0x31, 0x07, 0x5d, 0x04, 0x31, 0x07, 0x62, 0x03, 0x52,
2970x07, 0x60, 0x04, 0x76, 0x07, 0x61, 0x04, 0x76, 0x07, 0x66, 0x03,
2980x2e, 0x07, 0x64, 0x04, 0xda, 0x07, 0x65, 0x04, 0xda, 0x07, 0x6a,
2990x02, 0xf6, 0x07, 0x68, 0x05, 0x62, 0x07, 0x69, 0x05, 0x62, 0x06,
3000x46, 0x0a, 0x22, 0x06, 0x48, 0x0d, 0x24, 0x06, 0x6e, 0x11, 0xd3,
3010x06, 0x70, 0x15, 0xcb, 0x06, 0x52, 0x20, 0x93, 0x06, 0x54, 0x20,
3020x54, 0x06, 0x4a, 0x27, 0x1d, 0x06, 0x58, 0x2f, 0xc8, 0x06, 0x5c,
3030x30, 0x07, 0x06, 0x4c, 0x37, 0x90, 0x06, 0x60, 0x3d, 0xdb, 0x06,
3040x64, 0x3e, 0x42, 0x06, 0x4e, 0x45, 0x78, 0x06, 0x68, 0x4c, 0x48,
3050x06, 0x6c, 0x4c, 0x6c, 0x06, 0x50, 0x52, 0xe2, 0x06, 0x42, 0x02,
3060xba
307};
308unsigned char coefficients2[] __initdata = {
3090x07, 0x46, 0x00, 0x00, 0x07, 0x49, 0x00, 0x00, 0x07, 0x45, 0x0f,
3100xff, 0x07, 0x48, 0x0f, 0xff, 0x07, 0x7b, 0x04, 0xcc, 0x07, 0x7d,
3110x04, 0xcc, 0x07, 0x7c, 0x00, 0x00, 0x07, 0x7e, 0x00, 0x00, 0x07,
3120x46, 0x00, 0x00, 0x07, 0x49, 0x00, 0x00, 0x07, 0x47, 0x00, 0x00,
3130x07, 0x4a, 0x00, 0x00, 0x07, 0x4c, 0x00, 0x00, 0x07, 0x4e, 0x00, 0x00
314};
315unsigned char coefficients3[] __initdata = {
3160x00, 0x00, 0x00, 0x00, 0x00, 0x28, 0x00, 0x28, 0x00, 0x51, 0x00,
3170x51, 0x00, 0x7a, 0x00, 0x7a, 0x00, 0xa3, 0x00, 0xa3, 0x00, 0xcc,
3180x00, 0xcc, 0x00, 0xf5, 0x00, 0xf5, 0x01, 0x1e, 0x01, 0x1e, 0x01,
3190x47, 0x01, 0x47, 0x01, 0x70, 0x01, 0x70, 0x01, 0x99, 0x01, 0x99,
3200x01, 0xc2, 0x01, 0xc2, 0x01, 0xeb, 0x01, 0xeb, 0x02, 0x14, 0x02,
3210x14, 0x02, 0x3d, 0x02, 0x3d, 0x02, 0x66, 0x02, 0x66, 0x02, 0x8f,
3220x02, 0x8f, 0x02, 0xb8, 0x02, 0xb8, 0x02, 0xe1, 0x02, 0xe1, 0x03,
3230x0a, 0x03, 0x0a, 0x03, 0x33, 0x03, 0x33, 0x03, 0x5c, 0x03, 0x5c,
3240x03, 0x85, 0x03, 0x85, 0x03, 0xae, 0x03, 0xae, 0x03, 0xd7, 0x03,
3250xd7, 0x04, 0x00, 0x04, 0x00, 0x04, 0x28, 0x04, 0x28, 0x04, 0x51,
3260x04, 0x51, 0x04, 0x7a, 0x04, 0x7a, 0x04, 0xa3, 0x04, 0xa3, 0x04,
3270xcc, 0x04, 0xcc, 0x04, 0xf5, 0x04, 0xf5, 0x05, 0x1e, 0x05, 0x1e,
3280x05, 0x47, 0x05, 0x47, 0x05, 0x70, 0x05, 0x70, 0x05, 0x99, 0x05,
3290x99, 0x05, 0xc2, 0x05, 0xc2, 0x05, 0xeb, 0x05, 0xeb, 0x06, 0x14,
3300x06, 0x14, 0x06, 0x3d, 0x06, 0x3d, 0x06, 0x66, 0x06, 0x66, 0x06,
3310x8f, 0x06, 0x8f, 0x06, 0xb8, 0x06, 0xb8, 0x06, 0xe1, 0x06, 0xe1,
3320x07, 0x0a, 0x07, 0x0a, 0x07, 0x33, 0x07, 0x33, 0x07, 0x5c, 0x07,
3330x5c, 0x07, 0x85, 0x07, 0x85, 0x07, 0xae, 0x07, 0xae, 0x07, 0xd7,
3340x07, 0xd7, 0x08, 0x00, 0x08, 0x00, 0x08, 0x28, 0x08, 0x28, 0x08,
3350x51, 0x08, 0x51, 0x08, 0x7a, 0x08, 0x7a, 0x08, 0xa3, 0x08, 0xa3,
3360x08, 0xcc, 0x08, 0xcc, 0x08, 0xf5, 0x08, 0xf5, 0x09, 0x1e, 0x09,
3370x1e, 0x09, 0x47, 0x09, 0x47, 0x09, 0x70, 0x09, 0x70, 0x09, 0x99,
3380x09, 0x99, 0x09, 0xc2, 0x09, 0xc2, 0x09, 0xeb, 0x09, 0xeb, 0x0a,
3390x14, 0x0a, 0x14, 0x0a, 0x3d, 0x0a, 0x3d, 0x0a, 0x66, 0x0a, 0x66,
3400x0a, 0x8f, 0x0a, 0x8f, 0x0a, 0xb8, 0x0a, 0xb8, 0x0a, 0xe1, 0x0a,
3410xe1, 0x0b, 0x0a, 0x0b, 0x0a, 0x0b, 0x33, 0x0b, 0x33, 0x0b, 0x5c,
3420x0b, 0x5c, 0x0b, 0x85, 0x0b, 0x85, 0x0b, 0xae, 0x0b, 0xae, 0x0b,
3430xd7, 0x0b, 0xd7, 0x0c, 0x00, 0x0c, 0x00, 0x0c, 0x28, 0x0c, 0x28,
3440x0c, 0x51, 0x0c, 0x51, 0x0c, 0x7a, 0x0c, 0x7a, 0x0c, 0xa3, 0x0c,
3450xa3, 0x0c, 0xcc, 0x0c, 0xcc, 0x0c, 0xf5, 0x0c, 0xf5, 0x0d, 0x1e,
3460x0d, 0x1e, 0x0d, 0x47, 0x0d, 0x47, 0x0d, 0x70, 0x0d, 0x70, 0x0d,
3470x99, 0x0d, 0x99, 0x0d, 0xc2, 0x0d, 0xc2, 0x0d, 0xeb, 0x0d, 0xeb,
3480x0e, 0x14, 0x0e, 0x14, 0x0e, 0x3d, 0x0e, 0x3d, 0x0e, 0x66, 0x0e,
3490x66, 0x0e, 0x8f, 0x0e, 0x8f, 0x0e, 0xb8, 0x0e, 0xb8, 0x0e, 0xe1,
3500x0e, 0xe1, 0x0f, 0x0a, 0x0f, 0x0a, 0x0f, 0x33, 0x0f, 0x33, 0x0f,
3510x5c, 0x0f, 0x5c, 0x0f, 0x85, 0x0f, 0x85, 0x0f, 0xae, 0x0f, 0xae,
3520x0f, 0xd7, 0x0f, 0xd7, 0x0f, 0xff, 0x0f, 0xff
353};
354
355static int
356wavefront_fx_idle (snd_wavefront_t *dev)
357
358{
359 int i;
360 unsigned int x = 0x80;
361
362 for (i = 0; i < 1000; i++) {
363 x = inb (dev->fx_status);
364 if ((x & 0x80) == 0) {
365 break;
366 }
367 }
368
369 if (x & 0x80) {
370 snd_printk ("FX device never idle.\n");
371 return 0;
372 }
373
374 return (1);
375}
376
377static void
378wavefront_fx_mute (snd_wavefront_t *dev, int onoff)
379
380{
381 if (!wavefront_fx_idle(dev)) {
382 return;
383 }
384
385 outb (onoff ? 0x02 : 0x00, dev->fx_op);
386}
387
388static int
389wavefront_fx_memset (snd_wavefront_t *dev,
390 int page,
391 int addr,
392 int cnt,
393 unsigned short *data)
394{
395 if (page < 0 || page > 7) {
396 snd_printk ("FX memset: "
397 "page must be >= 0 and <= 7\n");
398 return -(EINVAL);
399 }
400
401 if (addr < 0 || addr > 0x7f) {
402 snd_printk ("FX memset: "
403 "addr must be >= 0 and <= 7f\n");
404 return -(EINVAL);
405 }
406
407 if (cnt == 1) {
408
409 outb (FX_LSB_TRANSFER, dev->fx_lcr);
410 outb (page, dev->fx_dsp_page);
411 outb (addr, dev->fx_dsp_addr);
412 outb ((data[0] >> 8), dev->fx_dsp_msb);
413 outb ((data[0] & 0xff), dev->fx_dsp_lsb);
414
415 snd_printk ("FX: addr %d:%x set to 0x%x\n",
416 page, addr, data[0]);
417
418 } else {
419 int i;
420
421 outb (FX_AUTO_INCR|FX_LSB_TRANSFER, dev->fx_lcr);
422 outb (page, dev->fx_dsp_page);
423 outb (addr, dev->fx_dsp_addr);
424
425 for (i = 0; i < cnt; i++) {
426 outb ((data[i] >> 8), dev->fx_dsp_msb);
427 outb ((data[i] & 0xff), dev->fx_dsp_lsb);
428 if (!wavefront_fx_idle (dev)) {
429 break;
430 }
431 }
432
433 if (i != cnt) {
434 snd_printk ("FX memset "
435 "(0x%x, 0x%x, 0x%lx, %d) incomplete\n",
436 page, addr, (unsigned long) data, cnt);
437 return -(EIO);
438 }
439 }
440
441 return 0;
442}
443
444int
445snd_wavefront_fx_detect (snd_wavefront_t *dev)
446
447{
448 /* This is a crude check, but its the best one I have for now.
449 Certainly on the Maui and the Tropez, wavefront_fx_idle() will
450 report "never idle", which suggests that this test should
451 work OK.
452 */
453
454 if (inb (dev->fx_status) & 0x80) {
455 snd_printk ("Hmm, probably a Maui or Tropez.\n");
456 return -1;
457 }
458
459 return 0;
460}
461
462int
463snd_wavefront_fx_open (snd_hwdep_t *hw, struct file *file)
464
465{
466 if (!try_module_get(hw->card->module))
467 return -EFAULT;
468 file->private_data = hw;
469 return 0;
470}
471
472int
473snd_wavefront_fx_release (snd_hwdep_t *hw, struct file *file)
474
475{
476 module_put(hw->card->module);
477 return 0;
478}
479
480int
481snd_wavefront_fx_ioctl (snd_hwdep_t *sdev, struct file *file,
482 unsigned int cmd, unsigned long arg)
483
484{
485 snd_card_t *card;
486 snd_wavefront_card_t *acard;
487 snd_wavefront_t *dev;
488 wavefront_fx_info r;
489 unsigned short *page_data = NULL;
490 unsigned short *pd;
491 int err = 0;
492
493 snd_assert(sdev->card != NULL, return -ENODEV);
494
495 card = sdev->card;
496
497 snd_assert(card->private_data != NULL, return -ENODEV);
498
499 acard = card->private_data;
500 dev = &acard->wavefront;
501
502 if (copy_from_user (&r, (void __user *)arg, sizeof (wavefront_fx_info)))
503 return -EFAULT;
504
505 switch (r.request) {
506 case WFFX_MUTE:
507 wavefront_fx_mute (dev, r.data[0]);
508 return -EIO;
509
510 case WFFX_MEMSET:
511 if (r.data[2] <= 0) {
512 snd_printk ("cannot write "
513 "<= 0 bytes to FX\n");
514 return -EIO;
515 } else if (r.data[2] == 1) {
516 pd = (unsigned short *) &r.data[3];
517 } else {
518 if (r.data[2] > 256) {
519 snd_printk ("cannot write "
520 "> 512 bytes to FX\n");
521 return -EIO;
522 }
523 page_data = kmalloc(r.data[2] * sizeof(short), GFP_KERNEL);
524 if (!page_data)
525 return -ENOMEM;
526 if (copy_from_user (page_data,
527 (unsigned char __user *) r.data[3],
528 r.data[2] * sizeof(short))) {
529 kfree(page_data);
530 return -EFAULT;
531 }
532 pd = page_data;
533 }
534
535 err = wavefront_fx_memset (dev,
536 r.data[0], /* page */
537 r.data[1], /* addr */
538 r.data[2], /* cnt */
539 pd);
540 kfree(page_data);
541 break;
542
543 default:
544 snd_printk ("FX: ioctl %d not yet supported\n",
545 r.request);
546 return -ENOTTY;
547 }
548 return err;
549}
550
551/* YSS225 initialization.
552
553 This code was developed using DOSEMU. The Turtle Beach SETUPSND
554 utility was run with I/O tracing in DOSEMU enabled, and a reconstruction
555 of the port I/O done, using the Yamaha faxback document as a guide
556 to add more logic to the code. Its really pretty weird.
557
558 There was an alternative approach of just dumping the whole I/O
559 sequence as a series of port/value pairs and a simple loop
560 that output it. However, I hope that eventually I'll get more
561 control over what this code does, and so I tried to stick with
562 a somewhat "algorithmic" approach.
563*/
564
565
566int __init
567snd_wavefront_fx_start (snd_wavefront_t *dev)
568
569{
570 unsigned int i, j;
571
572 /* Set all bits for all channels on the MOD unit to zero */
573 /* XXX But why do this twice ? */
574
575 for (j = 0; j < 2; j++) {
576 for (i = 0x10; i <= 0xff; i++) {
577
578 if (!wavefront_fx_idle (dev)) {
579 return (-1);
580 }
581
582 outb (i, dev->fx_mod_addr);
583 outb (0x0, dev->fx_mod_data);
584 }
585 }
586
587 if (!wavefront_fx_idle (dev)) return (-1);
588 outb (0x02, dev->fx_op); /* mute on */
589
590 if (!wavefront_fx_idle (dev)) return (-1);
591 outb (0x07, dev->fx_dsp_page);
592 outb (0x44, dev->fx_dsp_addr);
593 outb (0x00, dev->fx_dsp_msb);
594 outb (0x00, dev->fx_dsp_lsb);
595 if (!wavefront_fx_idle (dev)) return (-1);
596 outb (0x07, dev->fx_dsp_page);
597 outb (0x42, dev->fx_dsp_addr);
598 outb (0x00, dev->fx_dsp_msb);
599 outb (0x00, dev->fx_dsp_lsb);
600 if (!wavefront_fx_idle (dev)) return (-1);
601 outb (0x07, dev->fx_dsp_page);
602 outb (0x43, dev->fx_dsp_addr);
603 outb (0x00, dev->fx_dsp_msb);
604 outb (0x00, dev->fx_dsp_lsb);
605 if (!wavefront_fx_idle (dev)) return (-1);
606 outb (0x07, dev->fx_dsp_page);
607 outb (0x7c, dev->fx_dsp_addr);
608 outb (0x00, dev->fx_dsp_msb);
609 outb (0x00, dev->fx_dsp_lsb);
610 if (!wavefront_fx_idle (dev)) return (-1);
611 outb (0x07, dev->fx_dsp_page);
612 outb (0x7e, dev->fx_dsp_addr);
613 outb (0x00, dev->fx_dsp_msb);
614 outb (0x00, dev->fx_dsp_lsb);
615 if (!wavefront_fx_idle (dev)) return (-1);
616 outb (0x07, dev->fx_dsp_page);
617 outb (0x46, dev->fx_dsp_addr);
618 outb (0x00, dev->fx_dsp_msb);
619 outb (0x00, dev->fx_dsp_lsb);
620 if (!wavefront_fx_idle (dev)) return (-1);
621 outb (0x07, dev->fx_dsp_page);
622 outb (0x49, dev->fx_dsp_addr);
623 outb (0x00, dev->fx_dsp_msb);
624 outb (0x00, dev->fx_dsp_lsb);
625 if (!wavefront_fx_idle (dev)) return (-1);
626 outb (0x07, dev->fx_dsp_page);
627 outb (0x47, dev->fx_dsp_addr);
628 outb (0x00, dev->fx_dsp_msb);
629 outb (0x00, dev->fx_dsp_lsb);
630 if (!wavefront_fx_idle (dev)) return (-1);
631 outb (0x07, dev->fx_dsp_page);
632 outb (0x4a, dev->fx_dsp_addr);
633 outb (0x00, dev->fx_dsp_msb);
634 outb (0x00, dev->fx_dsp_lsb);
635
636 /* either because of stupidity by TB's programmers, or because it
637 actually does something, rezero the MOD page.
638 */
639 for (i = 0x10; i <= 0xff; i++) {
640
641 if (!wavefront_fx_idle (dev)) {
642 return (-1);
643 }
644
645 outb (i, dev->fx_mod_addr);
646 outb (0x0, dev->fx_mod_data);
647 }
648 /* load page zero */
649
650 outb (FX_AUTO_INCR|FX_LSB_TRANSFER, dev->fx_lcr);
651 outb (0x00, dev->fx_dsp_page);
652 outb (0x00, dev->fx_dsp_addr);
653
654 for (i = 0; i < sizeof (page_zero); i += 2) {
655 outb (page_zero[i], dev->fx_dsp_msb);
656 outb (page_zero[i+1], dev->fx_dsp_lsb);
657 if (!wavefront_fx_idle (dev)) return (-1);
658 }
659
660 /* Now load page one */
661
662 outb (FX_AUTO_INCR|FX_LSB_TRANSFER, dev->fx_lcr);
663 outb (0x01, dev->fx_dsp_page);
664 outb (0x00, dev->fx_dsp_addr);
665
666 for (i = 0; i < sizeof (page_one); i += 2) {
667 outb (page_one[i], dev->fx_dsp_msb);
668 outb (page_one[i+1], dev->fx_dsp_lsb);
669 if (!wavefront_fx_idle (dev)) return (-1);
670 }
671
672 outb (FX_AUTO_INCR|FX_LSB_TRANSFER, dev->fx_lcr);
673 outb (0x02, dev->fx_dsp_page);
674 outb (0x00, dev->fx_dsp_addr);
675
676 for (i = 0; i < sizeof (page_two); i++) {
677 outb (page_two[i], dev->fx_dsp_lsb);
678 if (!wavefront_fx_idle (dev)) return (-1);
679 }
680
681 outb (FX_AUTO_INCR|FX_LSB_TRANSFER, dev->fx_lcr);
682 outb (0x03, dev->fx_dsp_page);
683 outb (0x00, dev->fx_dsp_addr);
684
685 for (i = 0; i < sizeof (page_three); i++) {
686 outb (page_three[i], dev->fx_dsp_lsb);
687 if (!wavefront_fx_idle (dev)) return (-1);
688 }
689
690 outb (FX_AUTO_INCR|FX_LSB_TRANSFER, dev->fx_lcr);
691 outb (0x04, dev->fx_dsp_page);
692 outb (0x00, dev->fx_dsp_addr);
693
694 for (i = 0; i < sizeof (page_four); i++) {
695 outb (page_four[i], dev->fx_dsp_lsb);
696 if (!wavefront_fx_idle (dev)) return (-1);
697 }
698
699 /* Load memory area (page six) */
700
701 outb (FX_LSB_TRANSFER, dev->fx_lcr);
702 outb (0x06, dev->fx_dsp_page);
703
704 for (i = 0; i < sizeof (page_six); i += 3) {
705 outb (page_six[i], dev->fx_dsp_addr);
706 outb (page_six[i+1], dev->fx_dsp_msb);
707 outb (page_six[i+2], dev->fx_dsp_lsb);
708 if (!wavefront_fx_idle (dev)) return (-1);
709 }
710
711 outb (FX_AUTO_INCR|FX_LSB_TRANSFER, dev->fx_lcr);
712 outb (0x07, dev->fx_dsp_page);
713 outb (0x00, dev->fx_dsp_addr);
714
715 for (i = 0; i < sizeof (page_seven); i += 2) {
716 outb (page_seven[i], dev->fx_dsp_msb);
717 outb (page_seven[i+1], dev->fx_dsp_lsb);
718 if (!wavefront_fx_idle (dev)) return (-1);
719 }
720
721 /* Now setup the MOD area. We do this algorithmically in order to
722 save a little data space. It could be done in the same fashion
723 as the "pages".
724 */
725
726 for (i = 0x00; i <= 0x0f; i++) {
727 outb (0x01, dev->fx_mod_addr);
728 outb (i, dev->fx_mod_data);
729 if (!wavefront_fx_idle (dev)) return (-1);
730 outb (0x02, dev->fx_mod_addr);
731 outb (0x00, dev->fx_mod_data);
732 if (!wavefront_fx_idle (dev)) return (-1);
733 }
734
735 for (i = 0xb0; i <= 0xbf; i++) {
736 outb (i, dev->fx_mod_addr);
737 outb (0x20, dev->fx_mod_data);
738 if (!wavefront_fx_idle (dev)) return (-1);
739 }
740
741 for (i = 0xf0; i <= 0xff; i++) {
742 outb (i, dev->fx_mod_addr);
743 outb (0x20, dev->fx_mod_data);
744 if (!wavefront_fx_idle (dev)) return (-1);
745 }
746
747 for (i = 0x10; i <= 0x1d; i++) {
748 outb (i, dev->fx_mod_addr);
749 outb (0xff, dev->fx_mod_data);
750 if (!wavefront_fx_idle (dev)) return (-1);
751 }
752
753 outb (0x1e, dev->fx_mod_addr);
754 outb (0x40, dev->fx_mod_data);
755 if (!wavefront_fx_idle (dev)) return (-1);
756
757 for (i = 0x1f; i <= 0x2d; i++) {
758 outb (i, dev->fx_mod_addr);
759 outb (0xff, dev->fx_mod_data);
760 if (!wavefront_fx_idle (dev)) return (-1);
761 }
762
763 outb (0x2e, dev->fx_mod_addr);
764 outb (0x00, dev->fx_mod_data);
765 if (!wavefront_fx_idle (dev)) return (-1);
766
767 for (i = 0x2f; i <= 0x3e; i++) {
768 outb (i, dev->fx_mod_addr);
769 outb (0x00, dev->fx_mod_data);
770 if (!wavefront_fx_idle (dev)) return (-1);
771 }
772
773 outb (0x3f, dev->fx_mod_addr);
774 outb (0x20, dev->fx_mod_data);
775 if (!wavefront_fx_idle (dev)) return (-1);
776
777 for (i = 0x40; i <= 0x4d; i++) {
778 outb (i, dev->fx_mod_addr);
779 outb (0x00, dev->fx_mod_data);
780 if (!wavefront_fx_idle (dev)) return (-1);
781 }
782
783 outb (0x4e, dev->fx_mod_addr);
784 outb (0x0e, dev->fx_mod_data);
785 if (!wavefront_fx_idle (dev)) return (-1);
786 outb (0x4f, dev->fx_mod_addr);
787 outb (0x0e, dev->fx_mod_data);
788 if (!wavefront_fx_idle (dev)) return (-1);
789
790
791 for (i = 0x50; i <= 0x6b; i++) {
792 outb (i, dev->fx_mod_addr);
793 outb (0x00, dev->fx_mod_data);
794 if (!wavefront_fx_idle (dev)) return (-1);
795 }
796
797 outb (0x6c, dev->fx_mod_addr);
798 outb (0x40, dev->fx_mod_data);
799 if (!wavefront_fx_idle (dev)) return (-1);
800
801 outb (0x6d, dev->fx_mod_addr);
802 outb (0x00, dev->fx_mod_data);
803 if (!wavefront_fx_idle (dev)) return (-1);
804
805 outb (0x6e, dev->fx_mod_addr);
806 outb (0x40, dev->fx_mod_data);
807 if (!wavefront_fx_idle (dev)) return (-1);
808
809 outb (0x6f, dev->fx_mod_addr);
810 outb (0x40, dev->fx_mod_data);
811 if (!wavefront_fx_idle (dev)) return (-1);
812
813 for (i = 0x70; i <= 0x7f; i++) {
814 outb (i, dev->fx_mod_addr);
815 outb (0xc0, dev->fx_mod_data);
816 if (!wavefront_fx_idle (dev)) return (-1);
817 }
818
819 for (i = 0x80; i <= 0xaf; i++) {
820 outb (i, dev->fx_mod_addr);
821 outb (0x00, dev->fx_mod_data);
822 if (!wavefront_fx_idle (dev)) return (-1);
823 }
824
825 for (i = 0xc0; i <= 0xdd; i++) {
826 outb (i, dev->fx_mod_addr);
827 outb (0x00, dev->fx_mod_data);
828 if (!wavefront_fx_idle (dev)) return (-1);
829 }
830
831 outb (0xde, dev->fx_mod_addr);
832 outb (0x10, dev->fx_mod_data);
833 if (!wavefront_fx_idle (dev)) return (-1);
834 outb (0xdf, dev->fx_mod_addr);
835 outb (0x10, dev->fx_mod_data);
836 if (!wavefront_fx_idle (dev)) return (-1);
837
838 for (i = 0xe0; i <= 0xef; i++) {
839 outb (i, dev->fx_mod_addr);
840 outb (0x00, dev->fx_mod_data);
841 if (!wavefront_fx_idle (dev)) return (-1);
842 }
843
844 for (i = 0x00; i <= 0x0f; i++) {
845 outb (0x01, dev->fx_mod_addr);
846 outb (i, dev->fx_mod_data);
847 outb (0x02, dev->fx_mod_addr);
848 outb (0x01, dev->fx_mod_data);
849 if (!wavefront_fx_idle (dev)) return (-1);
850 }
851
852 outb (0x02, dev->fx_op); /* mute on */
853
854 /* Now set the coefficients and so forth for the programs above */
855
856 for (i = 0; i < sizeof (coefficients); i += 4) {
857 outb (coefficients[i], dev->fx_dsp_page);
858 outb (coefficients[i+1], dev->fx_dsp_addr);
859 outb (coefficients[i+2], dev->fx_dsp_msb);
860 outb (coefficients[i+3], dev->fx_dsp_lsb);
861 if (!wavefront_fx_idle (dev)) return (-1);
862 }
863
864 /* Some settings (?) that are too small to bundle into loops */
865
866 if (!wavefront_fx_idle (dev)) return (-1);
867 outb (0x1e, dev->fx_mod_addr);
868 outb (0x14, dev->fx_mod_data);
869 if (!wavefront_fx_idle (dev)) return (-1);
870 outb (0xde, dev->fx_mod_addr);
871 outb (0x20, dev->fx_mod_data);
872 if (!wavefront_fx_idle (dev)) return (-1);
873 outb (0xdf, dev->fx_mod_addr);
874 outb (0x20, dev->fx_mod_data);
875
876 /* some more coefficients */
877
878 if (!wavefront_fx_idle (dev)) return (-1);
879 outb (0x06, dev->fx_dsp_page);
880 outb (0x78, dev->fx_dsp_addr);
881 outb (0x00, dev->fx_dsp_msb);
882 outb (0x40, dev->fx_dsp_lsb);
883 if (!wavefront_fx_idle (dev)) return (-1);
884 outb (0x07, dev->fx_dsp_page);
885 outb (0x03, dev->fx_dsp_addr);
886 outb (0x0f, dev->fx_dsp_msb);
887 outb (0xff, dev->fx_dsp_lsb);
888 if (!wavefront_fx_idle (dev)) return (-1);
889 outb (0x07, dev->fx_dsp_page);
890 outb (0x0b, dev->fx_dsp_addr);
891 outb (0x0f, dev->fx_dsp_msb);
892 outb (0xff, dev->fx_dsp_lsb);
893 if (!wavefront_fx_idle (dev)) return (-1);
894 outb (0x07, dev->fx_dsp_page);
895 outb (0x02, dev->fx_dsp_addr);
896 outb (0x00, dev->fx_dsp_msb);
897 outb (0x00, dev->fx_dsp_lsb);
898 if (!wavefront_fx_idle (dev)) return (-1);
899 outb (0x07, dev->fx_dsp_page);
900 outb (0x0a, dev->fx_dsp_addr);
901 outb (0x00, dev->fx_dsp_msb);
902 outb (0x00, dev->fx_dsp_lsb);
903 if (!wavefront_fx_idle (dev)) return (-1);
904 outb (0x07, dev->fx_dsp_page);
905 outb (0x46, dev->fx_dsp_addr);
906 outb (0x00, dev->fx_dsp_msb);
907 outb (0x00, dev->fx_dsp_lsb);
908 if (!wavefront_fx_idle (dev)) return (-1);
909 outb (0x07, dev->fx_dsp_page);
910 outb (0x49, dev->fx_dsp_addr);
911 outb (0x00, dev->fx_dsp_msb);
912 outb (0x00, dev->fx_dsp_lsb);
913
914 /* Now, for some strange reason, lets reload every page
915 and all the coefficients over again. I have *NO* idea
916 why this is done. I do know that no sound is produced
917 is this phase is omitted.
918 */
919
920 outb (FX_AUTO_INCR|FX_LSB_TRANSFER, dev->fx_lcr);
921 outb (0x00, dev->fx_dsp_page);
922 outb (0x10, dev->fx_dsp_addr);
923
924 for (i = 0; i < sizeof (page_zero_v2); i += 2) {
925 outb (page_zero_v2[i], dev->fx_dsp_msb);
926 outb (page_zero_v2[i+1], dev->fx_dsp_lsb);
927 if (!wavefront_fx_idle (dev)) return (-1);
928 }
929
930 outb (FX_AUTO_INCR|FX_LSB_TRANSFER, dev->fx_lcr);
931 outb (0x01, dev->fx_dsp_page);
932 outb (0x10, dev->fx_dsp_addr);
933
934 for (i = 0; i < sizeof (page_one_v2); i += 2) {
935 outb (page_one_v2[i], dev->fx_dsp_msb);
936 outb (page_one_v2[i+1], dev->fx_dsp_lsb);
937 if (!wavefront_fx_idle (dev)) return (-1);
938 }
939
940 if (!wavefront_fx_idle (dev)) return (-1);
941 if (!wavefront_fx_idle (dev)) return (-1);
942
943 outb (FX_AUTO_INCR|FX_LSB_TRANSFER, dev->fx_lcr);
944 outb (0x02, dev->fx_dsp_page);
945 outb (0x10, dev->fx_dsp_addr);
946
947 for (i = 0; i < sizeof (page_two_v2); i++) {
948 outb (page_two_v2[i], dev->fx_dsp_lsb);
949 if (!wavefront_fx_idle (dev)) return (-1);
950 }
951 outb (FX_AUTO_INCR|FX_LSB_TRANSFER, dev->fx_lcr);
952 outb (0x03, dev->fx_dsp_page);
953 outb (0x10, dev->fx_dsp_addr);
954
955 for (i = 0; i < sizeof (page_three_v2); i++) {
956 outb (page_three_v2[i], dev->fx_dsp_lsb);
957 if (!wavefront_fx_idle (dev)) return (-1);
958 }
959
960 outb (FX_AUTO_INCR|FX_LSB_TRANSFER, dev->fx_lcr);
961 outb (0x04, dev->fx_dsp_page);
962 outb (0x10, dev->fx_dsp_addr);
963
964 for (i = 0; i < sizeof (page_four_v2); i++) {
965 outb (page_four_v2[i], dev->fx_dsp_lsb);
966 if (!wavefront_fx_idle (dev)) return (-1);
967 }
968
969 outb (FX_LSB_TRANSFER, dev->fx_lcr);
970 outb (0x06, dev->fx_dsp_page);
971
972 /* Page six v.2 is algorithmic */
973
974 for (i = 0x10; i <= 0x3e; i += 2) {
975 outb (i, dev->fx_dsp_addr);
976 outb (0x00, dev->fx_dsp_msb);
977 outb (0x00, dev->fx_dsp_lsb);
978 if (!wavefront_fx_idle (dev)) return (-1);
979 }
980
981 outb (FX_AUTO_INCR|FX_LSB_TRANSFER, dev->fx_lcr);
982 outb (0x07, dev->fx_dsp_page);
983 outb (0x10, dev->fx_dsp_addr);
984
985 for (i = 0; i < sizeof (page_seven_v2); i += 2) {
986 outb (page_seven_v2[i], dev->fx_dsp_msb);
987 outb (page_seven_v2[i+1], dev->fx_dsp_lsb);
988 if (!wavefront_fx_idle (dev)) return (-1);
989 }
990
991 for (i = 0x00; i < sizeof(mod_v2); i += 2) {
992 outb (mod_v2[i], dev->fx_mod_addr);
993 outb (mod_v2[i+1], dev->fx_mod_data);
994 if (!wavefront_fx_idle (dev)) return (-1);
995 }
996
997 for (i = 0; i < sizeof (coefficients2); i += 4) {
998 outb (coefficients2[i], dev->fx_dsp_page);
999 outb (coefficients2[i+1], dev->fx_dsp_addr);
1000 outb (coefficients2[i+2], dev->fx_dsp_msb);
1001 outb (coefficients2[i+3], dev->fx_dsp_lsb);
1002 if (!wavefront_fx_idle (dev)) return (-1);
1003 }
1004
1005 for (i = 0; i < sizeof (coefficients3); i += 2) {
1006 int x;
1007
1008 outb (0x07, dev->fx_dsp_page);
1009 x = (i % 4) ? 0x4e : 0x4c;
1010 outb (x, dev->fx_dsp_addr);
1011 outb (coefficients3[i], dev->fx_dsp_msb);
1012 outb (coefficients3[i+1], dev->fx_dsp_lsb);
1013 }
1014
1015 outb (0x00, dev->fx_op); /* mute off */
1016 if (!wavefront_fx_idle (dev)) return (-1);
1017
1018 return (0);
1019}
diff --git a/sound/isa/wavefront/wavefront_midi.c b/sound/isa/wavefront/wavefront_midi.c
new file mode 100644
index 000000000000..6f51d64fb565
--- /dev/null
+++ b/sound/isa/wavefront/wavefront_midi.c
@@ -0,0 +1,570 @@
1/*
2 * Copyright (C) by Paul Barton-Davis 1998-1999
3 *
4 * This file is distributed under the GNU GENERAL PUBLIC LICENSE (GPL)
5 * Version 2 (June 1991). See the "COPYING" file distributed with this
6 * software for more info.
7 */
8
9/* The low level driver for the WaveFront ICS2115 MIDI interface(s)
10 *
11 * Note that there is also an MPU-401 emulation (actually, a UART-401
12 * emulation) on the CS4232 on the Tropez and Tropez Plus. This code
13 * has nothing to do with that interface at all.
14 *
15 * The interface is essentially just a UART-401, but is has the
16 * interesting property of supporting what Turtle Beach called
17 * "Virtual MIDI" mode. In this mode, there are effectively *two*
18 * MIDI buses accessible via the interface, one that is routed
19 * solely to/from the external WaveFront synthesizer and the other
20 * corresponding to the pin/socket connector used to link external
21 * MIDI devices to the board.
22 *
23 * This driver fully supports this mode, allowing two distinct MIDI
24 * busses to be used completely independently, giving 32 channels of
25 * MIDI routing, 16 to the WaveFront synth and 16 to the external MIDI
26 * bus. The devices are named /dev/snd/midiCnD0 and /dev/snd/midiCnD1,
27 * where `n' is the card number. Note that the device numbers may be
28 * something other than 0 and 1 if the CS4232 UART/MPU-401 interface
29 * is enabled.
30 *
31 * Switching between the two is accomplished externally by the driver
32 * using the two otherwise unused MIDI bytes. See the code for more details.
33 *
34 * NOTE: VIRTUAL MIDI MODE IS ON BY DEFAULT (see lowlevel/isa/wavefront.c)
35 *
36 * The main reason to turn off Virtual MIDI mode is when you want to
37 * tightly couple the WaveFront synth with an external MIDI
38 * device. You won't be able to distinguish the source of any MIDI
39 * data except via SysEx ID, but thats probably OK, since for the most
40 * part, the WaveFront won't be sending any MIDI data at all.
41 *
42 * The main reason to turn on Virtual MIDI Mode is to provide two
43 * completely independent 16-channel MIDI buses, one to the
44 * WaveFront and one to any external MIDI devices. Given the 32
45 * voice nature of the WaveFront, its pretty easy to find a use
46 * for all 16 channels driving just that synth.
47 *
48 */
49
50#include <sound/driver.h>
51#include <asm/io.h>
52#include <linux/init.h>
53#include <linux/time.h>
54#include <linux/wait.h>
55#include <sound/core.h>
56#include <sound/snd_wavefront.h>
57
58static inline int
59wf_mpu_status (snd_wavefront_midi_t *midi)
60
61{
62 return inb (midi->mpu_status_port);
63}
64
65static inline int
66input_avail (snd_wavefront_midi_t *midi)
67
68{
69 return !(wf_mpu_status(midi) & INPUT_AVAIL);
70}
71
72static inline int
73output_ready (snd_wavefront_midi_t *midi)
74
75{
76 return !(wf_mpu_status(midi) & OUTPUT_READY);
77}
78
79static inline int
80read_data (snd_wavefront_midi_t *midi)
81
82{
83 return inb (midi->mpu_data_port);
84}
85
86static inline void
87write_data (snd_wavefront_midi_t *midi, unsigned char byte)
88
89{
90 outb (byte, midi->mpu_data_port);
91}
92
93static snd_wavefront_midi_t *
94get_wavefront_midi (snd_rawmidi_substream_t *substream)
95
96{
97 snd_card_t *card;
98 snd_wavefront_card_t *acard;
99
100 if (substream == NULL || substream->rmidi == NULL)
101 return NULL;
102
103 card = substream->rmidi->card;
104
105 if (card == NULL)
106 return NULL;
107
108 if (card->private_data == NULL)
109 return NULL;
110
111 acard = card->private_data;
112
113 return &acard->wavefront.midi;
114}
115
116static void snd_wavefront_midi_output_write(snd_wavefront_card_t *card)
117{
118 snd_wavefront_midi_t *midi = &card->wavefront.midi;
119 snd_wavefront_mpu_id mpu;
120 unsigned long flags;
121 unsigned char midi_byte;
122 int max = 256, mask = 1;
123 int timeout;
124
125 /* Its not OK to try to change the status of "virtuality" of
126 the MIDI interface while we're outputting stuff. See
127 snd_wavefront_midi_{enable,disable}_virtual () for the
128 other half of this.
129
130 The first loop attempts to flush any data from the
131 current output device, and then the second
132 emits the switch byte (if necessary), and starts
133 outputting data for the output device currently in use.
134 */
135
136 if (midi->substream_output[midi->output_mpu] == NULL) {
137 goto __second;
138 }
139
140 while (max > 0) {
141
142 /* XXX fix me - no hard timing loops allowed! */
143
144 for (timeout = 30000; timeout > 0; timeout--) {
145 if (output_ready (midi))
146 break;
147 }
148
149 spin_lock_irqsave (&midi->virtual, flags);
150 if ((midi->mode[midi->output_mpu] & MPU401_MODE_OUTPUT) == 0) {
151 spin_unlock_irqrestore (&midi->virtual, flags);
152 goto __second;
153 }
154 if (output_ready (midi)) {
155 if (snd_rawmidi_transmit(midi->substream_output[midi->output_mpu], &midi_byte, 1) == 1) {
156 if (!midi->isvirtual ||
157 (midi_byte != WF_INTERNAL_SWITCH &&
158 midi_byte != WF_EXTERNAL_SWITCH))
159 write_data(midi, midi_byte);
160 max--;
161 } else {
162 if (midi->istimer) {
163 if (--midi->istimer <= 0)
164 del_timer(&midi->timer);
165 }
166 midi->mode[midi->output_mpu] &= ~MPU401_MODE_OUTPUT_TRIGGER;
167 spin_unlock_irqrestore (&midi->virtual, flags);
168 goto __second;
169 }
170 } else {
171 spin_unlock_irqrestore (&midi->virtual, flags);
172 return;
173 }
174 spin_unlock_irqrestore (&midi->virtual, flags);
175 }
176
177 __second:
178
179 if (midi->substream_output[!midi->output_mpu] == NULL) {
180 return;
181 }
182
183 while (max > 0) {
184
185 /* XXX fix me - no hard timing loops allowed! */
186
187 for (timeout = 30000; timeout > 0; timeout--) {
188 if (output_ready (midi))
189 break;
190 }
191
192 spin_lock_irqsave (&midi->virtual, flags);
193 if (!midi->isvirtual)
194 mask = 0;
195 mpu = midi->output_mpu ^ mask;
196 mask = 0; /* don't invert the value from now */
197 if ((midi->mode[mpu] & MPU401_MODE_OUTPUT) == 0) {
198 spin_unlock_irqrestore (&midi->virtual, flags);
199 return;
200 }
201 if (snd_rawmidi_transmit_empty(midi->substream_output[mpu]))
202 goto __timer;
203 if (output_ready (midi)) {
204 if (mpu != midi->output_mpu) {
205 write_data(midi, mpu == internal_mpu ?
206 WF_INTERNAL_SWITCH :
207 WF_EXTERNAL_SWITCH);
208 midi->output_mpu = mpu;
209 } else if (snd_rawmidi_transmit(midi->substream_output[mpu], &midi_byte, 1) == 1) {
210 if (!midi->isvirtual ||
211 (midi_byte != WF_INTERNAL_SWITCH &&
212 midi_byte != WF_EXTERNAL_SWITCH))
213 write_data(midi, midi_byte);
214 max--;
215 } else {
216 __timer:
217 if (midi->istimer) {
218 if (--midi->istimer <= 0)
219 del_timer(&midi->timer);
220 }
221 midi->mode[mpu] &= ~MPU401_MODE_OUTPUT_TRIGGER;
222 spin_unlock_irqrestore (&midi->virtual, flags);
223 return;
224 }
225 } else {
226 spin_unlock_irqrestore (&midi->virtual, flags);
227 return;
228 }
229 spin_unlock_irqrestore (&midi->virtual, flags);
230 }
231}
232
233static int snd_wavefront_midi_input_open(snd_rawmidi_substream_t * substream)
234{
235 unsigned long flags;
236 snd_wavefront_midi_t *midi;
237 snd_wavefront_mpu_id mpu;
238
239 snd_assert(substream != NULL && substream->rmidi != NULL, return -EIO);
240 snd_assert(substream->rmidi->private_data != NULL, return -EIO);
241
242 mpu = *((snd_wavefront_mpu_id *) substream->rmidi->private_data);
243
244 if ((midi = get_wavefront_midi (substream)) == NULL)
245 return -EIO;
246
247 spin_lock_irqsave (&midi->open, flags);
248 midi->mode[mpu] |= MPU401_MODE_INPUT;
249 midi->substream_input[mpu] = substream;
250 spin_unlock_irqrestore (&midi->open, flags);
251
252 return 0;
253}
254
255static int snd_wavefront_midi_output_open(snd_rawmidi_substream_t * substream)
256{
257 unsigned long flags;
258 snd_wavefront_midi_t *midi;
259 snd_wavefront_mpu_id mpu;
260
261 snd_assert(substream != NULL && substream->rmidi != NULL, return -EIO);
262 snd_assert(substream->rmidi->private_data != NULL, return -EIO);
263
264 mpu = *((snd_wavefront_mpu_id *) substream->rmidi->private_data);
265
266 if ((midi = get_wavefront_midi (substream)) == NULL)
267 return -EIO;
268
269 spin_lock_irqsave (&midi->open, flags);
270 midi->mode[mpu] |= MPU401_MODE_OUTPUT;
271 midi->substream_output[mpu] = substream;
272 spin_unlock_irqrestore (&midi->open, flags);
273
274 return 0;
275}
276
277static int snd_wavefront_midi_input_close(snd_rawmidi_substream_t * substream)
278{
279 unsigned long flags;
280 snd_wavefront_midi_t *midi;
281 snd_wavefront_mpu_id mpu;
282
283 snd_assert(substream != NULL && substream->rmidi != NULL, return -EIO);
284 snd_assert(substream->rmidi->private_data != NULL, return -EIO);
285
286 mpu = *((snd_wavefront_mpu_id *) substream->rmidi->private_data);
287
288 if ((midi = get_wavefront_midi (substream)) == NULL)
289 return -EIO;
290
291 spin_lock_irqsave (&midi->open, flags);
292 midi->mode[mpu] &= ~MPU401_MODE_INPUT;
293 spin_unlock_irqrestore (&midi->open, flags);
294
295 return 0;
296}
297
298static int snd_wavefront_midi_output_close(snd_rawmidi_substream_t * substream)
299{
300 unsigned long flags;
301 snd_wavefront_midi_t *midi;
302 snd_wavefront_mpu_id mpu;
303
304 snd_assert(substream != NULL && substream->rmidi != NULL, return -EIO);
305 snd_assert(substream->rmidi->private_data != NULL, return -EIO);
306
307 mpu = *((snd_wavefront_mpu_id *) substream->rmidi->private_data);
308
309 if ((midi = get_wavefront_midi (substream)) == NULL)
310 return -EIO;
311
312 spin_lock_irqsave (&midi->open, flags);
313 midi->mode[mpu] &= ~MPU401_MODE_OUTPUT;
314 spin_unlock_irqrestore (&midi->open, flags);
315 return 0;
316}
317
318static void snd_wavefront_midi_input_trigger(snd_rawmidi_substream_t * substream, int up)
319{
320 unsigned long flags;
321 snd_wavefront_midi_t *midi;
322 snd_wavefront_mpu_id mpu;
323
324 if (substream == NULL || substream->rmidi == NULL)
325 return;
326
327 if (substream->rmidi->private_data == NULL)
328 return;
329
330 mpu = *((snd_wavefront_mpu_id *) substream->rmidi->private_data);
331
332 if ((midi = get_wavefront_midi (substream)) == NULL) {
333 return;
334 }
335
336 spin_lock_irqsave (&midi->virtual, flags);
337 if (up) {
338 midi->mode[mpu] |= MPU401_MODE_INPUT_TRIGGER;
339 } else {
340 midi->mode[mpu] &= ~MPU401_MODE_INPUT_TRIGGER;
341 }
342 spin_unlock_irqrestore (&midi->virtual, flags);
343}
344
345static void snd_wavefront_midi_output_timer(unsigned long data)
346{
347 snd_wavefront_card_t *card = (snd_wavefront_card_t *)data;
348 snd_wavefront_midi_t *midi = &card->wavefront.midi;
349 unsigned long flags;
350
351 spin_lock_irqsave (&midi->virtual, flags);
352 midi->timer.expires = 1 + jiffies;
353 add_timer(&midi->timer);
354 spin_unlock_irqrestore (&midi->virtual, flags);
355 snd_wavefront_midi_output_write(card);
356}
357
358static void snd_wavefront_midi_output_trigger(snd_rawmidi_substream_t * substream, int up)
359{
360 unsigned long flags;
361 snd_wavefront_midi_t *midi;
362 snd_wavefront_mpu_id mpu;
363
364 if (substream == NULL || substream->rmidi == NULL)
365 return;
366
367 if (substream->rmidi->private_data == NULL)
368 return;
369
370 mpu = *((snd_wavefront_mpu_id *) substream->rmidi->private_data);
371
372 if ((midi = get_wavefront_midi (substream)) == NULL) {
373 return;
374 }
375
376 spin_lock_irqsave (&midi->virtual, flags);
377 if (up) {
378 if ((midi->mode[mpu] & MPU401_MODE_OUTPUT_TRIGGER) == 0) {
379 if (!midi->istimer) {
380 init_timer(&midi->timer);
381 midi->timer.function = snd_wavefront_midi_output_timer;
382 midi->timer.data = (unsigned long) substream->rmidi->card->private_data;
383 midi->timer.expires = 1 + jiffies;
384 add_timer(&midi->timer);
385 }
386 midi->istimer++;
387 midi->mode[mpu] |= MPU401_MODE_OUTPUT_TRIGGER;
388 }
389 } else {
390 midi->mode[mpu] &= ~MPU401_MODE_OUTPUT_TRIGGER;
391 }
392 spin_unlock_irqrestore (&midi->virtual, flags);
393
394 if (up)
395 snd_wavefront_midi_output_write((snd_wavefront_card_t *)substream->rmidi->card->private_data);
396}
397
398void
399snd_wavefront_midi_interrupt (snd_wavefront_card_t *card)
400
401{
402 unsigned long flags;
403 snd_wavefront_midi_t *midi;
404 static snd_rawmidi_substream_t *substream = NULL;
405 static int mpu = external_mpu;
406 int max = 128;
407 unsigned char byte;
408
409 midi = &card->wavefront.midi;
410
411 if (!input_avail (midi)) { /* not for us */
412 snd_wavefront_midi_output_write(card);
413 return;
414 }
415
416 spin_lock_irqsave (&midi->virtual, flags);
417 while (--max) {
418
419 if (input_avail (midi)) {
420 byte = read_data (midi);
421
422 if (midi->isvirtual) {
423 if (byte == WF_EXTERNAL_SWITCH) {
424 substream = midi->substream_input[external_mpu];
425 mpu = external_mpu;
426 } else if (byte == WF_INTERNAL_SWITCH) {
427 substream = midi->substream_output[internal_mpu];
428 mpu = internal_mpu;
429 } /* else just leave it as it is */
430 } else {
431 substream = midi->substream_input[internal_mpu];
432 mpu = internal_mpu;
433 }
434
435 if (substream == NULL) {
436 continue;
437 }
438
439 if (midi->mode[mpu] & MPU401_MODE_INPUT_TRIGGER) {
440 snd_rawmidi_receive(substream, &byte, 1);
441 }
442 } else {
443 break;
444 }
445 }
446 spin_unlock_irqrestore (&midi->virtual, flags);
447
448 snd_wavefront_midi_output_write(card);
449}
450
451void
452snd_wavefront_midi_enable_virtual (snd_wavefront_card_t *card)
453
454{
455 unsigned long flags;
456
457 spin_lock_irqsave (&card->wavefront.midi.virtual, flags);
458 card->wavefront.midi.isvirtual = 1;
459 card->wavefront.midi.output_mpu = internal_mpu;
460 card->wavefront.midi.input_mpu = internal_mpu;
461 spin_unlock_irqrestore (&card->wavefront.midi.virtual, flags);
462}
463
464void
465snd_wavefront_midi_disable_virtual (snd_wavefront_card_t *card)
466
467{
468 unsigned long flags;
469
470 spin_lock_irqsave (&card->wavefront.midi.virtual, flags);
471 // snd_wavefront_midi_input_close (card->ics2115_external_rmidi);
472 // snd_wavefront_midi_output_close (card->ics2115_external_rmidi);
473 card->wavefront.midi.isvirtual = 0;
474 spin_unlock_irqrestore (&card->wavefront.midi.virtual, flags);
475}
476
477int __init
478snd_wavefront_midi_start (snd_wavefront_card_t *card)
479
480{
481 int ok, i;
482 unsigned char rbuf[4], wbuf[4];
483 snd_wavefront_t *dev;
484 snd_wavefront_midi_t *midi;
485
486 dev = &card->wavefront;
487 midi = &dev->midi;
488
489 /* The ICS2115 MPU-401 interface doesn't do anything
490 until its set into UART mode.
491 */
492
493 /* XXX fix me - no hard timing loops allowed! */
494
495 for (i = 0; i < 30000 && !output_ready (midi); i++);
496
497 if (!output_ready (midi)) {
498 snd_printk ("MIDI interface not ready for command\n");
499 return -1;
500 }
501
502 /* Any interrupts received from now on
503 are owned by the MIDI side of things.
504 */
505
506 dev->interrupts_are_midi = 1;
507
508 outb (UART_MODE_ON, midi->mpu_command_port);
509
510 for (ok = 0, i = 50000; i > 0 && !ok; i--) {
511 if (input_avail (midi)) {
512 if (read_data (midi) == MPU_ACK) {
513 ok = 1;
514 break;
515 }
516 }
517 }
518
519 if (!ok) {
520 snd_printk ("cannot set UART mode for MIDI interface");
521 dev->interrupts_are_midi = 0;
522 return -1;
523 }
524
525 /* Route external MIDI to WaveFront synth (by default) */
526
527 if (snd_wavefront_cmd (dev, WFC_MISYNTH_ON, rbuf, wbuf)) {
528 snd_printk ("can't enable MIDI-IN-2-synth routing.\n");
529 /* XXX error ? */
530 }
531
532 /* Turn on Virtual MIDI, but first *always* turn it off,
533 since otherwise consectutive reloads of the driver will
534 never cause the hardware to generate the initial "internal" or
535 "external" source bytes in the MIDI data stream. This
536 is pretty important, since the internal hardware generally will
537 be used to generate none or very little MIDI output, and
538 thus the only source of MIDI data is actually external. Without
539 the switch bytes, the driver will think it all comes from
540 the internal interface. Duh.
541 */
542
543 if (snd_wavefront_cmd (dev, WFC_VMIDI_OFF, rbuf, wbuf)) {
544 snd_printk ("virtual MIDI mode not disabled\n");
545 return 0; /* We're OK, but missing the external MIDI dev */
546 }
547
548 snd_wavefront_midi_enable_virtual (card);
549
550 if (snd_wavefront_cmd (dev, WFC_VMIDI_ON, rbuf, wbuf)) {
551 snd_printk ("cannot enable virtual MIDI mode.\n");
552 snd_wavefront_midi_disable_virtual (card);
553 }
554 return 0;
555}
556
557snd_rawmidi_ops_t snd_wavefront_midi_output =
558{
559 .open = snd_wavefront_midi_output_open,
560 .close = snd_wavefront_midi_output_close,
561 .trigger = snd_wavefront_midi_output_trigger,
562};
563
564snd_rawmidi_ops_t snd_wavefront_midi_input =
565{
566 .open = snd_wavefront_midi_input_open,
567 .close = snd_wavefront_midi_input_close,
568 .trigger = snd_wavefront_midi_input_trigger,
569};
570
diff --git a/sound/isa/wavefront/wavefront_synth.c b/sound/isa/wavefront/wavefront_synth.c
new file mode 100644
index 000000000000..0c3c951009d8
--- /dev/null
+++ b/sound/isa/wavefront/wavefront_synth.c
@@ -0,0 +1,2243 @@
1/* Copyright (C) by Paul Barton-Davis 1998-1999
2 *
3 * Some portions of this file are taken from work that is
4 * copyright (C) by Hannu Savolainen 1993-1996
5 *
6 * This program is distributed under the GNU GENERAL PUBLIC LICENSE (GPL)
7 * Version 2 (June 1991). See the "COPYING" file distributed with this software
8 * for more info.
9 */
10
11/*
12 * An ALSA lowlevel driver for Turtle Beach ICS2115 wavetable synth
13 * (Maui, Tropez, Tropez Plus)
14 *
15 * This driver supports the onboard wavetable synthesizer (an ICS2115),
16 * including patch, sample and program loading and unloading, conversion
17 * of GUS patches during loading, and full user-level access to all
18 * WaveFront commands. It tries to provide semi-intelligent patch and
19 * sample management as well.
20 *
21 */
22
23#include <sound/driver.h>
24#include <asm/io.h>
25#include <linux/interrupt.h>
26#include <linux/init.h>
27#include <linux/delay.h>
28#include <linux/time.h>
29#include <linux/wait.h>
30#include <linux/moduleparam.h>
31#include <sound/core.h>
32#include <sound/snd_wavefront.h>
33#include <sound/initval.h>
34
35static int wf_raw = 0; /* we normally check for "raw state" to firmware
36 loading. if non-zero, then during driver loading, the
37 state of the board is ignored, and we reset the
38 board and load the firmware anyway.
39 */
40
41static int fx_raw = 1; /* if this is zero, we'll leave the FX processor in
42 whatever state it is when the driver is loaded.
43 The default is to download the microprogram and
44 associated coefficients to set it up for "default"
45 operation, whatever that means.
46 */
47
48static int debug_default = 0; /* you can set this to control debugging
49 during driver loading. it takes any combination
50 of the WF_DEBUG_* flags defined in
51 wavefront.h
52 */
53
54/* XXX this needs to be made firmware and hardware version dependent */
55
56static char *ospath = "/etc/sound/wavefront.os"; /* where to find a processed
57 version of the WaveFront OS
58 */
59
60static int wait_usecs = 150; /* This magic number seems to give pretty optimal
61 throughput based on my limited experimentation.
62 If you want to play around with it and find a better
63 value, be my guest. Remember, the idea is to
64 get a number that causes us to just busy wait
65 for as many WaveFront commands as possible, without
66 coming up with a number so large that we hog the
67 whole CPU.
68
69 Specifically, with this number, out of about 134,000
70 status waits, only about 250 result in a sleep.
71 */
72
73static int sleep_interval = 100; /* HZ/sleep_interval seconds per sleep */
74static int sleep_tries = 50; /* number of times we'll try to sleep */
75
76static int reset_time = 2; /* hundreths of a second we wait after a HW
77 reset for the expected interrupt.
78 */
79
80static int ramcheck_time = 20; /* time in seconds to wait while ROM code
81 checks on-board RAM.
82 */
83
84static int osrun_time = 10; /* time in seconds we wait for the OS to
85 start running.
86 */
87module_param(wf_raw, int, 0444);
88MODULE_PARM_DESC(wf_raw, "if non-zero, assume that we need to boot the OS");
89module_param(fx_raw, int, 0444);
90MODULE_PARM_DESC(fx_raw, "if non-zero, assume that the FX process needs help");
91module_param(debug_default, int, 0444);
92MODULE_PARM_DESC(debug_default, "debug parameters for card initialization");
93module_param(wait_usecs, int, 0444);
94MODULE_PARM_DESC(wait_usecs, "how long to wait without sleeping, usecs");
95module_param(sleep_interval, int, 0444);
96MODULE_PARM_DESC(sleep_interval, "how long to sleep when waiting for reply");
97module_param(sleep_tries, int, 0444);
98MODULE_PARM_DESC(sleep_tries, "how many times to try sleeping during a wait");
99module_param(ospath, charp, 0444);
100MODULE_PARM_DESC(ospath, "full pathname to processed ICS2115 OS firmware");
101module_param(reset_time, int, 0444);
102MODULE_PARM_DESC(reset_time, "how long to wait for a reset to take effect");
103module_param(ramcheck_time, int, 0444);
104MODULE_PARM_DESC(ramcheck_time, "how many seconds to wait for the RAM test");
105module_param(osrun_time, int, 0444);
106MODULE_PARM_DESC(osrun_time, "how many seconds to wait for the ICS2115 OS");
107
108/* if WF_DEBUG not defined, no run-time debugging messages will
109 be available via the debug flag setting. Given the current
110 beta state of the driver, this will remain set until a future
111 version.
112*/
113
114#define WF_DEBUG 1
115
116#ifdef WF_DEBUG
117
118#if defined(NEW_MACRO_VARARGS) || __GNUC__ >= 3
119#define DPRINT(cond, ...) \
120 if ((dev->debug & (cond)) == (cond)) { \
121 snd_printk (__VA_ARGS__); \
122 }
123#else
124#define DPRINT(cond, args...) \
125 if ((dev->debug & (cond)) == (cond)) { \
126 snd_printk (args); \
127 }
128#endif
129#else
130#define DPRINT(cond, args...)
131#endif /* WF_DEBUG */
132
133#define LOGNAME "WaveFront: "
134
135/* bitmasks for WaveFront status port value */
136
137#define STAT_RINTR_ENABLED 0x01
138#define STAT_CAN_READ 0x02
139#define STAT_INTR_READ 0x04
140#define STAT_WINTR_ENABLED 0x10
141#define STAT_CAN_WRITE 0x20
142#define STAT_INTR_WRITE 0x40
143
144static int wavefront_delete_sample (snd_wavefront_t *, int sampnum);
145static int wavefront_find_free_sample (snd_wavefront_t *);
146
147typedef struct {
148 int cmd;
149 char *action;
150 unsigned int read_cnt;
151 unsigned int write_cnt;
152 int need_ack;
153} wavefront_command;
154
155static struct {
156 int errno;
157 const char *errstr;
158} wavefront_errors[] = {
159 { 0x01, "Bad sample number" },
160 { 0x02, "Out of sample memory" },
161 { 0x03, "Bad patch number" },
162 { 0x04, "Error in number of voices" },
163 { 0x06, "Sample load already in progress" },
164 { 0x0B, "No sample load request pending" },
165 { 0x0E, "Bad MIDI channel number" },
166 { 0x10, "Download Record Error" },
167 { 0x80, "Success" },
168 { 0x0 }
169};
170
171#define NEEDS_ACK 1
172
173static wavefront_command wavefront_commands[] = {
174 { WFC_SET_SYNTHVOL, "set synthesizer volume", 0, 1, NEEDS_ACK },
175 { WFC_GET_SYNTHVOL, "get synthesizer volume", 1, 0, 0},
176 { WFC_SET_NVOICES, "set number of voices", 0, 1, NEEDS_ACK },
177 { WFC_GET_NVOICES, "get number of voices", 1, 0, 0 },
178 { WFC_SET_TUNING, "set synthesizer tuning", 0, 2, NEEDS_ACK },
179 { WFC_GET_TUNING, "get synthesizer tuning", 2, 0, 0 },
180 { WFC_DISABLE_CHANNEL, "disable synth channel", 0, 1, NEEDS_ACK },
181 { WFC_ENABLE_CHANNEL, "enable synth channel", 0, 1, NEEDS_ACK },
182 { WFC_GET_CHANNEL_STATUS, "get synth channel status", 3, 0, 0 },
183 { WFC_MISYNTH_OFF, "disable midi-in to synth", 0, 0, NEEDS_ACK },
184 { WFC_MISYNTH_ON, "enable midi-in to synth", 0, 0, NEEDS_ACK },
185 { WFC_VMIDI_ON, "enable virtual midi mode", 0, 0, NEEDS_ACK },
186 { WFC_VMIDI_OFF, "disable virtual midi mode", 0, 0, NEEDS_ACK },
187 { WFC_MIDI_STATUS, "report midi status", 1, 0, 0 },
188 { WFC_FIRMWARE_VERSION, "report firmware version", 2, 0, 0 },
189 { WFC_HARDWARE_VERSION, "report hardware version", 2, 0, 0 },
190 { WFC_GET_NSAMPLES, "report number of samples", 2, 0, 0 },
191 { WFC_INSTOUT_LEVELS, "report instantaneous output levels", 7, 0, 0 },
192 { WFC_PEAKOUT_LEVELS, "report peak output levels", 7, 0, 0 },
193 { WFC_DOWNLOAD_SAMPLE, "download sample",
194 0, WF_SAMPLE_BYTES, NEEDS_ACK },
195 { WFC_DOWNLOAD_BLOCK, "download block", 0, 0, NEEDS_ACK},
196 { WFC_DOWNLOAD_SAMPLE_HEADER, "download sample header",
197 0, WF_SAMPLE_HDR_BYTES, NEEDS_ACK },
198 { WFC_UPLOAD_SAMPLE_HEADER, "upload sample header", 13, 2, 0 },
199
200 /* This command requires a variable number of bytes to be written.
201 There is a hack in snd_wavefront_cmd() to support this. The actual
202 count is passed in as the read buffer ptr, cast appropriately.
203 Ugh.
204 */
205
206 { WFC_DOWNLOAD_MULTISAMPLE, "download multisample", 0, 0, NEEDS_ACK },
207
208 /* This one is a hack as well. We just read the first byte of the
209 response, don't fetch an ACK, and leave the rest to the
210 calling function. Ugly, ugly, ugly.
211 */
212
213 { WFC_UPLOAD_MULTISAMPLE, "upload multisample", 2, 1, 0 },
214 { WFC_DOWNLOAD_SAMPLE_ALIAS, "download sample alias",
215 0, WF_ALIAS_BYTES, NEEDS_ACK },
216 { WFC_UPLOAD_SAMPLE_ALIAS, "upload sample alias", WF_ALIAS_BYTES, 2, 0},
217 { WFC_DELETE_SAMPLE, "delete sample", 0, 2, NEEDS_ACK },
218 { WFC_IDENTIFY_SAMPLE_TYPE, "identify sample type", 5, 2, 0 },
219 { WFC_UPLOAD_SAMPLE_PARAMS, "upload sample parameters" },
220 { WFC_REPORT_FREE_MEMORY, "report free memory", 4, 0, 0 },
221 { WFC_DOWNLOAD_PATCH, "download patch", 0, 134, NEEDS_ACK },
222 { WFC_UPLOAD_PATCH, "upload patch", 132, 2, 0 },
223 { WFC_DOWNLOAD_PROGRAM, "download program", 0, 33, NEEDS_ACK },
224 { WFC_UPLOAD_PROGRAM, "upload program", 32, 1, 0 },
225 { WFC_DOWNLOAD_EDRUM_PROGRAM, "download enhanced drum program", 0, 9,
226 NEEDS_ACK},
227 { WFC_UPLOAD_EDRUM_PROGRAM, "upload enhanced drum program", 8, 1, 0},
228 { WFC_SET_EDRUM_CHANNEL, "set enhanced drum program channel",
229 0, 1, NEEDS_ACK },
230 { WFC_DISABLE_DRUM_PROGRAM, "disable drum program", 0, 1, NEEDS_ACK },
231 { WFC_REPORT_CHANNEL_PROGRAMS, "report channel program numbers",
232 32, 0, 0 },
233 { WFC_NOOP, "the no-op command", 0, 0, NEEDS_ACK },
234 { 0x00 }
235};
236
237static const char *
238wavefront_errorstr (int errnum)
239
240{
241 int i;
242
243 for (i = 0; wavefront_errors[i].errstr; i++) {
244 if (wavefront_errors[i].errno == errnum) {
245 return wavefront_errors[i].errstr;
246 }
247 }
248
249 return "Unknown WaveFront error";
250}
251
252static wavefront_command *
253wavefront_get_command (int cmd)
254
255{
256 int i;
257
258 for (i = 0; wavefront_commands[i].cmd != 0; i++) {
259 if (cmd == wavefront_commands[i].cmd) {
260 return &wavefront_commands[i];
261 }
262 }
263
264 return (wavefront_command *) 0;
265}
266
267static inline int
268wavefront_status (snd_wavefront_t *dev)
269
270{
271 return inb (dev->status_port);
272}
273
274static int
275wavefront_sleep (int limit)
276
277{
278 set_current_state(TASK_INTERRUPTIBLE);
279 schedule_timeout(limit);
280
281 return signal_pending(current);
282}
283
284static int
285wavefront_wait (snd_wavefront_t *dev, int mask)
286
287{
288 int i;
289
290 /* Spin for a short period of time, because >99% of all
291 requests to the WaveFront can be serviced inline like this.
292 */
293
294 for (i = 0; i < wait_usecs; i += 5) {
295 if (wavefront_status (dev) & mask) {
296 return 1;
297 }
298 udelay(5);
299 }
300
301 for (i = 0; i < sleep_tries; i++) {
302
303 if (wavefront_status (dev) & mask) {
304 return 1;
305 }
306
307 if (wavefront_sleep (HZ/sleep_interval)) {
308 return (0);
309 }
310 }
311
312 return (0);
313}
314
315static int
316wavefront_read (snd_wavefront_t *dev)
317
318{
319 if (wavefront_wait (dev, STAT_CAN_READ))
320 return inb (dev->data_port);
321
322 DPRINT (WF_DEBUG_DATA, "read timeout.\n");
323
324 return -1;
325}
326
327static int
328wavefront_write (snd_wavefront_t *dev, unsigned char data)
329
330{
331 if (wavefront_wait (dev, STAT_CAN_WRITE)) {
332 outb (data, dev->data_port);
333 return 0;
334 }
335
336 DPRINT (WF_DEBUG_DATA, "write timeout.\n");
337
338 return -1;
339}
340
341int
342snd_wavefront_cmd (snd_wavefront_t *dev,
343 int cmd, unsigned char *rbuf, unsigned char *wbuf)
344
345{
346 int ack;
347 unsigned int i;
348 int c;
349 wavefront_command *wfcmd;
350
351 if ((wfcmd = wavefront_get_command (cmd)) == (wavefront_command *) 0) {
352 snd_printk ("command 0x%x not supported.\n",
353 cmd);
354 return 1;
355 }
356
357 /* Hack to handle the one variable-size write command. See
358 wavefront_send_multisample() for the other half of this
359 gross and ugly strategy.
360 */
361
362 if (cmd == WFC_DOWNLOAD_MULTISAMPLE) {
363 wfcmd->write_cnt = (unsigned long) rbuf;
364 rbuf = NULL;
365 }
366
367 DPRINT (WF_DEBUG_CMD, "0x%x [%s] (%d,%d,%d)\n",
368 cmd, wfcmd->action, wfcmd->read_cnt,
369 wfcmd->write_cnt, wfcmd->need_ack);
370
371 if (wavefront_write (dev, cmd)) {
372 DPRINT ((WF_DEBUG_IO|WF_DEBUG_CMD), "cannot request "
373 "0x%x [%s].\n",
374 cmd, wfcmd->action);
375 return 1;
376 }
377
378 if (wfcmd->write_cnt > 0) {
379 DPRINT (WF_DEBUG_DATA, "writing %d bytes "
380 "for 0x%x\n",
381 wfcmd->write_cnt, cmd);
382
383 for (i = 0; i < wfcmd->write_cnt; i++) {
384 if (wavefront_write (dev, wbuf[i])) {
385 DPRINT (WF_DEBUG_IO, "bad write for byte "
386 "%d of 0x%x [%s].\n",
387 i, cmd, wfcmd->action);
388 return 1;
389 }
390
391 DPRINT (WF_DEBUG_DATA, "write[%d] = 0x%x\n",
392 i, wbuf[i]);
393 }
394 }
395
396 if (wfcmd->read_cnt > 0) {
397 DPRINT (WF_DEBUG_DATA, "reading %d ints "
398 "for 0x%x\n",
399 wfcmd->read_cnt, cmd);
400
401 for (i = 0; i < wfcmd->read_cnt; i++) {
402
403 if ((c = wavefront_read (dev)) == -1) {
404 DPRINT (WF_DEBUG_IO, "bad read for byte "
405 "%d of 0x%x [%s].\n",
406 i, cmd, wfcmd->action);
407 return 1;
408 }
409
410 /* Now handle errors. Lots of special cases here */
411
412 if (c == 0xff) {
413 if ((c = wavefront_read (dev)) == -1) {
414 DPRINT (WF_DEBUG_IO, "bad read for "
415 "error byte at "
416 "read byte %d "
417 "of 0x%x [%s].\n",
418 i, cmd,
419 wfcmd->action);
420 return 1;
421 }
422
423 /* Can you believe this madness ? */
424
425 if (c == 1 &&
426 wfcmd->cmd == WFC_IDENTIFY_SAMPLE_TYPE) {
427 rbuf[0] = WF_ST_EMPTY;
428 return (0);
429
430 } else if (c == 3 &&
431 wfcmd->cmd == WFC_UPLOAD_PATCH) {
432
433 return 3;
434
435 } else if (c == 1 &&
436 wfcmd->cmd == WFC_UPLOAD_PROGRAM) {
437
438 return 1;
439
440 } else {
441
442 DPRINT (WF_DEBUG_IO, "error %d (%s) "
443 "during "
444 "read for byte "
445 "%d of 0x%x "
446 "[%s].\n",
447 c,
448 wavefront_errorstr (c),
449 i, cmd,
450 wfcmd->action);
451 return 1;
452
453 }
454
455 } else {
456 rbuf[i] = c;
457 }
458
459 DPRINT (WF_DEBUG_DATA, "read[%d] = 0x%x\n",i, rbuf[i]);
460 }
461 }
462
463 if ((wfcmd->read_cnt == 0 && wfcmd->write_cnt == 0) || wfcmd->need_ack) {
464
465 DPRINT (WF_DEBUG_CMD, "reading ACK for 0x%x\n", cmd);
466
467 /* Some commands need an ACK, but return zero instead
468 of the standard value.
469 */
470
471 if ((ack = wavefront_read (dev)) == 0) {
472 ack = WF_ACK;
473 }
474
475 if (ack != WF_ACK) {
476 if (ack == -1) {
477 DPRINT (WF_DEBUG_IO, "cannot read ack for "
478 "0x%x [%s].\n",
479 cmd, wfcmd->action);
480 return 1;
481
482 } else {
483 int err = -1; /* something unknown */
484
485 if (ack == 0xff) { /* explicit error */
486
487 if ((err = wavefront_read (dev)) == -1) {
488 DPRINT (WF_DEBUG_DATA,
489 "cannot read err "
490 "for 0x%x [%s].\n",
491 cmd, wfcmd->action);
492 }
493 }
494
495 DPRINT (WF_DEBUG_IO, "0x%x [%s] "
496 "failed (0x%x, 0x%x, %s)\n",
497 cmd, wfcmd->action, ack, err,
498 wavefront_errorstr (err));
499
500 return -err;
501 }
502 }
503
504 DPRINT (WF_DEBUG_DATA, "ack received "
505 "for 0x%x [%s]\n",
506 cmd, wfcmd->action);
507 } else {
508
509 DPRINT (WF_DEBUG_CMD, "0x%x [%s] does not need "
510 "ACK (%d,%d,%d)\n",
511 cmd, wfcmd->action, wfcmd->read_cnt,
512 wfcmd->write_cnt, wfcmd->need_ack);
513 }
514
515 return 0;
516
517}
518
519/***********************************************************************
520WaveFront data munging
521
522Things here are weird. All data written to the board cannot
523have its most significant bit set. Any data item with values
524potentially > 0x7F (127) must be split across multiple bytes.
525
526Sometimes, we need to munge numeric values that are represented on
527the x86 side as 8-32 bit values. Sometimes, we need to munge data
528that is represented on the x86 side as an array of bytes. The most
529efficient approach to handling both cases seems to be to use 2
530different functions for munging and 2 for de-munging. This avoids
531weird casting and worrying about bit-level offsets.
532
533**********************************************************************/
534
535static unsigned char *
536munge_int32 (unsigned int src,
537 unsigned char *dst,
538 unsigned int dst_size)
539{
540 unsigned int i;
541
542 for (i = 0; i < dst_size; i++) {
543 *dst = src & 0x7F; /* Mask high bit of LSB */
544 src = src >> 7; /* Rotate Right 7 bits */
545 /* Note: we leave the upper bits in place */
546
547 dst++;
548 };
549 return dst;
550};
551
552static int
553demunge_int32 (unsigned char* src, int src_size)
554
555{
556 int i;
557 int outval = 0;
558
559 for (i = src_size - 1; i >= 0; i--) {
560 outval=(outval<<7)+src[i];
561 }
562
563 return outval;
564};
565
566static
567unsigned char *
568munge_buf (unsigned char *src, unsigned char *dst, unsigned int dst_size)
569
570{
571 unsigned int i;
572 unsigned int last = dst_size / 2;
573
574 for (i = 0; i < last; i++) {
575 *dst++ = src[i] & 0x7f;
576 *dst++ = src[i] >> 7;
577 }
578 return dst;
579}
580
581static
582unsigned char *
583demunge_buf (unsigned char *src, unsigned char *dst, unsigned int src_bytes)
584
585{
586 int i;
587 unsigned char *end = src + src_bytes;
588
589 end = src + src_bytes;
590
591 /* NOTE: src and dst *CAN* point to the same address */
592
593 for (i = 0; src != end; i++) {
594 dst[i] = *src++;
595 dst[i] |= (*src++)<<7;
596 }
597
598 return dst;
599}
600
601/***********************************************************************
602WaveFront: sample, patch and program management.
603***********************************************************************/
604
605static int
606wavefront_delete_sample (snd_wavefront_t *dev, int sample_num)
607
608{
609 unsigned char wbuf[2];
610 int x;
611
612 wbuf[0] = sample_num & 0x7f;
613 wbuf[1] = sample_num >> 7;
614
615 if ((x = snd_wavefront_cmd (dev, WFC_DELETE_SAMPLE, NULL, wbuf)) == 0) {
616 dev->sample_status[sample_num] = WF_ST_EMPTY;
617 }
618
619 return x;
620}
621
622static int
623wavefront_get_sample_status (snd_wavefront_t *dev, int assume_rom)
624
625{
626 int i;
627 unsigned char rbuf[32], wbuf[32];
628 unsigned int sc_real, sc_alias, sc_multi;
629
630 /* check sample status */
631
632 if (snd_wavefront_cmd (dev, WFC_GET_NSAMPLES, rbuf, wbuf)) {
633 snd_printk ("cannot request sample count.\n");
634 return -1;
635 }
636
637 sc_real = sc_alias = sc_multi = dev->samples_used = 0;
638
639 for (i = 0; i < WF_MAX_SAMPLE; i++) {
640
641 wbuf[0] = i & 0x7f;
642 wbuf[1] = i >> 7;
643
644 if (snd_wavefront_cmd (dev, WFC_IDENTIFY_SAMPLE_TYPE, rbuf, wbuf)) {
645 snd_printk("cannot identify sample "
646 "type of slot %d\n", i);
647 dev->sample_status[i] = WF_ST_EMPTY;
648 continue;
649 }
650
651 dev->sample_status[i] = (WF_SLOT_FILLED|rbuf[0]);
652
653 if (assume_rom) {
654 dev->sample_status[i] |= WF_SLOT_ROM;
655 }
656
657 switch (rbuf[0] & WF_ST_MASK) {
658 case WF_ST_SAMPLE:
659 sc_real++;
660 break;
661 case WF_ST_MULTISAMPLE:
662 sc_multi++;
663 break;
664 case WF_ST_ALIAS:
665 sc_alias++;
666 break;
667 case WF_ST_EMPTY:
668 break;
669
670 default:
671 snd_printk ("unknown sample type for "
672 "slot %d (0x%x)\n",
673 i, rbuf[0]);
674 }
675
676 if (rbuf[0] != WF_ST_EMPTY) {
677 dev->samples_used++;
678 }
679 }
680
681 snd_printk ("%d samples used (%d real, %d aliases, %d multi), "
682 "%d empty\n", dev->samples_used, sc_real, sc_alias, sc_multi,
683 WF_MAX_SAMPLE - dev->samples_used);
684
685
686 return (0);
687
688}
689
690static int
691wavefront_get_patch_status (snd_wavefront_t *dev)
692
693{
694 unsigned char patchbuf[WF_PATCH_BYTES];
695 unsigned char patchnum[2];
696 wavefront_patch *p;
697 int i, x, cnt, cnt2;
698
699 for (i = 0; i < WF_MAX_PATCH; i++) {
700 patchnum[0] = i & 0x7f;
701 patchnum[1] = i >> 7;
702
703 if ((x = snd_wavefront_cmd (dev, WFC_UPLOAD_PATCH, patchbuf,
704 patchnum)) == 0) {
705
706 dev->patch_status[i] |= WF_SLOT_FILLED;
707 p = (wavefront_patch *) patchbuf;
708 dev->sample_status
709 [p->sample_number|(p->sample_msb<<7)] |=
710 WF_SLOT_USED;
711
712 } else if (x == 3) { /* Bad patch number */
713 dev->patch_status[i] = 0;
714 } else {
715 snd_printk ("upload patch "
716 "error 0x%x\n", x);
717 dev->patch_status[i] = 0;
718 return 1;
719 }
720 }
721
722 /* program status has already filled in slot_used bits */
723
724 for (i = 0, cnt = 0, cnt2 = 0; i < WF_MAX_PATCH; i++) {
725 if (dev->patch_status[i] & WF_SLOT_FILLED) {
726 cnt++;
727 }
728 if (dev->patch_status[i] & WF_SLOT_USED) {
729 cnt2++;
730 }
731
732 }
733 snd_printk ("%d patch slots filled, %d in use\n", cnt, cnt2);
734
735 return (0);
736}
737
738static int
739wavefront_get_program_status (snd_wavefront_t *dev)
740
741{
742 unsigned char progbuf[WF_PROGRAM_BYTES];
743 wavefront_program prog;
744 unsigned char prognum;
745 int i, x, l, cnt;
746
747 for (i = 0; i < WF_MAX_PROGRAM; i++) {
748 prognum = i;
749
750 if ((x = snd_wavefront_cmd (dev, WFC_UPLOAD_PROGRAM, progbuf,
751 &prognum)) == 0) {
752
753 dev->prog_status[i] |= WF_SLOT_USED;
754
755 demunge_buf (progbuf, (unsigned char *) &prog,
756 WF_PROGRAM_BYTES);
757
758 for (l = 0; l < WF_NUM_LAYERS; l++) {
759 if (prog.layer[l].mute) {
760 dev->patch_status
761 [prog.layer[l].patch_number] |=
762 WF_SLOT_USED;
763 }
764 }
765 } else if (x == 1) { /* Bad program number */
766 dev->prog_status[i] = 0;
767 } else {
768 snd_printk ("upload program "
769 "error 0x%x\n", x);
770 dev->prog_status[i] = 0;
771 }
772 }
773
774 for (i = 0, cnt = 0; i < WF_MAX_PROGRAM; i++) {
775 if (dev->prog_status[i]) {
776 cnt++;
777 }
778 }
779
780 snd_printk ("%d programs slots in use\n", cnt);
781
782 return (0);
783}
784
785static int
786wavefront_send_patch (snd_wavefront_t *dev, wavefront_patch_info *header)
787
788{
789 unsigned char buf[WF_PATCH_BYTES+2];
790 unsigned char *bptr;
791
792 DPRINT (WF_DEBUG_LOAD_PATCH, "downloading patch %d\n",
793 header->number);
794
795 dev->patch_status[header->number] |= WF_SLOT_FILLED;
796
797 bptr = buf;
798 bptr = munge_int32 (header->number, buf, 2);
799 munge_buf ((unsigned char *)&header->hdr.p, bptr, WF_PATCH_BYTES);
800
801 if (snd_wavefront_cmd (dev, WFC_DOWNLOAD_PATCH, NULL, buf)) {
802 snd_printk ("download patch failed\n");
803 return -(EIO);
804 }
805
806 return (0);
807}
808
809static int
810wavefront_send_program (snd_wavefront_t *dev, wavefront_patch_info *header)
811
812{
813 unsigned char buf[WF_PROGRAM_BYTES+1];
814 int i;
815
816 DPRINT (WF_DEBUG_LOAD_PATCH, "downloading program %d\n",
817 header->number);
818
819 dev->prog_status[header->number] = WF_SLOT_USED;
820
821 /* XXX need to zero existing SLOT_USED bit for program_status[i]
822 where `i' is the program that's being (potentially) overwritten.
823 */
824
825 for (i = 0; i < WF_NUM_LAYERS; i++) {
826 if (header->hdr.pr.layer[i].mute) {
827 dev->patch_status[header->hdr.pr.layer[i].patch_number] |=
828 WF_SLOT_USED;
829
830 /* XXX need to mark SLOT_USED for sample used by
831 patch_number, but this means we have to load it. Ick.
832 */
833 }
834 }
835
836 buf[0] = header->number;
837 munge_buf ((unsigned char *)&header->hdr.pr, &buf[1], WF_PROGRAM_BYTES);
838
839 if (snd_wavefront_cmd (dev, WFC_DOWNLOAD_PROGRAM, NULL, buf)) {
840 snd_printk ("download patch failed\n");
841 return -(EIO);
842 }
843
844 return (0);
845}
846
847static int
848wavefront_freemem (snd_wavefront_t *dev)
849
850{
851 char rbuf[8];
852
853 if (snd_wavefront_cmd (dev, WFC_REPORT_FREE_MEMORY, rbuf, NULL)) {
854 snd_printk ("can't get memory stats.\n");
855 return -1;
856 } else {
857 return demunge_int32 (rbuf, 4);
858 }
859}
860
861static int
862wavefront_send_sample (snd_wavefront_t *dev,
863 wavefront_patch_info *header,
864 u16 __user *dataptr,
865 int data_is_unsigned)
866
867{
868 /* samples are downloaded via a 16-bit wide i/o port
869 (you could think of it as 2 adjacent 8-bit wide ports
870 but its less efficient that way). therefore, all
871 the blocksizes and so forth listed in the documentation,
872 and used conventionally to refer to sample sizes,
873 which are given in 8-bit units (bytes), need to be
874 divided by 2.
875 */
876
877 u16 sample_short;
878 u32 length;
879 u16 __user *data_end = NULL;
880 unsigned int i;
881 const unsigned int max_blksize = 4096/2;
882 unsigned int written;
883 unsigned int blocksize;
884 int dma_ack;
885 int blocknum;
886 unsigned char sample_hdr[WF_SAMPLE_HDR_BYTES];
887 unsigned char *shptr;
888 int skip = 0;
889 int initial_skip = 0;
890
891 DPRINT (WF_DEBUG_LOAD_PATCH, "sample %sdownload for slot %d, "
892 "type %d, %d bytes from 0x%lx\n",
893 header->size ? "" : "header ",
894 header->number, header->subkey,
895 header->size,
896 (unsigned long) header->dataptr);
897
898 if (header->number == WAVEFRONT_FIND_FREE_SAMPLE_SLOT) {
899 int x;
900
901 if ((x = wavefront_find_free_sample (dev)) < 0) {
902 return -ENOMEM;
903 }
904 snd_printk ("unspecified sample => %d\n", x);
905 header->number = x;
906 }
907
908 if (header->size) {
909
910 /* XXX it's a debatable point whether or not RDONLY semantics
911 on the ROM samples should cover just the sample data or
912 the sample header. For now, it only covers the sample data,
913 so anyone is free at all times to rewrite sample headers.
914
915 My reason for this is that we have the sample headers
916 available in the WFB file for General MIDI, and so these
917 can always be reset if needed. The sample data, however,
918 cannot be recovered without a complete reset and firmware
919 reload of the ICS2115, which is a very expensive operation.
920
921 So, doing things this way allows us to honor the notion of
922 "RESETSAMPLES" reasonably cheaply. Note however, that this
923 is done purely at user level: there is no WFB parser in
924 this driver, and so a complete reset (back to General MIDI,
925 or theoretically some other configuration) is the
926 responsibility of the user level library.
927
928 To try to do this in the kernel would be a little
929 crazy: we'd need 158K of kernel space just to hold
930 a copy of the patch/program/sample header data.
931 */
932
933 if (dev->rom_samples_rdonly) {
934 if (dev->sample_status[header->number] & WF_SLOT_ROM) {
935 snd_printk ("sample slot %d "
936 "write protected\n",
937 header->number);
938 return -EACCES;
939 }
940 }
941
942 wavefront_delete_sample (dev, header->number);
943 }
944
945 if (header->size) {
946 dev->freemem = wavefront_freemem (dev);
947
948 if (dev->freemem < (int)header->size) {
949 snd_printk ("insufficient memory to "
950 "load %d byte sample.\n",
951 header->size);
952 return -ENOMEM;
953 }
954
955 }
956
957 skip = WF_GET_CHANNEL(&header->hdr.s);
958
959 if (skip > 0 && header->hdr.s.SampleResolution != LINEAR_16BIT) {
960 snd_printk ("channel selection only "
961 "possible on 16-bit samples");
962 return -(EINVAL);
963 }
964
965 switch (skip) {
966 case 0:
967 initial_skip = 0;
968 skip = 1;
969 break;
970 case 1:
971 initial_skip = 0;
972 skip = 2;
973 break;
974 case 2:
975 initial_skip = 1;
976 skip = 2;
977 break;
978 case 3:
979 initial_skip = 2;
980 skip = 3;
981 break;
982 case 4:
983 initial_skip = 3;
984 skip = 4;
985 break;
986 case 5:
987 initial_skip = 4;
988 skip = 5;
989 break;
990 case 6:
991 initial_skip = 5;
992 skip = 6;
993 break;
994 }
995
996 DPRINT (WF_DEBUG_LOAD_PATCH, "channel selection: %d => "
997 "initial skip = %d, skip = %d\n",
998 WF_GET_CHANNEL (&header->hdr.s),
999 initial_skip, skip);
1000
1001 /* Be safe, and zero the "Unused" bits ... */
1002
1003 WF_SET_CHANNEL(&header->hdr.s, 0);
1004
1005 /* adjust size for 16 bit samples by dividing by two. We always
1006 send 16 bits per write, even for 8 bit samples, so the length
1007 is always half the size of the sample data in bytes.
1008 */
1009
1010 length = header->size / 2;
1011
1012 /* the data we're sent has not been munged, and in fact, the
1013 header we have to send isn't just a munged copy either.
1014 so, build the sample header right here.
1015 */
1016
1017 shptr = &sample_hdr[0];
1018
1019 shptr = munge_int32 (header->number, shptr, 2);
1020
1021 if (header->size) {
1022 shptr = munge_int32 (length, shptr, 4);
1023 }
1024
1025 /* Yes, a 4 byte result doesn't contain all of the offset bits,
1026 but the offset only uses 24 bits.
1027 */
1028
1029 shptr = munge_int32 (*((u32 *) &header->hdr.s.sampleStartOffset),
1030 shptr, 4);
1031 shptr = munge_int32 (*((u32 *) &header->hdr.s.loopStartOffset),
1032 shptr, 4);
1033 shptr = munge_int32 (*((u32 *) &header->hdr.s.loopEndOffset),
1034 shptr, 4);
1035 shptr = munge_int32 (*((u32 *) &header->hdr.s.sampleEndOffset),
1036 shptr, 4);
1037
1038 /* This one is truly weird. What kind of weirdo decided that in
1039 a system dominated by 16 and 32 bit integers, they would use
1040 a just 12 bits ?
1041 */
1042
1043 shptr = munge_int32 (header->hdr.s.FrequencyBias, shptr, 3);
1044
1045 /* Why is this nybblified, when the MSB is *always* zero ?
1046 Anyway, we can't take address of bitfield, so make a
1047 good-faith guess at where it starts.
1048 */
1049
1050 shptr = munge_int32 (*(&header->hdr.s.FrequencyBias+1),
1051 shptr, 2);
1052
1053 if (snd_wavefront_cmd (dev,
1054 header->size ?
1055 WFC_DOWNLOAD_SAMPLE : WFC_DOWNLOAD_SAMPLE_HEADER,
1056 NULL, sample_hdr)) {
1057 snd_printk ("sample %sdownload refused.\n",
1058 header->size ? "" : "header ");
1059 return -(EIO);
1060 }
1061
1062 if (header->size == 0) {
1063 goto sent; /* Sorry. Just had to have one somewhere */
1064 }
1065
1066 data_end = dataptr + length;
1067
1068 /* Do any initial skip over an unused channel's data */
1069
1070 dataptr += initial_skip;
1071
1072 for (written = 0, blocknum = 0;
1073 written < length; written += max_blksize, blocknum++) {
1074
1075 if ((length - written) > max_blksize) {
1076 blocksize = max_blksize;
1077 } else {
1078 /* round to nearest 16-byte value */
1079 blocksize = ((length-written+7)&~0x7);
1080 }
1081
1082 if (snd_wavefront_cmd (dev, WFC_DOWNLOAD_BLOCK, NULL, NULL)) {
1083 snd_printk ("download block "
1084 "request refused.\n");
1085 return -(EIO);
1086 }
1087
1088 for (i = 0; i < blocksize; i++) {
1089
1090 if (dataptr < data_end) {
1091
1092 __get_user (sample_short, dataptr);
1093 dataptr += skip;
1094
1095 if (data_is_unsigned) { /* GUS ? */
1096
1097 if (WF_SAMPLE_IS_8BIT(&header->hdr.s)) {
1098
1099 /* 8 bit sample
1100 resolution, sign
1101 extend both bytes.
1102 */
1103
1104 ((unsigned char*)
1105 &sample_short)[0] += 0x7f;
1106 ((unsigned char*)
1107 &sample_short)[1] += 0x7f;
1108
1109 } else {
1110
1111 /* 16 bit sample
1112 resolution, sign
1113 extend the MSB.
1114 */
1115
1116 sample_short += 0x7fff;
1117 }
1118 }
1119
1120 } else {
1121
1122 /* In padding section of final block:
1123
1124 Don't fetch unsupplied data from
1125 user space, just continue with
1126 whatever the final value was.
1127 */
1128 }
1129
1130 if (i < blocksize - 1) {
1131 outw (sample_short, dev->block_port);
1132 } else {
1133 outw (sample_short, dev->last_block_port);
1134 }
1135 }
1136
1137 /* Get "DMA page acknowledge", even though its really
1138 nothing to do with DMA at all.
1139 */
1140
1141 if ((dma_ack = wavefront_read (dev)) != WF_DMA_ACK) {
1142 if (dma_ack == -1) {
1143 snd_printk ("upload sample "
1144 "DMA ack timeout\n");
1145 return -(EIO);
1146 } else {
1147 snd_printk ("upload sample "
1148 "DMA ack error 0x%x\n",
1149 dma_ack);
1150 return -(EIO);
1151 }
1152 }
1153 }
1154
1155 dev->sample_status[header->number] = (WF_SLOT_FILLED|WF_ST_SAMPLE);
1156
1157 /* Note, label is here because sending the sample header shouldn't
1158 alter the sample_status info at all.
1159 */
1160
1161 sent:
1162 return (0);
1163}
1164
1165static int
1166wavefront_send_alias (snd_wavefront_t *dev, wavefront_patch_info *header)
1167
1168{
1169 unsigned char alias_hdr[WF_ALIAS_BYTES];
1170
1171 DPRINT (WF_DEBUG_LOAD_PATCH, "download alias, %d is "
1172 "alias for %d\n",
1173 header->number,
1174 header->hdr.a.OriginalSample);
1175
1176 munge_int32 (header->number, &alias_hdr[0], 2);
1177 munge_int32 (header->hdr.a.OriginalSample, &alias_hdr[2], 2);
1178 munge_int32 (*((unsigned int *)&header->hdr.a.sampleStartOffset),
1179 &alias_hdr[4], 4);
1180 munge_int32 (*((unsigned int *)&header->hdr.a.loopStartOffset),
1181 &alias_hdr[8], 4);
1182 munge_int32 (*((unsigned int *)&header->hdr.a.loopEndOffset),
1183 &alias_hdr[12], 4);
1184 munge_int32 (*((unsigned int *)&header->hdr.a.sampleEndOffset),
1185 &alias_hdr[16], 4);
1186 munge_int32 (header->hdr.a.FrequencyBias, &alias_hdr[20], 3);
1187 munge_int32 (*(&header->hdr.a.FrequencyBias+1), &alias_hdr[23], 2);
1188
1189 if (snd_wavefront_cmd (dev, WFC_DOWNLOAD_SAMPLE_ALIAS, NULL, alias_hdr)) {
1190 snd_printk ("download alias failed.\n");
1191 return -(EIO);
1192 }
1193
1194 dev->sample_status[header->number] = (WF_SLOT_FILLED|WF_ST_ALIAS);
1195
1196 return (0);
1197}
1198
1199static int
1200wavefront_send_multisample (snd_wavefront_t *dev, wavefront_patch_info *header)
1201{
1202 int i;
1203 int num_samples;
1204 unsigned char *msample_hdr;
1205
1206 msample_hdr = kmalloc(sizeof(WF_MSAMPLE_BYTES), GFP_KERNEL);
1207 if (! msample_hdr)
1208 return -ENOMEM;
1209
1210 munge_int32 (header->number, &msample_hdr[0], 2);
1211
1212 /* You'll recall at this point that the "number of samples" value
1213 in a wavefront_multisample struct is actually the log2 of the
1214 real number of samples.
1215 */
1216
1217 num_samples = (1<<(header->hdr.ms.NumberOfSamples&7));
1218 msample_hdr[2] = (unsigned char) header->hdr.ms.NumberOfSamples;
1219
1220 DPRINT (WF_DEBUG_LOAD_PATCH, "multi %d with %d=%d samples\n",
1221 header->number,
1222 header->hdr.ms.NumberOfSamples,
1223 num_samples);
1224
1225 for (i = 0; i < num_samples; i++) {
1226 DPRINT(WF_DEBUG_LOAD_PATCH|WF_DEBUG_DATA, "sample[%d] = %d\n",
1227 i, header->hdr.ms.SampleNumber[i]);
1228 munge_int32 (header->hdr.ms.SampleNumber[i],
1229 &msample_hdr[3+(i*2)], 2);
1230 }
1231
1232 /* Need a hack here to pass in the number of bytes
1233 to be written to the synth. This is ugly, and perhaps
1234 one day, I'll fix it.
1235 */
1236
1237 if (snd_wavefront_cmd (dev, WFC_DOWNLOAD_MULTISAMPLE,
1238 (unsigned char *) (long) ((num_samples*2)+3),
1239 msample_hdr)) {
1240 snd_printk ("download of multisample failed.\n");
1241 kfree(msample_hdr);
1242 return -(EIO);
1243 }
1244
1245 dev->sample_status[header->number] = (WF_SLOT_FILLED|WF_ST_MULTISAMPLE);
1246
1247 kfree(msample_hdr);
1248 return (0);
1249}
1250
1251static int
1252wavefront_fetch_multisample (snd_wavefront_t *dev,
1253 wavefront_patch_info *header)
1254{
1255 int i;
1256 unsigned char log_ns[1];
1257 unsigned char number[2];
1258 int num_samples;
1259
1260 munge_int32 (header->number, number, 2);
1261
1262 if (snd_wavefront_cmd (dev, WFC_UPLOAD_MULTISAMPLE, log_ns, number)) {
1263 snd_printk ("upload multisample failed.\n");
1264 return -(EIO);
1265 }
1266
1267 DPRINT (WF_DEBUG_DATA, "msample %d has %d samples\n",
1268 header->number, log_ns[0]);
1269
1270 header->hdr.ms.NumberOfSamples = log_ns[0];
1271
1272 /* get the number of samples ... */
1273
1274 num_samples = (1 << log_ns[0]);
1275
1276 for (i = 0; i < num_samples; i++) {
1277 char d[2];
1278 int val;
1279
1280 if ((val = wavefront_read (dev)) == -1) {
1281 snd_printk ("upload multisample failed "
1282 "during sample loop.\n");
1283 return -(EIO);
1284 }
1285 d[0] = val;
1286
1287 if ((val = wavefront_read (dev)) == -1) {
1288 snd_printk ("upload multisample failed "
1289 "during sample loop.\n");
1290 return -(EIO);
1291 }
1292 d[1] = val;
1293
1294 header->hdr.ms.SampleNumber[i] =
1295 demunge_int32 ((unsigned char *) d, 2);
1296
1297 DPRINT (WF_DEBUG_DATA, "msample sample[%d] = %d\n",
1298 i, header->hdr.ms.SampleNumber[i]);
1299 }
1300
1301 return (0);
1302}
1303
1304
1305static int
1306wavefront_send_drum (snd_wavefront_t *dev, wavefront_patch_info *header)
1307
1308{
1309 unsigned char drumbuf[WF_DRUM_BYTES];
1310 wavefront_drum *drum = &header->hdr.d;
1311 int i;
1312
1313 DPRINT (WF_DEBUG_LOAD_PATCH, "downloading edrum for MIDI "
1314 "note %d, patch = %d\n",
1315 header->number, drum->PatchNumber);
1316
1317 drumbuf[0] = header->number & 0x7f;
1318
1319 for (i = 0; i < 4; i++) {
1320 munge_int32 (((unsigned char *)drum)[i], &drumbuf[1+(i*2)], 2);
1321 }
1322
1323 if (snd_wavefront_cmd (dev, WFC_DOWNLOAD_EDRUM_PROGRAM, NULL, drumbuf)) {
1324 snd_printk ("download drum failed.\n");
1325 return -(EIO);
1326 }
1327
1328 return (0);
1329}
1330
1331static int
1332wavefront_find_free_sample (snd_wavefront_t *dev)
1333
1334{
1335 int i;
1336
1337 for (i = 0; i < WF_MAX_SAMPLE; i++) {
1338 if (!(dev->sample_status[i] & WF_SLOT_FILLED)) {
1339 return i;
1340 }
1341 }
1342 snd_printk ("no free sample slots!\n");
1343 return -1;
1344}
1345
1346#if 0
1347static int
1348wavefront_find_free_patch (snd_wavefront_t *dev)
1349
1350{
1351 int i;
1352
1353 for (i = 0; i < WF_MAX_PATCH; i++) {
1354 if (!(dev->patch_status[i] & WF_SLOT_FILLED)) {
1355 return i;
1356 }
1357 }
1358 snd_printk ("no free patch slots!\n");
1359 return -1;
1360}
1361#endif
1362
1363static int
1364wavefront_load_patch (snd_wavefront_t *dev, const char __user *addr)
1365{
1366 wavefront_patch_info *header;
1367 int err;
1368
1369 header = kmalloc(sizeof(*header), GFP_KERNEL);
1370 if (! header)
1371 return -ENOMEM;
1372
1373 if (copy_from_user (header, addr, sizeof(wavefront_patch_info) -
1374 sizeof(wavefront_any))) {
1375 snd_printk ("bad address for load patch.\n");
1376 err = -EFAULT;
1377 goto __error;
1378 }
1379
1380 DPRINT (WF_DEBUG_LOAD_PATCH, "download "
1381 "Sample type: %d "
1382 "Sample number: %d "
1383 "Sample size: %d\n",
1384 header->subkey,
1385 header->number,
1386 header->size);
1387
1388 switch (header->subkey) {
1389 case WF_ST_SAMPLE: /* sample or sample_header, based on patch->size */
1390
1391 if (copy_from_user (&header->hdr.s, header->hdrptr,
1392 sizeof (wavefront_sample))) {
1393 err = -EFAULT;
1394 break;
1395 }
1396
1397 err = wavefront_send_sample (dev, header, header->dataptr, 0);
1398 break;
1399
1400 case WF_ST_MULTISAMPLE:
1401
1402 if (copy_from_user (&header->hdr.s, header->hdrptr,
1403 sizeof (wavefront_multisample))) {
1404 err = -EFAULT;
1405 break;
1406 }
1407
1408 err = wavefront_send_multisample (dev, header);
1409 break;
1410
1411 case WF_ST_ALIAS:
1412
1413 if (copy_from_user (&header->hdr.a, header->hdrptr,
1414 sizeof (wavefront_alias))) {
1415 err = -EFAULT;
1416 break;
1417 }
1418
1419 err = wavefront_send_alias (dev, header);
1420 break;
1421
1422 case WF_ST_DRUM:
1423 if (copy_from_user (&header->hdr.d, header->hdrptr,
1424 sizeof (wavefront_drum))) {
1425 err = -EFAULT;
1426 break;
1427 }
1428
1429 err = wavefront_send_drum (dev, header);
1430 break;
1431
1432 case WF_ST_PATCH:
1433 if (copy_from_user (&header->hdr.p, header->hdrptr,
1434 sizeof (wavefront_patch))) {
1435 err = -EFAULT;
1436 break;
1437 }
1438
1439 err = wavefront_send_patch (dev, header);
1440 break;
1441
1442 case WF_ST_PROGRAM:
1443 if (copy_from_user (&header->hdr.pr, header->hdrptr,
1444 sizeof (wavefront_program))) {
1445 err = -EFAULT;
1446 break;
1447 }
1448
1449 err = wavefront_send_program (dev, header);
1450 break;
1451
1452 default:
1453 snd_printk ("unknown patch type %d.\n",
1454 header->subkey);
1455 err = -EINVAL;
1456 break;
1457 }
1458
1459 __error:
1460 kfree(header);
1461 return err;
1462}
1463
1464/***********************************************************************
1465WaveFront: hardware-dependent interface
1466***********************************************************************/
1467
1468static void
1469process_sample_hdr (u8 *buf)
1470
1471{
1472 wavefront_sample s;
1473 u8 *ptr;
1474
1475 ptr = buf;
1476
1477 /* The board doesn't send us an exact copy of a "wavefront_sample"
1478 in response to an Upload Sample Header command. Instead, we
1479 have to convert the data format back into our data structure,
1480 just as in the Download Sample command, where we have to do
1481 something very similar in the reverse direction.
1482 */
1483
1484 *((u32 *) &s.sampleStartOffset) = demunge_int32 (ptr, 4); ptr += 4;
1485 *((u32 *) &s.loopStartOffset) = demunge_int32 (ptr, 4); ptr += 4;
1486 *((u32 *) &s.loopEndOffset) = demunge_int32 (ptr, 4); ptr += 4;
1487 *((u32 *) &s.sampleEndOffset) = demunge_int32 (ptr, 4); ptr += 4;
1488 *((u32 *) &s.FrequencyBias) = demunge_int32 (ptr, 3); ptr += 3;
1489
1490 s.SampleResolution = *ptr & 0x3;
1491 s.Loop = *ptr & 0x8;
1492 s.Bidirectional = *ptr & 0x10;
1493 s.Reverse = *ptr & 0x40;
1494
1495 /* Now copy it back to where it came from */
1496
1497 memcpy (buf, (unsigned char *) &s, sizeof (wavefront_sample));
1498}
1499
1500static int
1501wavefront_synth_control (snd_wavefront_card_t *acard,
1502 wavefront_control *wc)
1503
1504{
1505 snd_wavefront_t *dev = &acard->wavefront;
1506 unsigned char patchnumbuf[2];
1507 int i;
1508
1509 DPRINT (WF_DEBUG_CMD, "synth control with "
1510 "cmd 0x%x\n", wc->cmd);
1511
1512 /* Pre-handling of or for various commands */
1513
1514 switch (wc->cmd) {
1515
1516 case WFC_DISABLE_INTERRUPTS:
1517 snd_printk ("interrupts disabled.\n");
1518 outb (0x80|0x20, dev->control_port);
1519 dev->interrupts_are_midi = 1;
1520 return 0;
1521
1522 case WFC_ENABLE_INTERRUPTS:
1523 snd_printk ("interrupts enabled.\n");
1524 outb (0x80|0x40|0x20, dev->control_port);
1525 dev->interrupts_are_midi = 1;
1526 return 0;
1527
1528 case WFC_INTERRUPT_STATUS:
1529 wc->rbuf[0] = dev->interrupts_are_midi;
1530 return 0;
1531
1532 case WFC_ROMSAMPLES_RDONLY:
1533 dev->rom_samples_rdonly = wc->wbuf[0];
1534 wc->status = 0;
1535 return 0;
1536
1537 case WFC_IDENTIFY_SLOT_TYPE:
1538 i = wc->wbuf[0] | (wc->wbuf[1] << 7);
1539 if (i <0 || i >= WF_MAX_SAMPLE) {
1540 snd_printk ("invalid slot ID %d\n",
1541 i);
1542 wc->status = EINVAL;
1543 return -EINVAL;
1544 }
1545 wc->rbuf[0] = dev->sample_status[i];
1546 wc->status = 0;
1547 return 0;
1548
1549 case WFC_DEBUG_DRIVER:
1550 dev->debug = wc->wbuf[0];
1551 snd_printk ("debug = 0x%x\n", dev->debug);
1552 return 0;
1553
1554 case WFC_UPLOAD_PATCH:
1555 munge_int32 (*((u32 *) wc->wbuf), patchnumbuf, 2);
1556 memcpy (wc->wbuf, patchnumbuf, 2);
1557 break;
1558
1559 case WFC_UPLOAD_MULTISAMPLE:
1560 /* multisamples have to be handled differently, and
1561 cannot be dealt with properly by snd_wavefront_cmd() alone.
1562 */
1563 wc->status = wavefront_fetch_multisample
1564 (dev, (wavefront_patch_info *) wc->rbuf);
1565 return 0;
1566
1567 case WFC_UPLOAD_SAMPLE_ALIAS:
1568 snd_printk ("support for sample alias upload "
1569 "being considered.\n");
1570 wc->status = EINVAL;
1571 return -EINVAL;
1572 }
1573
1574 wc->status = snd_wavefront_cmd (dev, wc->cmd, wc->rbuf, wc->wbuf);
1575
1576 /* Post-handling of certain commands.
1577
1578 In particular, if the command was an upload, demunge the data
1579 so that the user-level doesn't have to think about it.
1580 */
1581
1582 if (wc->status == 0) {
1583 switch (wc->cmd) {
1584 /* intercept any freemem requests so that we know
1585 we are always current with the user-level view
1586 of things.
1587 */
1588
1589 case WFC_REPORT_FREE_MEMORY:
1590 dev->freemem = demunge_int32 (wc->rbuf, 4);
1591 break;
1592
1593 case WFC_UPLOAD_PATCH:
1594 demunge_buf (wc->rbuf, wc->rbuf, WF_PATCH_BYTES);
1595 break;
1596
1597 case WFC_UPLOAD_PROGRAM:
1598 demunge_buf (wc->rbuf, wc->rbuf, WF_PROGRAM_BYTES);
1599 break;
1600
1601 case WFC_UPLOAD_EDRUM_PROGRAM:
1602 demunge_buf (wc->rbuf, wc->rbuf, WF_DRUM_BYTES - 1);
1603 break;
1604
1605 case WFC_UPLOAD_SAMPLE_HEADER:
1606 process_sample_hdr (wc->rbuf);
1607 break;
1608
1609 case WFC_UPLOAD_SAMPLE_ALIAS:
1610 snd_printk ("support for "
1611 "sample aliases still "
1612 "being considered.\n");
1613 break;
1614
1615 case WFC_VMIDI_OFF:
1616 snd_wavefront_midi_disable_virtual (acard);
1617 break;
1618
1619 case WFC_VMIDI_ON:
1620 snd_wavefront_midi_enable_virtual (acard);
1621 break;
1622 }
1623 }
1624
1625 return 0;
1626}
1627
1628int
1629snd_wavefront_synth_open (snd_hwdep_t *hw, struct file *file)
1630
1631{
1632 if (!try_module_get(hw->card->module))
1633 return -EFAULT;
1634 file->private_data = hw;
1635 return 0;
1636}
1637
1638int
1639snd_wavefront_synth_release (snd_hwdep_t *hw, struct file *file)
1640
1641{
1642 module_put(hw->card->module);
1643 return 0;
1644}
1645
1646int
1647snd_wavefront_synth_ioctl (snd_hwdep_t *hw, struct file *file,
1648 unsigned int cmd, unsigned long arg)
1649
1650{
1651 snd_card_t *card;
1652 snd_wavefront_t *dev;
1653 snd_wavefront_card_t *acard;
1654 wavefront_control *wc;
1655 void __user *argp = (void __user *)arg;
1656 int err;
1657
1658 card = (snd_card_t *) hw->card;
1659
1660 snd_assert(card != NULL, return -ENODEV);
1661
1662 snd_assert(card->private_data != NULL, return -ENODEV);
1663
1664 acard = card->private_data;
1665 dev = &acard->wavefront;
1666
1667 switch (cmd) {
1668 case WFCTL_LOAD_SPP:
1669 if (wavefront_load_patch (dev, argp) != 0) {
1670 return -EIO;
1671 }
1672 break;
1673
1674 case WFCTL_WFCMD:
1675 wc = kmalloc(sizeof(*wc), GFP_KERNEL);
1676 if (! wc)
1677 return -ENOMEM;
1678 if (copy_from_user (wc, argp, sizeof (*wc)))
1679 err = -EFAULT;
1680 else if (wavefront_synth_control (acard, wc) < 0)
1681 err = -EIO;
1682 else if (copy_to_user (argp, wc, sizeof (*wc)))
1683 err = -EFAULT;
1684 else
1685 err = 0;
1686 kfree(wc);
1687 return err;
1688
1689 default:
1690 return -EINVAL;
1691 }
1692
1693 return 0;
1694}
1695
1696
1697/***********************************************************************/
1698/* WaveFront: interface for card-level wavefront module */
1699/***********************************************************************/
1700
1701void
1702snd_wavefront_internal_interrupt (snd_wavefront_card_t *card)
1703{
1704 snd_wavefront_t *dev = &card->wavefront;
1705
1706 /*
1707 Some comments on interrupts. I attempted a version of this
1708 driver that used interrupts throughout the code instead of
1709 doing busy and/or sleep-waiting. Alas, it appears that once
1710 the Motorola firmware is downloaded, the card *never*
1711 generates an RX interrupt. These are successfully generated
1712 during firmware loading, and after that wavefront_status()
1713 reports that an interrupt is pending on the card from time
1714 to time, but it never seems to be delivered to this
1715 driver. Note also that wavefront_status() continues to
1716 report that RX interrupts are enabled, suggesting that I
1717 didn't goof up and disable them by mistake.
1718
1719 Thus, I stepped back to a prior version of
1720 wavefront_wait(), the only place where this really
1721 matters. Its sad, but I've looked through the code to check
1722 on things, and I really feel certain that the Motorola
1723 firmware prevents RX-ready interrupts.
1724 */
1725
1726 if ((wavefront_status(dev) & (STAT_INTR_READ|STAT_INTR_WRITE)) == 0) {
1727 return;
1728 }
1729
1730 spin_lock(&dev->irq_lock);
1731 dev->irq_ok = 1;
1732 dev->irq_cnt++;
1733 spin_unlock(&dev->irq_lock);
1734 wake_up(&dev->interrupt_sleeper);
1735}
1736
1737/* STATUS REGISTER
1738
17390 Host Rx Interrupt Enable (1=Enabled)
17401 Host Rx Register Full (1=Full)
17412 Host Rx Interrupt Pending (1=Interrupt)
17423 Unused
17434 Host Tx Interrupt (1=Enabled)
17445 Host Tx Register empty (1=Empty)
17456 Host Tx Interrupt Pending (1=Interrupt)
17467 Unused
1747*/
1748
1749static int __init
1750snd_wavefront_interrupt_bits (int irq)
1751
1752{
1753 int bits;
1754
1755 switch (irq) {
1756 case 9:
1757 bits = 0x00;
1758 break;
1759 case 5:
1760 bits = 0x08;
1761 break;
1762 case 12:
1763 bits = 0x10;
1764 break;
1765 case 15:
1766 bits = 0x18;
1767 break;
1768
1769 default:
1770 snd_printk ("invalid IRQ %d\n", irq);
1771 bits = -1;
1772 }
1773
1774 return bits;
1775}
1776
1777static void __init
1778wavefront_should_cause_interrupt (snd_wavefront_t *dev,
1779 int val, int port, int timeout)
1780
1781{
1782 wait_queue_t wait;
1783
1784 init_waitqueue_entry(&wait, current);
1785 spin_lock_irq(&dev->irq_lock);
1786 add_wait_queue(&dev->interrupt_sleeper, &wait);
1787 dev->irq_ok = 0;
1788 outb (val,port);
1789 spin_unlock_irq(&dev->irq_lock);
1790 while (1) {
1791 set_current_state(TASK_INTERRUPTIBLE);
1792 if ((timeout = schedule_timeout(timeout)) == 0)
1793 return;
1794 if (dev->irq_ok)
1795 return;
1796 }
1797}
1798
1799static int __init
1800wavefront_reset_to_cleanliness (snd_wavefront_t *dev)
1801
1802{
1803 int bits;
1804 int hwv[2];
1805
1806 /* IRQ already checked */
1807
1808 bits = snd_wavefront_interrupt_bits (dev->irq);
1809
1810 /* try reset of port */
1811
1812 outb (0x0, dev->control_port);
1813
1814 /* At this point, the board is in reset, and the H/W initialization
1815 register is accessed at the same address as the data port.
1816
1817 Bit 7 - Enable IRQ Driver
1818 0 - Tri-state the Wave-Board drivers for the PC Bus IRQs
1819 1 - Enable IRQ selected by bits 5:3 to be driven onto the PC Bus.
1820
1821 Bit 6 - MIDI Interface Select
1822
1823 0 - Use the MIDI Input from the 26-pin WaveBlaster
1824 compatible header as the serial MIDI source
1825 1 - Use the MIDI Input from the 9-pin D connector as the
1826 serial MIDI source.
1827
1828 Bits 5:3 - IRQ Selection
1829 0 0 0 - IRQ 2/9
1830 0 0 1 - IRQ 5
1831 0 1 0 - IRQ 12
1832 0 1 1 - IRQ 15
1833 1 0 0 - Reserved
1834 1 0 1 - Reserved
1835 1 1 0 - Reserved
1836 1 1 1 - Reserved
1837
1838 Bits 2:1 - Reserved
1839 Bit 0 - Disable Boot ROM
1840 0 - memory accesses to 03FC30-03FFFFH utilize the internal Boot ROM
1841 1 - memory accesses to 03FC30-03FFFFH are directed to external
1842 storage.
1843
1844 */
1845
1846 /* configure hardware: IRQ, enable interrupts,
1847 plus external 9-pin MIDI interface selected
1848 */
1849
1850 outb (0x80 | 0x40 | bits, dev->data_port);
1851
1852 /* CONTROL REGISTER
1853
1854 0 Host Rx Interrupt Enable (1=Enabled) 0x1
1855 1 Unused 0x2
1856 2 Unused 0x4
1857 3 Unused 0x8
1858 4 Host Tx Interrupt Enable 0x10
1859 5 Mute (0=Mute; 1=Play) 0x20
1860 6 Master Interrupt Enable (1=Enabled) 0x40
1861 7 Master Reset (0=Reset; 1=Run) 0x80
1862
1863 Take us out of reset, mute output, master + TX + RX interrupts on.
1864
1865 We'll get an interrupt presumably to tell us that the TX
1866 register is clear.
1867 */
1868
1869 wavefront_should_cause_interrupt(dev, 0x80|0x40|0x10|0x1,
1870 dev->control_port,
1871 (reset_time*HZ)/100);
1872
1873 /* Note: data port is now the data port, not the h/w initialization
1874 port.
1875 */
1876
1877 if (!dev->irq_ok) {
1878 snd_printk ("intr not received after h/w un-reset.\n");
1879 goto gone_bad;
1880 }
1881
1882 /* Note: data port is now the data port, not the h/w initialization
1883 port.
1884
1885 At this point, only "HW VERSION" or "DOWNLOAD OS" commands
1886 will work. So, issue one of them, and wait for TX
1887 interrupt. This can take a *long* time after a cold boot,
1888 while the ISC ROM does its RAM test. The SDK says up to 4
1889 seconds - with 12MB of RAM on a Tropez+, it takes a lot
1890 longer than that (~16secs). Note that the card understands
1891 the difference between a warm and a cold boot, so
1892 subsequent ISC2115 reboots (say, caused by module
1893 reloading) will get through this much faster.
1894
1895 XXX Interesting question: why is no RX interrupt received first ?
1896 */
1897
1898 wavefront_should_cause_interrupt(dev, WFC_HARDWARE_VERSION,
1899 dev->data_port, ramcheck_time*HZ);
1900
1901 if (!dev->irq_ok) {
1902 snd_printk ("post-RAM-check interrupt not received.\n");
1903 goto gone_bad;
1904 }
1905
1906 if (!wavefront_wait (dev, STAT_CAN_READ)) {
1907 snd_printk ("no response to HW version cmd.\n");
1908 goto gone_bad;
1909 }
1910
1911 if ((hwv[0] = wavefront_read (dev)) == -1) {
1912 snd_printk ("board not responding correctly.\n");
1913 goto gone_bad;
1914 }
1915
1916 if (hwv[0] == 0xFF) { /* NAK */
1917
1918 /* Board's RAM test failed. Try to read error code,
1919 and tell us about it either way.
1920 */
1921
1922 if ((hwv[0] = wavefront_read (dev)) == -1) {
1923 snd_printk ("on-board RAM test failed "
1924 "(bad error code).\n");
1925 } else {
1926 snd_printk ("on-board RAM test failed "
1927 "(error code: 0x%x).\n",
1928 hwv[0]);
1929 }
1930 goto gone_bad;
1931 }
1932
1933 /* We're OK, just get the next byte of the HW version response */
1934
1935 if ((hwv[1] = wavefront_read (dev)) == -1) {
1936 snd_printk ("incorrect h/w response.\n");
1937 goto gone_bad;
1938 }
1939
1940 snd_printk ("hardware version %d.%d\n",
1941 hwv[0], hwv[1]);
1942
1943 return 0;
1944
1945
1946 gone_bad:
1947 return (1);
1948}
1949
1950#include <linux/fs.h>
1951#include <linux/mm.h>
1952#include <linux/slab.h>
1953#include <linux/unistd.h>
1954#include <linux/syscalls.h>
1955#include <asm/uaccess.h>
1956
1957
1958static int __init
1959wavefront_download_firmware (snd_wavefront_t *dev, char *path)
1960
1961{
1962 unsigned char section[WF_SECTION_MAX];
1963 signed char section_length; /* yes, just a char; max value is WF_SECTION_MAX */
1964 int section_cnt_downloaded = 0;
1965 int fd;
1966 int c;
1967 int i;
1968 mm_segment_t fs;
1969
1970 /* This tries to be a bit cleverer than the stuff Alan Cox did for
1971 the generic sound firmware, in that it actually knows
1972 something about the structure of the Motorola firmware. In
1973 particular, it uses a version that has been stripped of the
1974 20K of useless header information, and had section lengths
1975 added, making it possible to load the entire OS without any
1976 [kv]malloc() activity, since the longest entity we ever read is
1977 42 bytes (well, WF_SECTION_MAX) long.
1978 */
1979
1980 fs = get_fs();
1981 set_fs (get_ds());
1982
1983 if ((fd = sys_open ((char __user *) path, 0, 0)) < 0) {
1984 snd_printk ("Unable to load \"%s\".\n",
1985 path);
1986 return 1;
1987 }
1988
1989 while (1) {
1990 int x;
1991
1992 if ((x = sys_read (fd, (char __user *) &section_length, sizeof (section_length))) !=
1993 sizeof (section_length)) {
1994 snd_printk ("firmware read error.\n");
1995 goto failure;
1996 }
1997
1998 if (section_length == 0) {
1999 break;
2000 }
2001
2002 if (section_length < 0 || section_length > WF_SECTION_MAX) {
2003 snd_printk ("invalid firmware section length %d\n",
2004 section_length);
2005 goto failure;
2006 }
2007
2008 if (sys_read (fd, (char __user *) section, section_length) != section_length) {
2009 snd_printk ("firmware section "
2010 "read error.\n");
2011 goto failure;
2012 }
2013
2014 /* Send command */
2015
2016 if (wavefront_write (dev, WFC_DOWNLOAD_OS)) {
2017 goto failure;
2018 }
2019
2020 for (i = 0; i < section_length; i++) {
2021 if (wavefront_write (dev, section[i])) {
2022 goto failure;
2023 }
2024 }
2025
2026 /* get ACK */
2027
2028 if (wavefront_wait (dev, STAT_CAN_READ)) {
2029
2030 if ((c = inb (dev->data_port)) != WF_ACK) {
2031
2032 snd_printk ("download "
2033 "of section #%d not "
2034 "acknowledged, ack = 0x%x\n",
2035 section_cnt_downloaded + 1, c);
2036 goto failure;
2037
2038 }
2039
2040 } else {
2041 snd_printk ("time out for firmware ACK.\n");
2042 goto failure;
2043 }
2044
2045 }
2046
2047 sys_close (fd);
2048 set_fs (fs);
2049 return 0;
2050
2051 failure:
2052 sys_close (fd);
2053 set_fs (fs);
2054 snd_printk ("firmware download failed!!!\n");
2055 return 1;
2056}
2057
2058
2059static int __init
2060wavefront_do_reset (snd_wavefront_t *dev)
2061
2062{
2063 char voices[1];
2064
2065 if (wavefront_reset_to_cleanliness (dev)) {
2066 snd_printk ("hw reset failed.\n");
2067 goto gone_bad;
2068 }
2069
2070 if (dev->israw) {
2071 if (wavefront_download_firmware (dev, ospath)) {
2072 goto gone_bad;
2073 }
2074
2075 dev->israw = 0;
2076
2077 /* Wait for the OS to get running. The protocol for
2078 this is non-obvious, and was determined by
2079 using port-IO tracing in DOSemu and some
2080 experimentation here.
2081
2082 Rather than using timed waits, use interrupts creatively.
2083 */
2084
2085 wavefront_should_cause_interrupt (dev, WFC_NOOP,
2086 dev->data_port,
2087 (osrun_time*HZ));
2088
2089 if (!dev->irq_ok) {
2090 snd_printk ("no post-OS interrupt.\n");
2091 goto gone_bad;
2092 }
2093
2094 /* Now, do it again ! */
2095
2096 wavefront_should_cause_interrupt (dev, WFC_NOOP,
2097 dev->data_port, (10*HZ));
2098
2099 if (!dev->irq_ok) {
2100 snd_printk ("no post-OS interrupt(2).\n");
2101 goto gone_bad;
2102 }
2103
2104 /* OK, no (RX/TX) interrupts any more, but leave mute
2105 in effect.
2106 */
2107
2108 outb (0x80|0x40, dev->control_port);
2109 }
2110
2111 /* SETUPSND.EXE asks for sample memory config here, but since i
2112 have no idea how to interpret the result, we'll forget
2113 about it.
2114 */
2115
2116 if ((dev->freemem = wavefront_freemem (dev)) < 0) {
2117 goto gone_bad;
2118 }
2119
2120 snd_printk ("available DRAM %dk\n", dev->freemem / 1024);
2121
2122 if (wavefront_write (dev, 0xf0) ||
2123 wavefront_write (dev, 1) ||
2124 (wavefront_read (dev) < 0)) {
2125 dev->debug = 0;
2126 snd_printk ("MPU emulation mode not set.\n");
2127 goto gone_bad;
2128 }
2129
2130 voices[0] = 32;
2131
2132 if (snd_wavefront_cmd (dev, WFC_SET_NVOICES, NULL, voices)) {
2133 snd_printk ("cannot set number of voices to 32.\n");
2134 goto gone_bad;
2135 }
2136
2137
2138 return 0;
2139
2140 gone_bad:
2141 /* reset that sucker so that it doesn't bother us. */
2142
2143 outb (0x0, dev->control_port);
2144 dev->interrupts_are_midi = 0;
2145 return 1;
2146}
2147
2148int __init
2149snd_wavefront_start (snd_wavefront_t *dev)
2150
2151{
2152 int samples_are_from_rom;
2153
2154 /* IMPORTANT: assumes that snd_wavefront_detect() and/or
2155 wavefront_reset_to_cleanliness() has already been called
2156 */
2157
2158 if (dev->israw) {
2159 samples_are_from_rom = 1;
2160 } else {
2161 /* XXX is this always true ? */
2162 samples_are_from_rom = 0;
2163 }
2164
2165 if (dev->israw || fx_raw) {
2166 if (wavefront_do_reset (dev)) {
2167 return -1;
2168 }
2169 }
2170 /* Check for FX device, present only on Tropez+ */
2171
2172 dev->has_fx = (snd_wavefront_fx_detect (dev) == 0);
2173
2174 if (dev->has_fx && fx_raw) {
2175 snd_wavefront_fx_start (dev);
2176 }
2177
2178 wavefront_get_sample_status (dev, samples_are_from_rom);
2179 wavefront_get_program_status (dev);
2180 wavefront_get_patch_status (dev);
2181
2182 /* Start normal operation: unreset, master interrupt enabled, no mute
2183 */
2184
2185 outb (0x80|0x40|0x20, dev->control_port);
2186
2187 return (0);
2188}
2189
2190int __init
2191snd_wavefront_detect (snd_wavefront_card_t *card)
2192
2193{
2194 unsigned char rbuf[4], wbuf[4];
2195 snd_wavefront_t *dev = &card->wavefront;
2196
2197 /* returns zero if a WaveFront card is successfully detected.
2198 negative otherwise.
2199 */
2200
2201 dev->israw = 0;
2202 dev->has_fx = 0;
2203 dev->debug = debug_default;
2204 dev->interrupts_are_midi = 0;
2205 dev->irq_cnt = 0;
2206 dev->rom_samples_rdonly = 1;
2207
2208 if (snd_wavefront_cmd (dev, WFC_FIRMWARE_VERSION, rbuf, wbuf) == 0) {
2209
2210 dev->fw_version[0] = rbuf[0];
2211 dev->fw_version[1] = rbuf[1];
2212
2213 snd_printk ("firmware %d.%d already loaded.\n",
2214 rbuf[0], rbuf[1]);
2215
2216 /* check that a command actually works */
2217
2218 if (snd_wavefront_cmd (dev, WFC_HARDWARE_VERSION,
2219 rbuf, wbuf) == 0) {
2220 dev->hw_version[0] = rbuf[0];
2221 dev->hw_version[1] = rbuf[1];
2222 } else {
2223 snd_printk ("not raw, but no "
2224 "hardware version!\n");
2225 return -1;
2226 }
2227
2228 if (!wf_raw) {
2229 return 0;
2230 } else {
2231 snd_printk ("reloading firmware as you requested.\n");
2232 dev->israw = 1;
2233 }
2234
2235 } else {
2236
2237 dev->israw = 1;
2238 snd_printk ("no response to firmware probe, assume raw.\n");
2239
2240 }
2241
2242 return 0;
2243}