1/*
2 *  card-als4000.c - driver for Avance Logic ALS4000 based soundcards.
3 *  Copyright (C) 2000 by Bart Hartgers <bart@etpmod.phys.tue.nl>,
4 *			  Jaroslav Kysela <perex@suse.cz>
5 *  Copyright (C) 2002 by Andreas Mohr <hw7oshyuv3001@sneakemail.com>
6 *
7 *  Framework borrowed from Massimo Piccioni's card-als100.c.
8 *
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 * NOTES
25 *
26 *  Since Avance does not provide any meaningful documentation, and I
27 *  bought an ALS4000 based soundcard, I was forced to base this driver
28 *  on reverse engineering.
29 *
30 *  Note: this is no longer true. Pretty verbose chip docu (ALS4000a.PDF)
31 *  can be found on the ALSA web site.
32 *
33 *  The ALS4000 seems to be the PCI-cousin of the ALS100. It contains an
34 *  ALS100-like SB DSP/mixer, an OPL3 synth, a MPU401 and a gameport
35 *  interface. These subsystems can be mapped into ISA io-port space,
36 *  using the PCI-interface. In addition, the PCI-bit provides DMA and IRQ
37 *  services to the subsystems.
38 *
39 * While ALS4000 is very similar to a SoundBlaster, the differences in
40 * DMA and capturing require more changes to the SoundBlaster than
41 * desirable, so I made this separate driver.
42 *
43 * The ALS4000 can do real full duplex playback/capture.
44 *
45 * FMDAC:
46 * - 0x4f -> port 0x14
47 * - port 0x15 |= 1
48 *
49 * Enable/disable 3D sound:
50 * - 0x50 -> port 0x14
51 * - change bit 6 (0x40) of port 0x15
52 *
53 * Set QSound:
54 * - 0xdb -> port 0x14
55 * - set port 0x15:
56 *   0x3e (mode 3), 0x3c (mode 2), 0x3a (mode 1), 0x38 (mode 0)
57 *
58 * Set KSound:
59 * - value -> some port 0x0c0d
60 *
61 * ToDo:
62 * - Proper shared IRQ handling?
63 * - power management? (card can do voice wakeup according to datasheet!!)
64 */
65
66#include <sound/driver.h>
67#include <asm/io.h>
68#include <linux/init.h>
69#include <linux/pci.h>
70#include <linux/slab.h>
71#include <linux/gameport.h>
72#include <linux/moduleparam.h>
73#include <linux/dma-mapping.h>
74#include <sound/core.h>
75#include <sound/pcm.h>
76#include <sound/rawmidi.h>
77#include <sound/mpu401.h>
78#include <sound/opl3.h>
79#include <sound/sb.h>
80#include <sound/initval.h>
81
82MODULE_AUTHOR("Bart Hartgers <bart@etpmod.phys.tue.nl>");
83MODULE_DESCRIPTION("Avance Logic ALS4000");
84MODULE_LICENSE("GPL");
85MODULE_SUPPORTED_DEVICE("{{Avance Logic,ALS4000}}");
86
87#if defined(CONFIG_GAMEPORT) || (defined(MODULE) && defined(CONFIG_GAMEPORT_MODULE))
88#define SUPPORT_JOYSTICK 1
89#endif
90
91static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX;	/* Index 0-MAX */
92static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR;	/* ID for this card */
93static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP;	/* Enable this card */
94#ifdef SUPPORT_JOYSTICK
95static int joystick_port[SNDRV_CARDS];
96#endif
97
98module_param_array(index, int, NULL, 0444);
99MODULE_PARM_DESC(index, "Index value for ALS4000 soundcard.");
100module_param_array(id, charp, NULL, 0444);
101MODULE_PARM_DESC(id, "ID string for ALS4000 soundcard.");
102module_param_array(enable, bool, NULL, 0444);
103MODULE_PARM_DESC(enable, "Enable ALS4000 soundcard.");
104#ifdef SUPPORT_JOYSTICK
105module_param_array(joystick_port, int, NULL, 0444);
106MODULE_PARM_DESC(joystick_port, "Joystick port address for ALS4000 soundcard. (0 = disabled)");
107#endif
108
109struct snd_card_als4000 {
110	/* most frequent access first */
111	unsigned long gcr;
112	struct pci_dev *pci;
113	struct snd_sb *chip;
114#ifdef SUPPORT_JOYSTICK
115	struct gameport *gameport;
116#endif
117};
118
119static struct pci_device_id snd_als4000_ids[] = {
120	{ 0x4005, 0x4000, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, },   /* ALS4000 */
121	{ 0, }
122};
123
124MODULE_DEVICE_TABLE(pci, snd_als4000_ids);
125
126static inline void snd_als4000_gcr_write_addr(unsigned long port, u32 reg, u32 val)
127{
128	outb(reg, port+0x0c);
129	outl(val, port+0x08);
130}
131
132static inline void snd_als4000_gcr_write(struct snd_sb *sb, u32 reg, u32 val)
133{
134	snd_als4000_gcr_write_addr(sb->alt_port, reg, val);
135}
136
137static inline u32 snd_als4000_gcr_read_addr(unsigned long port, u32 reg)
138{
139	outb(reg, port+0x0c);
140	return inl(port+0x08);
141}
142
143static inline u32 snd_als4000_gcr_read(struct snd_sb *sb, u32 reg)
144{
145	return snd_als4000_gcr_read_addr(sb->alt_port, reg);
146}
147
148static void snd_als4000_set_rate(struct snd_sb *chip, unsigned int rate)
149{
150	if (!(chip->mode & SB_RATE_LOCK)) {
151		snd_sbdsp_command(chip, SB_DSP_SAMPLE_RATE_OUT);
152		snd_sbdsp_command(chip, rate>>8);
153		snd_sbdsp_command(chip, rate);
154	}
155}
156
157static inline void snd_als4000_set_capture_dma(struct snd_sb *chip,
158					       dma_addr_t addr, unsigned size)
159{
160	snd_als4000_gcr_write(chip, 0xa2, addr);
161	snd_als4000_gcr_write(chip, 0xa3, (size-1));
162}
163
164static inline void snd_als4000_set_playback_dma(struct snd_sb *chip,
165						dma_addr_t addr, unsigned size)
166{
167	snd_als4000_gcr_write(chip, 0x91, addr);
168	snd_als4000_gcr_write(chip, 0x92, (size-1)|0x180000);
169}
170
171#define ALS4000_FORMAT_SIGNED	(1<<0)
172#define ALS4000_FORMAT_16BIT	(1<<1)
173#define ALS4000_FORMAT_STEREO	(1<<2)
174
175static int snd_als4000_get_format(struct snd_pcm_runtime *runtime)
176{
177	int result;
178
179	result = 0;
180	if (snd_pcm_format_signed(runtime->format))
181		result |= ALS4000_FORMAT_SIGNED;
182	if (snd_pcm_format_physical_width(runtime->format) == 16)
183		result |= ALS4000_FORMAT_16BIT;
184	if (runtime->channels > 1)
185		result |= ALS4000_FORMAT_STEREO;
186	return result;
187}
188
189/* structure for setting up playback */
190static const struct {
191	unsigned char dsp_cmd, dma_on, dma_off, format;
192} playback_cmd_vals[]={
193/* ALS4000_FORMAT_U8_MONO */
194{ SB_DSP4_OUT8_AI, SB_DSP_DMA8_ON, SB_DSP_DMA8_OFF, SB_DSP4_MODE_UNS_MONO },
195/* ALS4000_FORMAT_S8_MONO */
196{ SB_DSP4_OUT8_AI, SB_DSP_DMA8_ON, SB_DSP_DMA8_OFF, SB_DSP4_MODE_SIGN_MONO },
197/* ALS4000_FORMAT_U16L_MONO */
198{ SB_DSP4_OUT16_AI, SB_DSP_DMA16_ON, SB_DSP_DMA16_OFF, SB_DSP4_MODE_UNS_MONO },
199/* ALS4000_FORMAT_S16L_MONO */
200{ SB_DSP4_OUT16_AI, SB_DSP_DMA16_ON, SB_DSP_DMA16_OFF, SB_DSP4_MODE_SIGN_MONO },
201/* ALS4000_FORMAT_U8_STEREO */
202{ SB_DSP4_OUT8_AI, SB_DSP_DMA8_ON, SB_DSP_DMA8_OFF, SB_DSP4_MODE_UNS_STEREO },
203/* ALS4000_FORMAT_S8_STEREO */
204{ SB_DSP4_OUT8_AI, SB_DSP_DMA8_ON, SB_DSP_DMA8_OFF, SB_DSP4_MODE_SIGN_STEREO },
205/* ALS4000_FORMAT_U16L_STEREO */
206{ SB_DSP4_OUT16_AI, SB_DSP_DMA16_ON, SB_DSP_DMA16_OFF, SB_DSP4_MODE_UNS_STEREO },
207/* ALS4000_FORMAT_S16L_STEREO */
208{ SB_DSP4_OUT16_AI, SB_DSP_DMA16_ON, SB_DSP_DMA16_OFF, SB_DSP4_MODE_SIGN_STEREO },
209};
210#define playback_cmd(chip) (playback_cmd_vals[(chip)->playback_format])
211
212/* structure for setting up capture */
213enum { CMD_WIDTH8=0x04, CMD_SIGNED=0x10, CMD_MONO=0x80, CMD_STEREO=0xA0 };
214static const unsigned char capture_cmd_vals[]=
215{
216CMD_WIDTH8|CMD_MONO,			/* ALS4000_FORMAT_U8_MONO */
217CMD_WIDTH8|CMD_SIGNED|CMD_MONO,		/* ALS4000_FORMAT_S8_MONO */
218CMD_MONO,				/* ALS4000_FORMAT_U16L_MONO */
219CMD_SIGNED|CMD_MONO,			/* ALS4000_FORMAT_S16L_MONO */
220CMD_WIDTH8|CMD_STEREO,			/* ALS4000_FORMAT_U8_STEREO */
221CMD_WIDTH8|CMD_SIGNED|CMD_STEREO,	/* ALS4000_FORMAT_S8_STEREO */
222CMD_STEREO,				/* ALS4000_FORMAT_U16L_STEREO */
223CMD_SIGNED|CMD_STEREO,			/* ALS4000_FORMAT_S16L_STEREO */
224};
225#define capture_cmd(chip) (capture_cmd_vals[(chip)->capture_format])
226
227static int snd_als4000_hw_params(struct snd_pcm_substream *substream,
228				 struct snd_pcm_hw_params *hw_params)
229{
230	return snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(hw_params));
231}
232
233static int snd_als4000_hw_free(struct snd_pcm_substream *substream)
234{
235	snd_pcm_lib_free_pages(substream);
236	return 0;
237}
238
239static int snd_als4000_capture_prepare(struct snd_pcm_substream *substream)
240{
241	struct snd_sb *chip = snd_pcm_substream_chip(substream);
242	struct snd_pcm_runtime *runtime = substream->runtime;
243	unsigned long size;
244	unsigned count;
245
246	chip->capture_format = snd_als4000_get_format(runtime);
247
248	size = snd_pcm_lib_buffer_bytes(substream);
249	count = snd_pcm_lib_period_bytes(substream);
250
251	if (chip->capture_format & ALS4000_FORMAT_16BIT)
252		count >>=1;
253	count--;
254
255	spin_lock_irq(&chip->reg_lock);
256	snd_als4000_set_rate(chip, runtime->rate);
257	snd_als4000_set_capture_dma(chip, runtime->dma_addr, size);
258	spin_unlock_irq(&chip->reg_lock);
259	spin_lock_irq(&chip->mixer_lock);
260	snd_sbmixer_write(chip, 0xdc, count);
261	snd_sbmixer_write(chip, 0xdd, count>>8);
262	spin_unlock_irq(&chip->mixer_lock);
263	return 0;
264}
265
266static int snd_als4000_playback_prepare(struct snd_pcm_substream *substream)
267{
268	struct snd_sb *chip = snd_pcm_substream_chip(substream);
269	struct snd_pcm_runtime *runtime = substream->runtime;
270	unsigned long size;
271	unsigned count;
272
273	chip->playback_format = snd_als4000_get_format(runtime);
274
275	size = snd_pcm_lib_buffer_bytes(substream);
276	count = snd_pcm_lib_period_bytes(substream);
277
278	if (chip->playback_format & ALS4000_FORMAT_16BIT)
279		count >>=1;
280	count--;
281
282	spin_lock_irq(&chip->reg_lock);
283	snd_als4000_set_rate(chip, runtime->rate);
284	snd_als4000_set_playback_dma(chip, runtime->dma_addr, size);
285
286	/* SPEAKER_ON not needed, since dma_on seems to also enable speaker */
287	/* snd_sbdsp_command(chip, SB_DSP_SPEAKER_ON); */
288	snd_sbdsp_command(chip, playback_cmd(chip).dsp_cmd);
289	snd_sbdsp_command(chip, playback_cmd(chip).format);
290	snd_sbdsp_command(chip, count);
291	snd_sbdsp_command(chip, count>>8);
292	snd_sbdsp_command(chip, playback_cmd(chip).dma_off);
293	spin_unlock_irq(&chip->reg_lock);
294
295	return 0;
296}
297
298static int snd_als4000_capture_trigger(struct snd_pcm_substream *substream, int cmd)
299{
300	struct snd_sb *chip = snd_pcm_substream_chip(substream);
301	int result = 0;
302
303	spin_lock(&chip->mixer_lock);
304	switch (cmd) {
305	case SNDRV_PCM_TRIGGER_START:
306	case SNDRV_PCM_TRIGGER_RESUME:
307		chip->mode |= SB_RATE_LOCK_CAPTURE;
308		snd_sbmixer_write(chip, 0xde, capture_cmd(chip));
309		break;
310	case SNDRV_PCM_TRIGGER_STOP:
311	case SNDRV_PCM_TRIGGER_SUSPEND:
312		chip->mode &= ~SB_RATE_LOCK_CAPTURE;
313		snd_sbmixer_write(chip, 0xde, 0);
314		break;
315	default:
316		result = -EINVAL;
317		break;
318	}
319	spin_unlock(&chip->mixer_lock);
320	return result;
321}
322
323static int snd_als4000_playback_trigger(struct snd_pcm_substream *substream, int cmd)
324{
325	struct snd_sb *chip = snd_pcm_substream_chip(substream);
326	int result = 0;
327
328	spin_lock(&chip->reg_lock);
329	switch (cmd) {
330	case SNDRV_PCM_TRIGGER_START:
331	case SNDRV_PCM_TRIGGER_RESUME:
332		chip->mode |= SB_RATE_LOCK_PLAYBACK;
333		snd_sbdsp_command(chip, playback_cmd(chip).dma_on);
334		break;
335	case SNDRV_PCM_TRIGGER_STOP:
336	case SNDRV_PCM_TRIGGER_SUSPEND:
337		snd_sbdsp_command(chip, playback_cmd(chip).dma_off);
338		chip->mode &= ~SB_RATE_LOCK_PLAYBACK;
339		break;
340	default:
341		result = -EINVAL;
342		break;
343	}
344	spin_unlock(&chip->reg_lock);
345	return result;
346}
347
348static snd_pcm_uframes_t snd_als4000_capture_pointer(struct snd_pcm_substream *substream)
349{
350	struct snd_sb *chip = snd_pcm_substream_chip(substream);
351	unsigned int result;
352
353	spin_lock(&chip->reg_lock);
354	result = snd_als4000_gcr_read(chip, 0xa4) & 0xffff;
355	spin_unlock(&chip->reg_lock);
356	return bytes_to_frames( substream->runtime, result );
357}
358
359static snd_pcm_uframes_t snd_als4000_playback_pointer(struct snd_pcm_substream *substream)
360{
361	struct snd_sb *chip = snd_pcm_substream_chip(substream);
362	unsigned result;
363
364	spin_lock(&chip->reg_lock);
365	result = snd_als4000_gcr_read(chip, 0xa0) & 0xffff;
366	spin_unlock(&chip->reg_lock);
367	return bytes_to_frames( substream->runtime, result );
368}
369
370static irqreturn_t snd_als4000_interrupt(int irq, void *dev_id)
371{
372	struct snd_sb *chip = dev_id;
373	unsigned gcr_status;
374	unsigned sb_status;
375
376	/* find out which bit of the ALS4000 produced the interrupt */
377	gcr_status = inb(chip->alt_port + 0xe);
378
379	if ((gcr_status & 0x80) && (chip->playback_substream)) /* playback */
380		snd_pcm_period_elapsed(chip->playback_substream);
381	if ((gcr_status & 0x40) && (chip->capture_substream)) /* capturing */
382		snd_pcm_period_elapsed(chip->capture_substream);
383	if ((gcr_status & 0x10) && (chip->rmidi)) /* MPU401 interrupt */
384		snd_mpu401_uart_interrupt(irq, chip->rmidi->private_data);
385	/* release the gcr */
386	outb(gcr_status, chip->alt_port + 0xe);
387
388	spin_lock(&chip->mixer_lock);
389	sb_status = snd_sbmixer_read(chip, SB_DSP4_IRQSTATUS);
390	spin_unlock(&chip->mixer_lock);
391
392	if (sb_status & SB_IRQTYPE_8BIT)
393		snd_sb_ack_8bit(chip);
394	if (sb_status & SB_IRQTYPE_16BIT)
395		snd_sb_ack_16bit(chip);
396	if (sb_status & SB_IRQTYPE_MPUIN)
397		inb(chip->mpu_port);
398	if (sb_status & 0x20)
399		inb(SBP(chip, RESET));
400	return IRQ_HANDLED;
401}
402
403/*****************************************************************/
404
405static struct snd_pcm_hardware snd_als4000_playback =
406{
407	.info =			(SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED |
408				 SNDRV_PCM_INFO_MMAP_VALID),
409	.formats =		SNDRV_PCM_FMTBIT_S8 | SNDRV_PCM_FMTBIT_U8 |
410				SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_U16_LE,	/* formats */
411	.rates =		SNDRV_PCM_RATE_CONTINUOUS | SNDRV_PCM_RATE_8000_48000,
412	.rate_min =		4000,
413	.rate_max =		48000,
414	.channels_min =		1,
415	.channels_max =		2,
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
424static struct snd_pcm_hardware snd_als4000_capture =
425{
426	.info =			(SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED |
427				 SNDRV_PCM_INFO_MMAP_VALID),
428	.formats =		SNDRV_PCM_FMTBIT_S8 | SNDRV_PCM_FMTBIT_U8 |
429				SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_U16_LE,	/* formats */
430	.rates =		SNDRV_PCM_RATE_CONTINUOUS | SNDRV_PCM_RATE_8000_48000,
431	.rate_min =		4000,
432	.rate_max =		48000,
433	.channels_min =		1,
434	.channels_max =		2,
435	.buffer_bytes_max =	65536,
436	.period_bytes_min =	64,
437	.period_bytes_max =	65536,
438	.periods_min =		1,
439	.periods_max =		1024,
440	.fifo_size =		0
441};
442
443/*****************************************************************/
444
445static int snd_als4000_playback_open(struct snd_pcm_substream *substream)
446{
447	struct snd_sb *chip = snd_pcm_substream_chip(substream);
448	struct snd_pcm_runtime *runtime = substream->runtime;
449
450	chip->playback_substream = substream;
451	runtime->hw = snd_als4000_playback;
452	return 0;
453}
454
455static int snd_als4000_playback_close(struct snd_pcm_substream *substream)
456{
457	struct snd_sb *chip = snd_pcm_substream_chip(substream);
458
459	chip->playback_substream = NULL;
460	snd_pcm_lib_free_pages(substream);
461	return 0;
462}
463
464static int snd_als4000_capture_open(struct snd_pcm_substream *substream)
465{
466	struct snd_sb *chip = snd_pcm_substream_chip(substream);
467	struct snd_pcm_runtime *runtime = substream->runtime;
468
469	chip->capture_substream = substream;
470	runtime->hw = snd_als4000_capture;
471	return 0;
472}
473
474static int snd_als4000_capture_close(struct snd_pcm_substream *substream)
475{
476	struct snd_sb *chip = snd_pcm_substream_chip(substream);
477
478	chip->capture_substream = NULL;
479	snd_pcm_lib_free_pages(substream);
480	return 0;
481}
482
483/******************************************************************/
484
485static struct snd_pcm_ops snd_als4000_playback_ops = {
486	.open =		snd_als4000_playback_open,
487	.close =	snd_als4000_playback_close,
488	.ioctl =	snd_pcm_lib_ioctl,
489	.hw_params =	snd_als4000_hw_params,
490	.hw_free =	snd_als4000_hw_free,
491	.prepare =	snd_als4000_playback_prepare,
492	.trigger =	snd_als4000_playback_trigger,
493	.pointer =	snd_als4000_playback_pointer
494};
495
496static struct snd_pcm_ops snd_als4000_capture_ops = {
497	.open =		snd_als4000_capture_open,
498	.close =	snd_als4000_capture_close,
499	.ioctl =	snd_pcm_lib_ioctl,
500	.hw_params =	snd_als4000_hw_params,
501	.hw_free =	snd_als4000_hw_free,
502	.prepare =	snd_als4000_capture_prepare,
503	.trigger =	snd_als4000_capture_trigger,
504	.pointer =	snd_als4000_capture_pointer
505};
506
507static int __devinit snd_als4000_pcm(struct snd_sb *chip, int device)
508{
509	struct snd_pcm *pcm;
510	int err;
511
512	if ((err = snd_pcm_new(chip->card, "ALS4000 DSP", device, 1, 1, &pcm)) < 0)
513		return err;
514	pcm->private_data = chip;
515	pcm->info_flags = SNDRV_PCM_INFO_JOINT_DUPLEX;
516	snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_als4000_playback_ops);
517	snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_als4000_capture_ops);
518
519	snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV, snd_dma_pci_data(chip->pci),
520					      64*1024, 64*1024);
521
522	chip->pcm = pcm;
523
524	return 0;
525}
526
527/******************************************************************/
528
529static void snd_als4000_set_addr(unsigned long gcr,
530					unsigned int sb,
531					unsigned int mpu,
532					unsigned int opl,
533					unsigned int game)
534{
535	u32 confA = 0;
536	u32 confB = 0;
537
538	if (mpu > 0)
539		confB |= (mpu | 1) << 16;
540	if (sb > 0)
541		confB |= (sb | 1);
542	if (game > 0)
543		confA |= (game | 1) << 16;
544	if (opl > 0)
545		confA |= (opl | 1);
546	snd_als4000_gcr_write_addr(gcr, 0xa8, confA);
547	snd_als4000_gcr_write_addr(gcr, 0xa9, confB);
548}
549
550static void snd_als4000_configure(struct snd_sb *chip)
551{
552	unsigned tmp;
553	int i;
554
555	/* do some more configuration */
556	spin_lock_irq(&chip->mixer_lock);
557	tmp = snd_sbmixer_read(chip, 0xc0);
558	snd_sbmixer_write(chip, 0xc0, tmp|0x80);
559	/* always select DMA channel 0, since we do not actually use DMA */
560	snd_sbmixer_write(chip, SB_DSP4_DMASETUP, SB_DMASETUP_DMA0);
561	snd_sbmixer_write(chip, 0xc0, tmp&0x7f);
562	spin_unlock_irq(&chip->mixer_lock);
563
564	spin_lock_irq(&chip->reg_lock);
565	/* magic number. Enables interrupts(?) */
566	snd_als4000_gcr_write(chip, 0x8c, 0x28000);
567	for(i = 0x91; i <= 0x96; ++i)
568		snd_als4000_gcr_write(chip, i, 0);
569
570	snd_als4000_gcr_write(chip, 0x99, snd_als4000_gcr_read(chip, 0x99));
571	spin_unlock_irq(&chip->reg_lock);
572}
573
574#ifdef SUPPORT_JOYSTICK
575static int __devinit snd_als4000_create_gameport(struct snd_card_als4000 *acard, int dev)
576{
577	struct gameport *gp;
578	struct resource *r;
579	int io_port;
580
581	if (joystick_port[dev] == 0)
582		return -ENODEV;
583
584	if (joystick_port[dev] == 1) { /* auto-detect */
585		for (io_port = 0x200; io_port <= 0x218; io_port += 8) {
586			r = request_region(io_port, 8, "ALS4000 gameport");
587			if (r)
588				break;
589		}
590	} else {
591		io_port = joystick_port[dev];
592		r = request_region(io_port, 8, "ALS4000 gameport");
593	}
594
595	if (!r) {
596		printk(KERN_WARNING "als4000: cannot reserve joystick ports\n");
597		return -EBUSY;
598	}
599
600	acard->gameport = gp = gameport_allocate_port();
601	if (!gp) {
602		printk(KERN_ERR "als4000: cannot allocate memory for gameport\n");
603		release_and_free_resource(r);
604		return -ENOMEM;
605	}
606
607	gameport_set_name(gp, "ALS4000 Gameport");
608	gameport_set_phys(gp, "pci%s/gameport0", pci_name(acard->pci));
609	gameport_set_dev_parent(gp, &acard->pci->dev);
610	gp->io = io_port;
611	gameport_set_port_data(gp, r);
612
613	/* Enable legacy joystick port */
614	snd_als4000_set_addr(acard->gcr, 0, 0, 0, 1);
615
616	gameport_register_port(acard->gameport);
617
618	return 0;
619}
620
621static void snd_als4000_free_gameport(struct snd_card_als4000 *acard)
622{
623	if (acard->gameport) {
624		struct resource *r = gameport_get_port_data(acard->gameport);
625
626		gameport_unregister_port(acard->gameport);
627		acard->gameport = NULL;
628
629		snd_als4000_set_addr(acard->gcr, 0, 0, 0, 0); /* disable joystick */
630		release_and_free_resource(r);
631	}
632}
633#else
634static inline int snd_als4000_create_gameport(struct snd_card_als4000 *acard, int dev) { return -ENOSYS; }
635static inline void snd_als4000_free_gameport(struct snd_card_als4000 *acard) { }
636#endif
637
638static void snd_card_als4000_free( struct snd_card *card )
639{
640	struct snd_card_als4000 * acard = (struct snd_card_als4000 *)card->private_data;
641
642	/* make sure that interrupts are disabled */
643	snd_als4000_gcr_write_addr( acard->gcr, 0x8c, 0);
644	/* free resources */
645	snd_als4000_free_gameport(acard);
646	pci_release_regions(acard->pci);
647	pci_disable_device(acard->pci);
648}
649
650static int __devinit snd_card_als4000_probe(struct pci_dev *pci,
651					  const struct pci_device_id *pci_id)
652{
653	static int dev;
654	struct snd_card *card;
655	struct snd_card_als4000 *acard;
656	unsigned long gcr;
657	struct snd_sb *chip;
658	struct snd_opl3 *opl3;
659	unsigned short word;
660	int err;
661
662	if (dev >= SNDRV_CARDS)
663		return -ENODEV;
664	if (!enable[dev]) {
665		dev++;
666		return -ENOENT;
667	}
668
669	/* enable PCI device */
670	if ((err = pci_enable_device(pci)) < 0) {
671		return err;
672	}
673	/* check, if we can restrict PCI DMA transfers to 24 bits */
674	if (pci_set_dma_mask(pci, DMA_24BIT_MASK) < 0 ||
675	    pci_set_consistent_dma_mask(pci, DMA_24BIT_MASK) < 0) {
676		snd_printk(KERN_ERR "architecture does not support 24bit PCI busmaster DMA\n");
677		pci_disable_device(pci);
678		return -ENXIO;
679	}
680
681	if ((err = pci_request_regions(pci, "ALS4000")) < 0) {
682		pci_disable_device(pci);
683		return err;
684	}
685	gcr = pci_resource_start(pci, 0);
686
687	pci_read_config_word(pci, PCI_COMMAND, &word);
688	pci_write_config_word(pci, PCI_COMMAND, word | PCI_COMMAND_IO);
689	pci_set_master(pci);
690
691	card = snd_card_new(index[dev], id[dev], THIS_MODULE,
692			    sizeof( struct snd_card_als4000 ) );
693	if (card == NULL) {
694		pci_release_regions(pci);
695		pci_disable_device(pci);
696		return -ENOMEM;
697	}
698
699	acard = (struct snd_card_als4000 *)card->private_data;
700	acard->pci = pci;
701	acard->gcr = gcr;
702	card->private_free = snd_card_als4000_free;
703
704	/* disable all legacy ISA stuff */
705	snd_als4000_set_addr(acard->gcr, 0, 0, 0, 0);
706
707	if ((err = snd_sbdsp_create(card,
708				    gcr + 0x10,
709				    pci->irq,
710				    snd_als4000_interrupt,
711				    -1,
712				    -1,
713				    SB_HW_ALS4000,
714				    &chip)) < 0) {
715		goto out_err;
716	}
717	acard->chip = chip;
718
719	chip->pci = pci;
720	chip->alt_port = gcr;
721	snd_card_set_dev(card, &pci->dev);
722
723	snd_als4000_configure(chip);
724
725	strcpy(card->driver, "ALS4000");
726	strcpy(card->shortname, "Avance Logic ALS4000");
727	sprintf(card->longname, "%s at 0x%lx, irq %i",
728		card->shortname, chip->alt_port, chip->irq);
729
730	if ((err = snd_mpu401_uart_new( card, 0, MPU401_HW_ALS4000,
731				        gcr+0x30, MPU401_INFO_INTEGRATED,
732					pci->irq, 0, &chip->rmidi)) < 0) {
733		printk(KERN_ERR "als4000: no MPU-401 device at 0x%lx?\n", gcr+0x30);
734		goto out_err;
735	}
736
737	if ((err = snd_als4000_pcm(chip, 0)) < 0) {
738		goto out_err;
739	}
740	if ((err = snd_sbmixer_new(chip)) < 0) {
741		goto out_err;
742	}
743
744	if (snd_opl3_create(card, gcr+0x10, gcr+0x12,
745			    OPL3_HW_AUTO, 1, &opl3) < 0) {
746		printk(KERN_ERR "als4000: no OPL device at 0x%lx-0x%lx?\n",
747			   gcr+0x10, gcr+0x12 );
748	} else {
749		if ((err = snd_opl3_hwdep_new(opl3, 0, 1, NULL)) < 0) {
750			goto out_err;
751		}
752	}
753
754	snd_als4000_create_gameport(acard, dev);
755
756	if ((err = snd_card_register(card)) < 0) {
757		goto out_err;
758	}
759	pci_set_drvdata(pci, card);
760	dev++;
761	err = 0;
762	goto out;
763
764out_err:
765	snd_card_free(card);
766
767out:
768	return err;
769}
770
771static void __devexit snd_card_als4000_remove(struct pci_dev *pci)
772{
773	snd_card_free(pci_get_drvdata(pci));
774	pci_set_drvdata(pci, NULL);
775}
776
777#ifdef CONFIG_PM
778static int snd_als4000_suspend(struct pci_dev *pci, pm_message_t state)
779{
780	struct snd_card *card = pci_get_drvdata(pci);
781	struct snd_card_als4000 *acard = card->private_data;
782	struct snd_sb *chip = acard->chip;
783
784	snd_power_change_state(card, SNDRV_CTL_POWER_D3hot);
785
786	snd_pcm_suspend_all(chip->pcm);
787	snd_sbmixer_suspend(chip);
788
789	pci_disable_device(pci);
790	pci_save_state(pci);
791	pci_set_power_state(pci, pci_choose_state(pci, state));
792	return 0;
793}
794
795static int snd_als4000_resume(struct pci_dev *pci)
796{
797	struct snd_card *card = pci_get_drvdata(pci);
798	struct snd_card_als4000 *acard = card->private_data;
799	struct snd_sb *chip = acard->chip;
800
801	pci_set_power_state(pci, PCI_D0);
802	pci_restore_state(pci);
803	if (pci_enable_device(pci) < 0) {
804		printk(KERN_ERR "als4000: pci_enable_device failed, "
805		       "disabling device\n");
806		snd_card_disconnect(card);
807		return -EIO;
808	}
809	pci_set_master(pci);
810
811	snd_als4000_configure(chip);
812	snd_sbdsp_reset(chip);
813	snd_sbmixer_resume(chip);
814
815#ifdef SUPPORT_JOYSTICK
816	if (acard->gameport)
817		snd_als4000_set_addr(acard->gcr, 0, 0, 0, 1);
818#endif
819
820	snd_power_change_state(card, SNDRV_CTL_POWER_D0);
821	return 0;
822}
823#endif
824
825
826static struct pci_driver driver = {
827	.name = "ALS4000",
828	.id_table = snd_als4000_ids,
829	.probe = snd_card_als4000_probe,
830	.remove = __devexit_p(snd_card_als4000_remove),
831#ifdef CONFIG_PM
832	.suspend = snd_als4000_suspend,
833	.resume = snd_als4000_resume,
834#endif
835};
836
837static int __init alsa_card_als4000_init(void)
838{
839	return pci_register_driver(&driver);
840}
841
842static void __exit alsa_card_als4000_exit(void)
843{
844	pci_unregister_driver(&driver);
845}
846
847module_init(alsa_card_als4000_init)
848module_exit(alsa_card_als4000_exit)
849