1/*
2 *  Driver for S3 SonicVibes soundcard
3 *  Copyright (c) by Jaroslav Kysela <perex@suse.cz>
4 *
5 *  BUGS:
6 *    It looks like 86c617 rev 3 doesn't supports DDMA buffers above 16MB?
7 *    Driver sometimes hangs... Nobody knows why at this moment...
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#include <sound/driver.h>
26#include <linux/delay.h>
27#include <linux/init.h>
28#include <linux/interrupt.h>
29#include <linux/pci.h>
30#include <linux/slab.h>
31#include <linux/gameport.h>
32#include <linux/moduleparam.h>
33#include <linux/dma-mapping.h>
34
35#include <sound/core.h>
36#include <sound/pcm.h>
37#include <sound/info.h>
38#include <sound/control.h>
39#include <sound/mpu401.h>
40#include <sound/opl3.h>
41#include <sound/initval.h>
42
43#include <asm/io.h>
44
45MODULE_AUTHOR("Jaroslav Kysela <perex@suse.cz>");
46MODULE_DESCRIPTION("S3 SonicVibes PCI");
47MODULE_LICENSE("GPL");
48MODULE_SUPPORTED_DEVICE("{{S3,SonicVibes PCI}}");
49
50#if defined(CONFIG_GAMEPORT) || (defined(MODULE) && defined(CONFIG_GAMEPORT_MODULE))
51#define SUPPORT_JOYSTICK 1
52#endif
53
54static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX;	/* Index 0-MAX */
55static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR;	/* ID for this card */
56static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP;	/* Enable this card */
57static int reverb[SNDRV_CARDS];
58static int mge[SNDRV_CARDS];
59static unsigned int dmaio = 0x7a00;	/* DDMA i/o address */
60
61module_param_array(index, int, NULL, 0444);
62MODULE_PARM_DESC(index, "Index value for S3 SonicVibes soundcard.");
63module_param_array(id, charp, NULL, 0444);
64MODULE_PARM_DESC(id, "ID string for S3 SonicVibes soundcard.");
65module_param_array(enable, bool, NULL, 0444);
66MODULE_PARM_DESC(enable, "Enable S3 SonicVibes soundcard.");
67module_param_array(reverb, bool, NULL, 0444);
68MODULE_PARM_DESC(reverb, "Enable reverb (SRAM is present) for S3 SonicVibes soundcard.");
69module_param_array(mge, bool, NULL, 0444);
70MODULE_PARM_DESC(mge, "MIC Gain Enable for S3 SonicVibes soundcard.");
71module_param(dmaio, uint, 0444);
72MODULE_PARM_DESC(dmaio, "DDMA i/o base address for S3 SonicVibes soundcard.");
73
74/*
75 * Enhanced port direct registers
76 */
77
78#define SV_REG(sonic, x) ((sonic)->enh_port + SV_REG_##x)
79
80#define SV_REG_CONTROL	0x00	/* R/W: CODEC/Mixer control register */
81#define   SV_ENHANCED	  0x01	/* audio mode select - enhanced mode */
82#define   SV_TEST	  0x02	/* test bit */
83#define   SV_REVERB	  0x04	/* reverb enable */
84#define   SV_WAVETABLE	  0x08	/* wavetable active / FM active if not set */
85#define   SV_INTA	  0x20	/* INTA driving - should be always 1 */
86#define   SV_RESET	  0x80	/* reset chip */
87#define SV_REG_IRQMASK	0x01	/* R/W: CODEC/Mixer interrupt mask register */
88#define   SV_DMAA_MASK	  0x01	/* mask DMA-A interrupt */
89#define   SV_DMAC_MASK	  0x04	/* mask DMA-C interrupt */
90#define   SV_SPEC_MASK	  0x08	/* special interrupt mask - should be always masked */
91#define   SV_UD_MASK	  0x40	/* Up/Down button interrupt mask */
92#define   SV_MIDI_MASK	  0x80	/* mask MIDI interrupt */
93#define SV_REG_STATUS	0x02	/* R/O: CODEC/Mixer status register */
94#define   SV_DMAA_IRQ	  0x01	/* DMA-A interrupt */
95#define   SV_DMAC_IRQ	  0x04	/* DMA-C interrupt */
96#define   SV_SPEC_IRQ	  0x08	/* special interrupt */
97#define   SV_UD_IRQ	  0x40	/* Up/Down interrupt */
98#define   SV_MIDI_IRQ	  0x80	/* MIDI interrupt */
99#define SV_REG_INDEX	0x04	/* R/W: CODEC/Mixer index address register */
100#define   SV_MCE          0x40	/* mode change enable */
101#define   SV_TRD	  0x80	/* DMA transfer request disabled */
102#define SV_REG_DATA	0x05	/* R/W: CODEC/Mixer index data register */
103
104/*
105 * Enhanced port indirect registers
106 */
107
108#define SV_IREG_LEFT_ADC	0x00	/* Left ADC Input Control */
109#define SV_IREG_RIGHT_ADC	0x01	/* Right ADC Input Control */
110#define SV_IREG_LEFT_AUX1	0x02	/* Left AUX1 Input Control */
111#define SV_IREG_RIGHT_AUX1	0x03	/* Right AUX1 Input Control */
112#define SV_IREG_LEFT_CD		0x04	/* Left CD Input Control */
113#define SV_IREG_RIGHT_CD	0x05	/* Right CD Input Control */
114#define SV_IREG_LEFT_LINE	0x06	/* Left Line Input Control */
115#define SV_IREG_RIGHT_LINE	0x07	/* Right Line Input Control */
116#define SV_IREG_MIC		0x08	/* MIC Input Control */
117#define SV_IREG_GAME_PORT	0x09	/* Game Port Control */
118#define SV_IREG_LEFT_SYNTH	0x0a	/* Left Synth Input Control */
119#define SV_IREG_RIGHT_SYNTH	0x0b	/* Right Synth Input Control */
120#define SV_IREG_LEFT_AUX2	0x0c	/* Left AUX2 Input Control */
121#define SV_IREG_RIGHT_AUX2	0x0d	/* Right AUX2 Input Control */
122#define SV_IREG_LEFT_ANALOG	0x0e	/* Left Analog Mixer Output Control */
123#define SV_IREG_RIGHT_ANALOG	0x0f	/* Right Analog Mixer Output Control */
124#define SV_IREG_LEFT_PCM	0x10	/* Left PCM Input Control */
125#define SV_IREG_RIGHT_PCM	0x11	/* Right PCM Input Control */
126#define SV_IREG_DMA_DATA_FMT	0x12	/* DMA Data Format */
127#define SV_IREG_PC_ENABLE	0x13	/* Playback/Capture Enable Register */
128#define SV_IREG_UD_BUTTON	0x14	/* Up/Down Button Register */
129#define SV_IREG_REVISION	0x15	/* Revision */
130#define SV_IREG_ADC_OUTPUT_CTRL	0x16	/* ADC Output Control */
131#define SV_IREG_DMA_A_UPPER	0x18	/* DMA A Upper Base Count */
132#define SV_IREG_DMA_A_LOWER	0x19	/* DMA A Lower Base Count */
133#define SV_IREG_DMA_C_UPPER	0x1c	/* DMA C Upper Base Count */
134#define SV_IREG_DMA_C_LOWER	0x1d	/* DMA C Lower Base Count */
135#define SV_IREG_PCM_RATE_LOW	0x1e	/* PCM Sampling Rate Low Byte */
136#define SV_IREG_PCM_RATE_HIGH	0x1f	/* PCM Sampling Rate High Byte */
137#define SV_IREG_SYNTH_RATE_LOW	0x20	/* Synthesizer Sampling Rate Low Byte */
138#define SV_IREG_SYNTH_RATE_HIGH 0x21	/* Synthesizer Sampling Rate High Byte */
139#define SV_IREG_ADC_CLOCK	0x22	/* ADC Clock Source Selection */
140#define SV_IREG_ADC_ALT_RATE	0x23	/* ADC Alternative Sampling Rate Selection */
141#define SV_IREG_ADC_PLL_M	0x24	/* ADC PLL M Register */
142#define SV_IREG_ADC_PLL_N	0x25	/* ADC PLL N Register */
143#define SV_IREG_SYNTH_PLL_M	0x26	/* Synthesizer PLL M Register */
144#define SV_IREG_SYNTH_PLL_N	0x27	/* Synthesizer PLL N Register */
145#define SV_IREG_MPU401		0x2a	/* MPU-401 UART Operation */
146#define SV_IREG_DRIVE_CTRL	0x2b	/* Drive Control */
147#define SV_IREG_SRS_SPACE	0x2c	/* SRS Space Control */
148#define SV_IREG_SRS_CENTER	0x2d	/* SRS Center Control */
149#define SV_IREG_WAVE_SOURCE	0x2e	/* Wavetable Sample Source Select */
150#define SV_IREG_ANALOG_POWER	0x30	/* Analog Power Down Control */
151#define SV_IREG_DIGITAL_POWER	0x31	/* Digital Power Down Control */
152
153#define SV_IREG_ADC_PLL		SV_IREG_ADC_PLL_M
154#define SV_IREG_SYNTH_PLL	SV_IREG_SYNTH_PLL_M
155
156/*
157 *  DMA registers
158 */
159
160#define SV_DMA_ADDR0		0x00
161#define SV_DMA_ADDR1		0x01
162#define SV_DMA_ADDR2		0x02
163#define SV_DMA_ADDR3		0x03
164#define SV_DMA_COUNT0		0x04
165#define SV_DMA_COUNT1		0x05
166#define SV_DMA_COUNT2		0x06
167#define SV_DMA_MODE		0x0b
168#define SV_DMA_RESET		0x0d
169#define SV_DMA_MASK		0x0f
170
171/*
172 *  Record sources
173 */
174
175#define SV_RECSRC_RESERVED	(0x00<<5)
176#define SV_RECSRC_CD		(0x01<<5)
177#define SV_RECSRC_DAC		(0x02<<5)
178#define SV_RECSRC_AUX2		(0x03<<5)
179#define SV_RECSRC_LINE		(0x04<<5)
180#define SV_RECSRC_AUX1		(0x05<<5)
181#define SV_RECSRC_MIC		(0x06<<5)
182#define SV_RECSRC_OUT		(0x07<<5)
183
184/*
185 *  constants
186 */
187
188#define SV_FULLRATE		48000
189#define SV_REFFREQUENCY		24576000
190#define SV_ADCMULT		512
191
192#define SV_MODE_PLAY		1
193#define SV_MODE_CAPTURE		2
194
195/*
196
197 */
198
199struct sonicvibes {
200	unsigned long dma1size;
201	unsigned long dma2size;
202	int irq;
203
204	unsigned long sb_port;
205	unsigned long enh_port;
206	unsigned long synth_port;
207	unsigned long midi_port;
208	unsigned long game_port;
209	unsigned int dmaa_port;
210	struct resource *res_dmaa;
211	unsigned int dmac_port;
212	struct resource *res_dmac;
213
214	unsigned char enable;
215	unsigned char irqmask;
216	unsigned char revision;
217	unsigned char format;
218	unsigned char srs_space;
219	unsigned char srs_center;
220	unsigned char mpu_switch;
221	unsigned char wave_source;
222
223	unsigned int mode;
224
225	struct pci_dev *pci;
226	struct snd_card *card;
227	struct snd_pcm *pcm;
228	struct snd_pcm_substream *playback_substream;
229	struct snd_pcm_substream *capture_substream;
230	struct snd_rawmidi *rmidi;
231	struct snd_hwdep *fmsynth;	/* S3FM */
232
233	spinlock_t reg_lock;
234
235	unsigned int p_dma_size;
236	unsigned int c_dma_size;
237
238	struct snd_kcontrol *master_mute;
239	struct snd_kcontrol *master_volume;
240
241#ifdef SUPPORT_JOYSTICK
242	struct gameport *gameport;
243#endif
244};
245
246static struct pci_device_id snd_sonic_ids[] = {
247	{ 0x5333, 0xca00, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, },
248        { 0, }
249};
250
251MODULE_DEVICE_TABLE(pci, snd_sonic_ids);
252
253static struct snd_ratden sonicvibes_adc_clock = {
254	.num_min = 4000 * 65536,
255	.num_max = 48000UL * 65536,
256	.num_step = 1,
257	.den = 65536,
258};
259static struct snd_pcm_hw_constraint_ratdens snd_sonicvibes_hw_constraints_adc_clock = {
260	.nrats = 1,
261	.rats = &sonicvibes_adc_clock,
262};
263
264/*
265 *  common I/O routines
266 */
267
268static inline void snd_sonicvibes_setdmaa(struct sonicvibes * sonic,
269					  unsigned int addr,
270					  unsigned int count)
271{
272	count--;
273	outl(addr, sonic->dmaa_port + SV_DMA_ADDR0);
274	outl(count, sonic->dmaa_port + SV_DMA_COUNT0);
275	outb(0x18, sonic->dmaa_port + SV_DMA_MODE);
276}
277
278static inline void snd_sonicvibes_setdmac(struct sonicvibes * sonic,
279					  unsigned int addr,
280					  unsigned int count)
281{
282	/* note: dmac is working in word mode!!! */
283	count >>= 1;
284	count--;
285	outl(addr, sonic->dmac_port + SV_DMA_ADDR0);
286	outl(count, sonic->dmac_port + SV_DMA_COUNT0);
287	outb(0x14, sonic->dmac_port + SV_DMA_MODE);
288}
289
290static inline unsigned int snd_sonicvibes_getdmaa(struct sonicvibes * sonic)
291{
292	return (inl(sonic->dmaa_port + SV_DMA_COUNT0) & 0xffffff) + 1;
293}
294
295static inline unsigned int snd_sonicvibes_getdmac(struct sonicvibes * sonic)
296{
297	/* note: dmac is working in word mode!!! */
298	return ((inl(sonic->dmac_port + SV_DMA_COUNT0) & 0xffffff) + 1) << 1;
299}
300
301static void snd_sonicvibes_out1(struct sonicvibes * sonic,
302				unsigned char reg,
303				unsigned char value)
304{
305	outb(reg, SV_REG(sonic, INDEX));
306	udelay(10);
307	outb(value, SV_REG(sonic, DATA));
308	udelay(10);
309}
310
311static void snd_sonicvibes_out(struct sonicvibes * sonic,
312			       unsigned char reg,
313			       unsigned char value)
314{
315	unsigned long flags;
316
317	spin_lock_irqsave(&sonic->reg_lock, flags);
318	outb(reg, SV_REG(sonic, INDEX));
319	udelay(10);
320	outb(value, SV_REG(sonic, DATA));
321	udelay(10);
322	spin_unlock_irqrestore(&sonic->reg_lock, flags);
323}
324
325static unsigned char snd_sonicvibes_in1(struct sonicvibes * sonic, unsigned char reg)
326{
327	unsigned char value;
328
329	outb(reg, SV_REG(sonic, INDEX));
330	udelay(10);
331	value = inb(SV_REG(sonic, DATA));
332	udelay(10);
333	return value;
334}
335
336static unsigned char snd_sonicvibes_in(struct sonicvibes * sonic, unsigned char reg)
337{
338	unsigned long flags;
339	unsigned char value;
340
341	spin_lock_irqsave(&sonic->reg_lock, flags);
342	outb(reg, SV_REG(sonic, INDEX));
343	udelay(10);
344	value = inb(SV_REG(sonic, DATA));
345	udelay(10);
346	spin_unlock_irqrestore(&sonic->reg_lock, flags);
347	return value;
348}
349
350
351static void snd_sonicvibes_setfmt(struct sonicvibes * sonic,
352                                  unsigned char mask,
353                                  unsigned char value)
354{
355	unsigned long flags;
356
357	spin_lock_irqsave(&sonic->reg_lock, flags);
358	outb(SV_MCE | SV_IREG_DMA_DATA_FMT, SV_REG(sonic, INDEX));
359	if (mask) {
360		sonic->format = inb(SV_REG(sonic, DATA));
361		udelay(10);
362	}
363	sonic->format = (sonic->format & mask) | value;
364	outb(sonic->format, SV_REG(sonic, DATA));
365	udelay(10);
366	outb(0, SV_REG(sonic, INDEX));
367	udelay(10);
368	spin_unlock_irqrestore(&sonic->reg_lock, flags);
369}
370
371static void snd_sonicvibes_pll(unsigned int rate,
372			       unsigned int *res_r,
373			       unsigned int *res_m,
374			       unsigned int *res_n)
375{
376	unsigned int r, m = 0, n = 0;
377	unsigned int xm, xn, xr, xd, metric = ~0U;
378
379	if (rate < 625000 / SV_ADCMULT)
380		rate = 625000 / SV_ADCMULT;
381	if (rate > 150000000 / SV_ADCMULT)
382		rate = 150000000 / SV_ADCMULT;
383	/* slight violation of specs, needed for continuous sampling rates */
384	for (r = 0; rate < 75000000 / SV_ADCMULT; r += 0x20, rate <<= 1);
385	for (xn = 3; xn < 33; xn++)	/* 35 */
386		for (xm = 3; xm < 257; xm++) {
387			xr = ((SV_REFFREQUENCY / SV_ADCMULT) * xm) / xn;
388			if (xr >= rate)
389				xd = xr - rate;
390			else
391				xd = rate - xr;
392			if (xd < metric) {
393				metric = xd;
394				m = xm - 2;
395				n = xn - 2;
396			}
397		}
398	*res_r = r;
399	*res_m = m;
400	*res_n = n;
401}
402
403static void snd_sonicvibes_setpll(struct sonicvibes * sonic,
404                                  unsigned char reg,
405                                  unsigned int rate)
406{
407	unsigned long flags;
408	unsigned int r, m, n;
409
410	snd_sonicvibes_pll(rate, &r, &m, &n);
411	if (sonic != NULL) {
412		spin_lock_irqsave(&sonic->reg_lock, flags);
413		snd_sonicvibes_out1(sonic, reg, m);
414		snd_sonicvibes_out1(sonic, reg + 1, r | n);
415		spin_unlock_irqrestore(&sonic->reg_lock, flags);
416	}
417}
418
419static void snd_sonicvibes_set_adc_rate(struct sonicvibes * sonic, unsigned int rate)
420{
421	unsigned long flags;
422	unsigned int div;
423	unsigned char clock;
424
425	div = 48000 / rate;
426	if (div > 8)
427		div = 8;
428	if ((48000 / div) == rate) {	/* use the alternate clock */
429		clock = 0x10;
430	} else {			/* use the PLL source */
431		clock = 0x00;
432		snd_sonicvibes_setpll(sonic, SV_IREG_ADC_PLL, rate);
433	}
434	spin_lock_irqsave(&sonic->reg_lock, flags);
435	snd_sonicvibes_out1(sonic, SV_IREG_ADC_ALT_RATE, (div - 1) << 4);
436	snd_sonicvibes_out1(sonic, SV_IREG_ADC_CLOCK, clock);
437	spin_unlock_irqrestore(&sonic->reg_lock, flags);
438}
439
440static int snd_sonicvibes_hw_constraint_dac_rate(struct snd_pcm_hw_params *params,
441						 struct snd_pcm_hw_rule *rule)
442{
443	unsigned int rate, div, r, m, n;
444
445	if (hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE)->min ==
446	    hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE)->max) {
447		rate = hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE)->min;
448		div = 48000 / rate;
449		if (div > 8)
450			div = 8;
451		if ((48000 / div) == rate) {
452			params->rate_num = rate;
453			params->rate_den = 1;
454		} else {
455			snd_sonicvibes_pll(rate, &r, &m, &n);
456			snd_assert((SV_REFFREQUENCY % 16) == 0, return -EINVAL);
457			snd_assert((SV_ADCMULT % 512) == 0, return -EINVAL);
458			params->rate_num = (SV_REFFREQUENCY/16) * (n+2) * r;
459			params->rate_den = (SV_ADCMULT/512) * (m+2);
460		}
461	}
462	return 0;
463}
464
465static void snd_sonicvibes_set_dac_rate(struct sonicvibes * sonic, unsigned int rate)
466{
467	unsigned int div;
468	unsigned long flags;
469
470	div = (rate * 65536 + SV_FULLRATE / 2) / SV_FULLRATE;
471	if (div > 65535)
472		div = 65535;
473	spin_lock_irqsave(&sonic->reg_lock, flags);
474	snd_sonicvibes_out1(sonic, SV_IREG_PCM_RATE_HIGH, div >> 8);
475	snd_sonicvibes_out1(sonic, SV_IREG_PCM_RATE_LOW, div);
476	spin_unlock_irqrestore(&sonic->reg_lock, flags);
477}
478
479static int snd_sonicvibes_trigger(struct sonicvibes * sonic, int what, int cmd)
480{
481	int result = 0;
482
483	spin_lock(&sonic->reg_lock);
484	if (cmd == SNDRV_PCM_TRIGGER_START) {
485		if (!(sonic->enable & what)) {
486			sonic->enable |= what;
487			snd_sonicvibes_out1(sonic, SV_IREG_PC_ENABLE, sonic->enable);
488		}
489	} else if (cmd == SNDRV_PCM_TRIGGER_STOP) {
490		if (sonic->enable & what) {
491			sonic->enable &= ~what;
492			snd_sonicvibes_out1(sonic, SV_IREG_PC_ENABLE, sonic->enable);
493		}
494	} else {
495		result = -EINVAL;
496	}
497	spin_unlock(&sonic->reg_lock);
498	return result;
499}
500
501static irqreturn_t snd_sonicvibes_interrupt(int irq, void *dev_id)
502{
503	struct sonicvibes *sonic = dev_id;
504	unsigned char status;
505
506	status = inb(SV_REG(sonic, STATUS));
507	if (!(status & (SV_DMAA_IRQ | SV_DMAC_IRQ | SV_MIDI_IRQ)))
508		return IRQ_NONE;
509	if (status == 0xff) {	/* failure */
510		outb(sonic->irqmask = ~0, SV_REG(sonic, IRQMASK));
511		snd_printk(KERN_ERR "IRQ failure - interrupts disabled!!\n");
512		return IRQ_HANDLED;
513	}
514	if (sonic->pcm) {
515		if (status & SV_DMAA_IRQ)
516			snd_pcm_period_elapsed(sonic->playback_substream);
517		if (status & SV_DMAC_IRQ)
518			snd_pcm_period_elapsed(sonic->capture_substream);
519	}
520	if (sonic->rmidi) {
521		if (status & SV_MIDI_IRQ)
522			snd_mpu401_uart_interrupt(irq, sonic->rmidi->private_data);
523	}
524	if (status & SV_UD_IRQ) {
525		unsigned char udreg;
526		int vol, oleft, oright, mleft, mright;
527
528		spin_lock(&sonic->reg_lock);
529		udreg = snd_sonicvibes_in1(sonic, SV_IREG_UD_BUTTON);
530		vol = udreg & 0x3f;
531		if (!(udreg & 0x40))
532			vol = -vol;
533		oleft = mleft = snd_sonicvibes_in1(sonic, SV_IREG_LEFT_ANALOG);
534		oright = mright = snd_sonicvibes_in1(sonic, SV_IREG_RIGHT_ANALOG);
535		oleft &= 0x1f;
536		oright &= 0x1f;
537		oleft += vol;
538		if (oleft < 0)
539			oleft = 0;
540		if (oleft > 0x1f)
541			oleft = 0x1f;
542		oright += vol;
543		if (oright < 0)
544			oright = 0;
545		if (oright > 0x1f)
546			oright = 0x1f;
547		if (udreg & 0x80) {
548			mleft ^= 0x80;
549			mright ^= 0x80;
550		}
551		oleft |= mleft & 0x80;
552		oright |= mright & 0x80;
553		snd_sonicvibes_out1(sonic, SV_IREG_LEFT_ANALOG, oleft);
554		snd_sonicvibes_out1(sonic, SV_IREG_RIGHT_ANALOG, oright);
555		spin_unlock(&sonic->reg_lock);
556		snd_ctl_notify(sonic->card, SNDRV_CTL_EVENT_MASK_VALUE, &sonic->master_mute->id);
557		snd_ctl_notify(sonic->card, SNDRV_CTL_EVENT_MASK_VALUE, &sonic->master_volume->id);
558	}
559	return IRQ_HANDLED;
560}
561
562/*
563 *  PCM part
564 */
565
566static int snd_sonicvibes_playback_trigger(struct snd_pcm_substream *substream,
567					   int cmd)
568{
569	struct sonicvibes *sonic = snd_pcm_substream_chip(substream);
570	return snd_sonicvibes_trigger(sonic, 1, cmd);
571}
572
573static int snd_sonicvibes_capture_trigger(struct snd_pcm_substream *substream,
574					  int cmd)
575{
576	struct sonicvibes *sonic = snd_pcm_substream_chip(substream);
577	return snd_sonicvibes_trigger(sonic, 2, cmd);
578}
579
580static int snd_sonicvibes_hw_params(struct snd_pcm_substream *substream,
581				    struct snd_pcm_hw_params *hw_params)
582{
583	return snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(hw_params));
584}
585
586static int snd_sonicvibes_hw_free(struct snd_pcm_substream *substream)
587{
588	return snd_pcm_lib_free_pages(substream);
589}
590
591static int snd_sonicvibes_playback_prepare(struct snd_pcm_substream *substream)
592{
593	struct sonicvibes *sonic = snd_pcm_substream_chip(substream);
594	struct snd_pcm_runtime *runtime = substream->runtime;
595	unsigned char fmt = 0;
596	unsigned int size = snd_pcm_lib_buffer_bytes(substream);
597	unsigned int count = snd_pcm_lib_period_bytes(substream);
598
599	sonic->p_dma_size = size;
600	count--;
601	if (runtime->channels > 1)
602		fmt |= 1;
603	if (snd_pcm_format_width(runtime->format) == 16)
604		fmt |= 2;
605	snd_sonicvibes_setfmt(sonic, ~3, fmt);
606	snd_sonicvibes_set_dac_rate(sonic, runtime->rate);
607	spin_lock_irq(&sonic->reg_lock);
608	snd_sonicvibes_setdmaa(sonic, runtime->dma_addr, size);
609	snd_sonicvibes_out1(sonic, SV_IREG_DMA_A_UPPER, count >> 8);
610	snd_sonicvibes_out1(sonic, SV_IREG_DMA_A_LOWER, count);
611	spin_unlock_irq(&sonic->reg_lock);
612	return 0;
613}
614
615static int snd_sonicvibes_capture_prepare(struct snd_pcm_substream *substream)
616{
617	struct sonicvibes *sonic = snd_pcm_substream_chip(substream);
618	struct snd_pcm_runtime *runtime = substream->runtime;
619	unsigned char fmt = 0;
620	unsigned int size = snd_pcm_lib_buffer_bytes(substream);
621	unsigned int count = snd_pcm_lib_period_bytes(substream);
622
623	sonic->c_dma_size = size;
624	count >>= 1;
625	count--;
626	if (runtime->channels > 1)
627		fmt |= 0x10;
628	if (snd_pcm_format_width(runtime->format) == 16)
629		fmt |= 0x20;
630	snd_sonicvibes_setfmt(sonic, ~0x30, fmt);
631	snd_sonicvibes_set_adc_rate(sonic, runtime->rate);
632	spin_lock_irq(&sonic->reg_lock);
633	snd_sonicvibes_setdmac(sonic, runtime->dma_addr, size);
634	snd_sonicvibes_out1(sonic, SV_IREG_DMA_C_UPPER, count >> 8);
635	snd_sonicvibes_out1(sonic, SV_IREG_DMA_C_LOWER, count);
636	spin_unlock_irq(&sonic->reg_lock);
637	return 0;
638}
639
640static snd_pcm_uframes_t snd_sonicvibes_playback_pointer(struct snd_pcm_substream *substream)
641{
642	struct sonicvibes *sonic = snd_pcm_substream_chip(substream);
643	size_t ptr;
644
645	if (!(sonic->enable & 1))
646		return 0;
647	ptr = sonic->p_dma_size - snd_sonicvibes_getdmaa(sonic);
648	return bytes_to_frames(substream->runtime, ptr);
649}
650
651static snd_pcm_uframes_t snd_sonicvibes_capture_pointer(struct snd_pcm_substream *substream)
652{
653	struct sonicvibes *sonic = snd_pcm_substream_chip(substream);
654	size_t ptr;
655	if (!(sonic->enable & 2))
656		return 0;
657	ptr = sonic->c_dma_size - snd_sonicvibes_getdmac(sonic);
658	return bytes_to_frames(substream->runtime, ptr);
659}
660
661static struct snd_pcm_hardware snd_sonicvibes_playback =
662{
663	.info =			(SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED |
664				 SNDRV_PCM_INFO_BLOCK_TRANSFER |
665				 SNDRV_PCM_INFO_MMAP_VALID),
666	.formats =		SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S16_LE,
667	.rates =		SNDRV_PCM_RATE_CONTINUOUS | SNDRV_PCM_RATE_8000_48000,
668	.rate_min =		4000,
669	.rate_max =		48000,
670	.channels_min =		1,
671	.channels_max =		2,
672	.buffer_bytes_max =	(128*1024),
673	.period_bytes_min =	32,
674	.period_bytes_max =	(128*1024),
675	.periods_min =		1,
676	.periods_max =		1024,
677	.fifo_size =		0,
678};
679
680static struct snd_pcm_hardware snd_sonicvibes_capture =
681{
682	.info =			(SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED |
683				 SNDRV_PCM_INFO_BLOCK_TRANSFER |
684				 SNDRV_PCM_INFO_MMAP_VALID),
685	.formats =		SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S16_LE,
686	.rates =		SNDRV_PCM_RATE_CONTINUOUS | SNDRV_PCM_RATE_8000_48000,
687	.rate_min =		4000,
688	.rate_max =		48000,
689	.channels_min =		1,
690	.channels_max =		2,
691	.buffer_bytes_max =	(128*1024),
692	.period_bytes_min =	32,
693	.period_bytes_max =	(128*1024),
694	.periods_min =		1,
695	.periods_max =		1024,
696	.fifo_size =		0,
697};
698
699static int snd_sonicvibes_playback_open(struct snd_pcm_substream *substream)
700{
701	struct sonicvibes *sonic = snd_pcm_substream_chip(substream);
702	struct snd_pcm_runtime *runtime = substream->runtime;
703
704	sonic->mode |= SV_MODE_PLAY;
705	sonic->playback_substream = substream;
706	runtime->hw = snd_sonicvibes_playback;
707	snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_RATE, snd_sonicvibes_hw_constraint_dac_rate, NULL, SNDRV_PCM_HW_PARAM_RATE, -1);
708	return 0;
709}
710
711static int snd_sonicvibes_capture_open(struct snd_pcm_substream *substream)
712{
713	struct sonicvibes *sonic = snd_pcm_substream_chip(substream);
714	struct snd_pcm_runtime *runtime = substream->runtime;
715
716	sonic->mode |= SV_MODE_CAPTURE;
717	sonic->capture_substream = substream;
718	runtime->hw = snd_sonicvibes_capture;
719	snd_pcm_hw_constraint_ratdens(runtime, 0, SNDRV_PCM_HW_PARAM_RATE,
720				      &snd_sonicvibes_hw_constraints_adc_clock);
721	return 0;
722}
723
724static int snd_sonicvibes_playback_close(struct snd_pcm_substream *substream)
725{
726	struct sonicvibes *sonic = snd_pcm_substream_chip(substream);
727
728	sonic->playback_substream = NULL;
729	sonic->mode &= ~SV_MODE_PLAY;
730	return 0;
731}
732
733static int snd_sonicvibes_capture_close(struct snd_pcm_substream *substream)
734{
735	struct sonicvibes *sonic = snd_pcm_substream_chip(substream);
736
737	sonic->capture_substream = NULL;
738	sonic->mode &= ~SV_MODE_CAPTURE;
739	return 0;
740}
741
742static struct snd_pcm_ops snd_sonicvibes_playback_ops = {
743	.open =		snd_sonicvibes_playback_open,
744	.close =	snd_sonicvibes_playback_close,
745	.ioctl =	snd_pcm_lib_ioctl,
746	.hw_params =	snd_sonicvibes_hw_params,
747	.hw_free =	snd_sonicvibes_hw_free,
748	.prepare =	snd_sonicvibes_playback_prepare,
749	.trigger =	snd_sonicvibes_playback_trigger,
750	.pointer =	snd_sonicvibes_playback_pointer,
751};
752
753static struct snd_pcm_ops snd_sonicvibes_capture_ops = {
754	.open =		snd_sonicvibes_capture_open,
755	.close =	snd_sonicvibes_capture_close,
756	.ioctl =	snd_pcm_lib_ioctl,
757	.hw_params =	snd_sonicvibes_hw_params,
758	.hw_free =	snd_sonicvibes_hw_free,
759	.prepare =	snd_sonicvibes_capture_prepare,
760	.trigger =	snd_sonicvibes_capture_trigger,
761	.pointer =	snd_sonicvibes_capture_pointer,
762};
763
764static int __devinit snd_sonicvibes_pcm(struct sonicvibes * sonic, int device, struct snd_pcm ** rpcm)
765{
766	struct snd_pcm *pcm;
767	int err;
768
769	if ((err = snd_pcm_new(sonic->card, "s3_86c617", device, 1, 1, &pcm)) < 0)
770		return err;
771	snd_assert(pcm != NULL, return -EINVAL);
772
773	snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_sonicvibes_playback_ops);
774	snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_sonicvibes_capture_ops);
775
776	pcm->private_data = sonic;
777	pcm->info_flags = 0;
778	strcpy(pcm->name, "S3 SonicVibes");
779	sonic->pcm = pcm;
780
781	snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV,
782					      snd_dma_pci_data(sonic->pci), 64*1024, 128*1024);
783
784	if (rpcm)
785		*rpcm = pcm;
786	return 0;
787}
788
789/*
790 *  Mixer part
791 */
792
793#define SONICVIBES_MUX(xname, xindex) \
794{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xindex, \
795  .info = snd_sonicvibes_info_mux, \
796  .get = snd_sonicvibes_get_mux, .put = snd_sonicvibes_put_mux }
797
798static int snd_sonicvibes_info_mux(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
799{
800	static char *texts[7] = {
801		"CD", "PCM", "Aux1", "Line", "Aux0", "Mic", "Mix"
802	};
803
804	uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
805	uinfo->count = 2;
806	uinfo->value.enumerated.items = 7;
807	if (uinfo->value.enumerated.item >= 7)
808		uinfo->value.enumerated.item = 6;
809	strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]);
810	return 0;
811}
812
813static int snd_sonicvibes_get_mux(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
814{
815	struct sonicvibes *sonic = snd_kcontrol_chip(kcontrol);
816
817	spin_lock_irq(&sonic->reg_lock);
818	ucontrol->value.enumerated.item[0] = ((snd_sonicvibes_in1(sonic, SV_IREG_LEFT_ADC) & SV_RECSRC_OUT) >> 5) - 1;
819	ucontrol->value.enumerated.item[1] = ((snd_sonicvibes_in1(sonic, SV_IREG_RIGHT_ADC) & SV_RECSRC_OUT) >> 5) - 1;
820	spin_unlock_irq(&sonic->reg_lock);
821	return 0;
822}
823
824static int snd_sonicvibes_put_mux(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
825{
826	struct sonicvibes *sonic = snd_kcontrol_chip(kcontrol);
827	unsigned short left, right, oval1, oval2;
828	int change;
829
830	if (ucontrol->value.enumerated.item[0] >= 7 ||
831	    ucontrol->value.enumerated.item[1] >= 7)
832		return -EINVAL;
833	left = (ucontrol->value.enumerated.item[0] + 1) << 5;
834	right = (ucontrol->value.enumerated.item[1] + 1) << 5;
835	spin_lock_irq(&sonic->reg_lock);
836	oval1 = snd_sonicvibes_in1(sonic, SV_IREG_LEFT_ADC);
837	oval2 = snd_sonicvibes_in1(sonic, SV_IREG_RIGHT_ADC);
838	left = (oval1 & ~SV_RECSRC_OUT) | left;
839	right = (oval2 & ~SV_RECSRC_OUT) | right;
840	change = left != oval1 || right != oval2;
841	snd_sonicvibes_out1(sonic, SV_IREG_LEFT_ADC, left);
842	snd_sonicvibes_out1(sonic, SV_IREG_RIGHT_ADC, right);
843	spin_unlock_irq(&sonic->reg_lock);
844	return change;
845}
846
847#define SONICVIBES_SINGLE(xname, xindex, reg, shift, mask, invert) \
848{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xindex, \
849  .info = snd_sonicvibes_info_single, \
850  .get = snd_sonicvibes_get_single, .put = snd_sonicvibes_put_single, \
851  .private_value = reg | (shift << 8) | (mask << 16) | (invert << 24) }
852
853static int snd_sonicvibes_info_single(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
854{
855	int mask = (kcontrol->private_value >> 16) & 0xff;
856
857	uinfo->type = mask == 1 ? SNDRV_CTL_ELEM_TYPE_BOOLEAN : SNDRV_CTL_ELEM_TYPE_INTEGER;
858	uinfo->count = 1;
859	uinfo->value.integer.min = 0;
860	uinfo->value.integer.max = mask;
861	return 0;
862}
863
864static int snd_sonicvibes_get_single(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
865{
866	struct sonicvibes *sonic = snd_kcontrol_chip(kcontrol);
867	int reg = kcontrol->private_value & 0xff;
868	int shift = (kcontrol->private_value >> 8) & 0xff;
869	int mask = (kcontrol->private_value >> 16) & 0xff;
870	int invert = (kcontrol->private_value >> 24) & 0xff;
871
872	spin_lock_irq(&sonic->reg_lock);
873	ucontrol->value.integer.value[0] = (snd_sonicvibes_in1(sonic, reg)>> shift) & mask;
874	spin_unlock_irq(&sonic->reg_lock);
875	if (invert)
876		ucontrol->value.integer.value[0] = mask - ucontrol->value.integer.value[0];
877	return 0;
878}
879
880static int snd_sonicvibes_put_single(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
881{
882	struct sonicvibes *sonic = snd_kcontrol_chip(kcontrol);
883	int reg = kcontrol->private_value & 0xff;
884	int shift = (kcontrol->private_value >> 8) & 0xff;
885	int mask = (kcontrol->private_value >> 16) & 0xff;
886	int invert = (kcontrol->private_value >> 24) & 0xff;
887	int change;
888	unsigned short val, oval;
889
890	val = (ucontrol->value.integer.value[0] & mask);
891	if (invert)
892		val = mask - val;
893	val <<= shift;
894	spin_lock_irq(&sonic->reg_lock);
895	oval = snd_sonicvibes_in1(sonic, reg);
896	val = (oval & ~(mask << shift)) | val;
897	change = val != oval;
898	snd_sonicvibes_out1(sonic, reg, val);
899	spin_unlock_irq(&sonic->reg_lock);
900	return change;
901}
902
903#define SONICVIBES_DOUBLE(xname, xindex, left_reg, right_reg, shift_left, shift_right, mask, invert) \
904{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xindex, \
905  .info = snd_sonicvibes_info_double, \
906  .get = snd_sonicvibes_get_double, .put = snd_sonicvibes_put_double, \
907  .private_value = left_reg | (right_reg << 8) | (shift_left << 16) | (shift_right << 19) | (mask << 24) | (invert << 22) }
908
909static int snd_sonicvibes_info_double(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
910{
911	int mask = (kcontrol->private_value >> 24) & 0xff;
912
913	uinfo->type = mask == 1 ? SNDRV_CTL_ELEM_TYPE_BOOLEAN : SNDRV_CTL_ELEM_TYPE_INTEGER;
914	uinfo->count = 2;
915	uinfo->value.integer.min = 0;
916	uinfo->value.integer.max = mask;
917	return 0;
918}
919
920static int snd_sonicvibes_get_double(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
921{
922	struct sonicvibes *sonic = snd_kcontrol_chip(kcontrol);
923	int left_reg = kcontrol->private_value & 0xff;
924	int right_reg = (kcontrol->private_value >> 8) & 0xff;
925	int shift_left = (kcontrol->private_value >> 16) & 0x07;
926	int shift_right = (kcontrol->private_value >> 19) & 0x07;
927	int mask = (kcontrol->private_value >> 24) & 0xff;
928	int invert = (kcontrol->private_value >> 22) & 1;
929
930	spin_lock_irq(&sonic->reg_lock);
931	ucontrol->value.integer.value[0] = (snd_sonicvibes_in1(sonic, left_reg) >> shift_left) & mask;
932	ucontrol->value.integer.value[1] = (snd_sonicvibes_in1(sonic, right_reg) >> shift_right) & mask;
933	spin_unlock_irq(&sonic->reg_lock);
934	if (invert) {
935		ucontrol->value.integer.value[0] = mask - ucontrol->value.integer.value[0];
936		ucontrol->value.integer.value[1] = mask - ucontrol->value.integer.value[1];
937	}
938	return 0;
939}
940
941static int snd_sonicvibes_put_double(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
942{
943	struct sonicvibes *sonic = snd_kcontrol_chip(kcontrol);
944	int left_reg = kcontrol->private_value & 0xff;
945	int right_reg = (kcontrol->private_value >> 8) & 0xff;
946	int shift_left = (kcontrol->private_value >> 16) & 0x07;
947	int shift_right = (kcontrol->private_value >> 19) & 0x07;
948	int mask = (kcontrol->private_value >> 24) & 0xff;
949	int invert = (kcontrol->private_value >> 22) & 1;
950	int change;
951	unsigned short val1, val2, oval1, oval2;
952
953	val1 = ucontrol->value.integer.value[0] & mask;
954	val2 = ucontrol->value.integer.value[1] & mask;
955	if (invert) {
956		val1 = mask - val1;
957		val2 = mask - val2;
958	}
959	val1 <<= shift_left;
960	val2 <<= shift_right;
961	spin_lock_irq(&sonic->reg_lock);
962	oval1 = snd_sonicvibes_in1(sonic, left_reg);
963	oval2 = snd_sonicvibes_in1(sonic, right_reg);
964	val1 = (oval1 & ~(mask << shift_left)) | val1;
965	val2 = (oval2 & ~(mask << shift_right)) | val2;
966	change = val1 != oval1 || val2 != oval2;
967	snd_sonicvibes_out1(sonic, left_reg, val1);
968	snd_sonicvibes_out1(sonic, right_reg, val2);
969	spin_unlock_irq(&sonic->reg_lock);
970	return change;
971}
972
973static struct snd_kcontrol_new snd_sonicvibes_controls[] __devinitdata = {
974SONICVIBES_DOUBLE("Capture Volume", 0, SV_IREG_LEFT_ADC, SV_IREG_RIGHT_ADC, 0, 0, 15, 0),
975SONICVIBES_DOUBLE("Aux Playback Switch", 0, SV_IREG_LEFT_AUX1, SV_IREG_RIGHT_AUX1, 7, 7, 1, 1),
976SONICVIBES_DOUBLE("Aux Playback Volume", 0, SV_IREG_LEFT_AUX1, SV_IREG_RIGHT_AUX1, 0, 0, 31, 1),
977SONICVIBES_DOUBLE("CD Playback Switch", 0, SV_IREG_LEFT_CD, SV_IREG_RIGHT_CD, 7, 7, 1, 1),
978SONICVIBES_DOUBLE("CD Playback Volume", 0, SV_IREG_LEFT_CD, SV_IREG_RIGHT_CD, 0, 0, 31, 1),
979SONICVIBES_DOUBLE("Line Playback Switch", 0, SV_IREG_LEFT_LINE, SV_IREG_RIGHT_LINE, 7, 7, 1, 1),
980SONICVIBES_DOUBLE("Line Playback Volume", 0, SV_IREG_LEFT_LINE, SV_IREG_RIGHT_LINE, 0, 0, 31, 1),
981SONICVIBES_SINGLE("Mic Playback Switch", 0, SV_IREG_MIC, 7, 1, 1),
982SONICVIBES_SINGLE("Mic Playback Volume", 0, SV_IREG_MIC, 0, 15, 1),
983SONICVIBES_SINGLE("Mic Boost", 0, SV_IREG_LEFT_ADC, 4, 1, 0),
984SONICVIBES_DOUBLE("Synth Playback Switch", 0, SV_IREG_LEFT_SYNTH, SV_IREG_RIGHT_SYNTH, 7, 7, 1, 1),
985SONICVIBES_DOUBLE("Synth Playback Volume", 0, SV_IREG_LEFT_SYNTH, SV_IREG_RIGHT_SYNTH, 0, 0, 31, 1),
986SONICVIBES_DOUBLE("Aux Playback Switch", 1, SV_IREG_LEFT_AUX2, SV_IREG_RIGHT_AUX2, 7, 7, 1, 1),
987SONICVIBES_DOUBLE("Aux Playback Volume", 1, SV_IREG_LEFT_AUX2, SV_IREG_RIGHT_AUX2, 0, 0, 31, 1),
988SONICVIBES_DOUBLE("Master Playback Switch", 0, SV_IREG_LEFT_ANALOG, SV_IREG_RIGHT_ANALOG, 7, 7, 1, 1),
989SONICVIBES_DOUBLE("Master Playback Volume", 0, SV_IREG_LEFT_ANALOG, SV_IREG_RIGHT_ANALOG, 0, 0, 31, 1),
990SONICVIBES_DOUBLE("PCM Playback Switch", 0, SV_IREG_LEFT_PCM, SV_IREG_RIGHT_PCM, 7, 7, 1, 1),
991SONICVIBES_DOUBLE("PCM Playback Volume", 0, SV_IREG_LEFT_PCM, SV_IREG_RIGHT_PCM, 0, 0, 63, 1),
992SONICVIBES_SINGLE("Loopback Capture Switch", 0, SV_IREG_ADC_OUTPUT_CTRL, 0, 1, 0),
993SONICVIBES_SINGLE("Loopback Capture Volume", 0, SV_IREG_ADC_OUTPUT_CTRL, 2, 63, 1),
994SONICVIBES_MUX("Capture Source", 0)
995};
996
997static void snd_sonicvibes_master_free(struct snd_kcontrol *kcontrol)
998{
999	struct sonicvibes *sonic = snd_kcontrol_chip(kcontrol);
1000	sonic->master_mute = NULL;
1001	sonic->master_volume = NULL;
1002}
1003
1004static int __devinit snd_sonicvibes_mixer(struct sonicvibes * sonic)
1005{
1006	struct snd_card *card;
1007	struct snd_kcontrol *kctl;
1008	unsigned int idx;
1009	int err;
1010
1011	snd_assert(sonic != NULL && sonic->card != NULL, return -EINVAL);
1012	card = sonic->card;
1013	strcpy(card->mixername, "S3 SonicVibes");
1014
1015	for (idx = 0; idx < ARRAY_SIZE(snd_sonicvibes_controls); idx++) {
1016		if ((err = snd_ctl_add(card, kctl = snd_ctl_new1(&snd_sonicvibes_controls[idx], sonic))) < 0)
1017			return err;
1018		switch (idx) {
1019		case 0:
1020		case 1: kctl->private_free = snd_sonicvibes_master_free; break;
1021		}
1022	}
1023	return 0;
1024}
1025
1026/*
1027
1028 */
1029
1030static void snd_sonicvibes_proc_read(struct snd_info_entry *entry,
1031				     struct snd_info_buffer *buffer)
1032{
1033	struct sonicvibes *sonic = entry->private_data;
1034	unsigned char tmp;
1035
1036	tmp = sonic->srs_space & 0x0f;
1037	snd_iprintf(buffer, "SRS 3D           : %s\n",
1038		    sonic->srs_space & 0x80 ? "off" : "on");
1039	snd_iprintf(buffer, "SRS Space        : %s\n",
1040		    tmp == 0x00 ? "100%" :
1041		    tmp == 0x01 ? "75%" :
1042		    tmp == 0x02 ? "50%" :
1043		    tmp == 0x03 ? "25%" : "0%");
1044	tmp = sonic->srs_center & 0x0f;
1045	snd_iprintf(buffer, "SRS Center       : %s\n",
1046		    tmp == 0x00 ? "100%" :
1047		    tmp == 0x01 ? "75%" :
1048		    tmp == 0x02 ? "50%" :
1049		    tmp == 0x03 ? "25%" : "0%");
1050	tmp = sonic->wave_source & 0x03;
1051	snd_iprintf(buffer, "WaveTable Source : %s\n",
1052		    tmp == 0x00 ? "on-board ROM" :
1053		    tmp == 0x01 ? "PCI bus" : "on-board ROM + PCI bus");
1054	tmp = sonic->mpu_switch;
1055	snd_iprintf(buffer, "Onboard synth    : %s\n", tmp & 0x01 ? "on" : "off");
1056	snd_iprintf(buffer, "Ext. Rx to synth : %s\n", tmp & 0x02 ? "on" : "off");
1057	snd_iprintf(buffer, "MIDI to ext. Tx  : %s\n", tmp & 0x04 ? "on" : "off");
1058}
1059
1060static void __devinit snd_sonicvibes_proc_init(struct sonicvibes * sonic)
1061{
1062	struct snd_info_entry *entry;
1063
1064	if (! snd_card_proc_new(sonic->card, "sonicvibes", &entry))
1065		snd_info_set_text_ops(entry, sonic, snd_sonicvibes_proc_read);
1066}
1067
1068/*
1069
1070 */
1071
1072#ifdef SUPPORT_JOYSTICK
1073static struct snd_kcontrol_new snd_sonicvibes_game_control __devinitdata =
1074SONICVIBES_SINGLE("Joystick Speed", 0, SV_IREG_GAME_PORT, 1, 15, 0);
1075
1076static int __devinit snd_sonicvibes_create_gameport(struct sonicvibes *sonic)
1077{
1078	struct gameport *gp;
1079
1080	sonic->gameport = gp = gameport_allocate_port();
1081	if (!gp) {
1082		printk(KERN_ERR "sonicvibes: cannot allocate memory for gameport\n");
1083		return -ENOMEM;
1084	}
1085
1086	gameport_set_name(gp, "SonicVibes Gameport");
1087	gameport_set_phys(gp, "pci%s/gameport0", pci_name(sonic->pci));
1088	gameport_set_dev_parent(gp, &sonic->pci->dev);
1089	gp->io = sonic->game_port;
1090
1091	gameport_register_port(gp);
1092
1093	snd_ctl_add(sonic->card, snd_ctl_new1(&snd_sonicvibes_game_control, sonic));
1094
1095	return 0;
1096}
1097
1098static void snd_sonicvibes_free_gameport(struct sonicvibes *sonic)
1099{
1100	if (sonic->gameport) {
1101		gameport_unregister_port(sonic->gameport);
1102		sonic->gameport = NULL;
1103	}
1104}
1105#else
1106static inline int snd_sonicvibes_create_gameport(struct sonicvibes *sonic) { return -ENOSYS; }
1107static inline void snd_sonicvibes_free_gameport(struct sonicvibes *sonic) { }
1108#endif
1109
1110static int snd_sonicvibes_free(struct sonicvibes *sonic)
1111{
1112	snd_sonicvibes_free_gameport(sonic);
1113	pci_write_config_dword(sonic->pci, 0x40, sonic->dmaa_port);
1114	pci_write_config_dword(sonic->pci, 0x48, sonic->dmac_port);
1115	if (sonic->irq >= 0)
1116		free_irq(sonic->irq, sonic);
1117	release_and_free_resource(sonic->res_dmaa);
1118	release_and_free_resource(sonic->res_dmac);
1119	pci_release_regions(sonic->pci);
1120	pci_disable_device(sonic->pci);
1121	kfree(sonic);
1122	return 0;
1123}
1124
1125static int snd_sonicvibes_dev_free(struct snd_device *device)
1126{
1127	struct sonicvibes *sonic = device->device_data;
1128	return snd_sonicvibes_free(sonic);
1129}
1130
1131static int __devinit snd_sonicvibes_create(struct snd_card *card,
1132					struct pci_dev *pci,
1133					int reverb,
1134					int mge,
1135					struct sonicvibes ** rsonic)
1136{
1137	struct sonicvibes *sonic;
1138	unsigned int dmaa, dmac;
1139	int err;
1140	static struct snd_device_ops ops = {
1141		.dev_free =	snd_sonicvibes_dev_free,
1142	};
1143
1144	*rsonic = NULL;
1145	/* enable PCI device */
1146	if ((err = pci_enable_device(pci)) < 0)
1147		return err;
1148	/* check, if we can restrict PCI DMA transfers to 24 bits */
1149        if (pci_set_dma_mask(pci, DMA_24BIT_MASK) < 0 ||
1150	    pci_set_consistent_dma_mask(pci, DMA_24BIT_MASK) < 0) {
1151		snd_printk(KERN_ERR "architecture does not support 24bit PCI busmaster DMA\n");
1152		pci_disable_device(pci);
1153                return -ENXIO;
1154        }
1155
1156	sonic = kzalloc(sizeof(*sonic), GFP_KERNEL);
1157	if (sonic == NULL) {
1158		pci_disable_device(pci);
1159		return -ENOMEM;
1160	}
1161	spin_lock_init(&sonic->reg_lock);
1162	sonic->card = card;
1163	sonic->pci = pci;
1164	sonic->irq = -1;
1165
1166	if ((err = pci_request_regions(pci, "S3 SonicVibes")) < 0) {
1167		kfree(sonic);
1168		pci_disable_device(pci);
1169		return err;
1170	}
1171
1172	sonic->sb_port = pci_resource_start(pci, 0);
1173	sonic->enh_port = pci_resource_start(pci, 1);
1174	sonic->synth_port = pci_resource_start(pci, 2);
1175	sonic->midi_port = pci_resource_start(pci, 3);
1176	sonic->game_port = pci_resource_start(pci, 4);
1177
1178	if (request_irq(pci->irq, snd_sonicvibes_interrupt, IRQF_SHARED,
1179			"S3 SonicVibes", sonic)) {
1180		snd_printk(KERN_ERR "unable to grab IRQ %d\n", pci->irq);
1181		snd_sonicvibes_free(sonic);
1182		return -EBUSY;
1183	}
1184	sonic->irq = pci->irq;
1185
1186	pci_read_config_dword(pci, 0x40, &dmaa);
1187	pci_read_config_dword(pci, 0x48, &dmac);
1188	dmaio &= ~0x0f;
1189	dmaa &= ~0x0f;
1190	dmac &= ~0x0f;
1191	if (!dmaa) {
1192		dmaa = dmaio;
1193		dmaio += 0x10;
1194		snd_printk(KERN_INFO "BIOS did not allocate DDMA channel A i/o, allocated at 0x%x\n", dmaa);
1195	}
1196	if (!dmac) {
1197		dmac = dmaio;
1198		dmaio += 0x10;
1199		snd_printk(KERN_INFO "BIOS did not allocate DDMA channel C i/o, allocated at 0x%x\n", dmac);
1200	}
1201	pci_write_config_dword(pci, 0x40, dmaa);
1202	pci_write_config_dword(pci, 0x48, dmac);
1203
1204	if ((sonic->res_dmaa = request_region(dmaa, 0x10, "S3 SonicVibes DDMA-A")) == NULL) {
1205		snd_sonicvibes_free(sonic);
1206		snd_printk(KERN_ERR "unable to grab DDMA-A port at 0x%x-0x%x\n", dmaa, dmaa + 0x10 - 1);
1207		return -EBUSY;
1208	}
1209	if ((sonic->res_dmac = request_region(dmac, 0x10, "S3 SonicVibes DDMA-C")) == NULL) {
1210		snd_sonicvibes_free(sonic);
1211		snd_printk(KERN_ERR "unable to grab DDMA-C port at 0x%x-0x%x\n", dmac, dmac + 0x10 - 1);
1212		return -EBUSY;
1213	}
1214
1215	pci_read_config_dword(pci, 0x40, &sonic->dmaa_port);
1216	pci_read_config_dword(pci, 0x48, &sonic->dmac_port);
1217	sonic->dmaa_port &= ~0x0f;
1218	sonic->dmac_port &= ~0x0f;
1219	pci_write_config_dword(pci, 0x40, sonic->dmaa_port | 9);	/* enable + enhanced */
1220	pci_write_config_dword(pci, 0x48, sonic->dmac_port | 9);	/* enable */
1221	/* ok.. initialize S3 SonicVibes chip */
1222	outb(SV_RESET, SV_REG(sonic, CONTROL));		/* reset chip */
1223	udelay(100);
1224	outb(0, SV_REG(sonic, CONTROL));	/* release reset */
1225	udelay(100);
1226	outb(SV_ENHANCED | SV_INTA | (reverb ? SV_REVERB : 0), SV_REG(sonic, CONTROL));
1227	inb(SV_REG(sonic, STATUS));	/* clear IRQs */
1228	snd_sonicvibes_out(sonic, SV_IREG_DRIVE_CTRL, 0);	/* drive current 16mA */
1229	snd_sonicvibes_out(sonic, SV_IREG_PC_ENABLE, sonic->enable = 0);	/* disable playback & capture */
1230	outb(sonic->irqmask = ~(SV_DMAA_MASK | SV_DMAC_MASK | SV_UD_MASK), SV_REG(sonic, IRQMASK));
1231	inb(SV_REG(sonic, STATUS));	/* clear IRQs */
1232	snd_sonicvibes_out(sonic, SV_IREG_ADC_CLOCK, 0);	/* use PLL as clock source */
1233	snd_sonicvibes_out(sonic, SV_IREG_ANALOG_POWER, 0);	/* power up analog parts */
1234	snd_sonicvibes_out(sonic, SV_IREG_DIGITAL_POWER, 0);	/* power up digital parts */
1235	snd_sonicvibes_setpll(sonic, SV_IREG_ADC_PLL, 8000);
1236	snd_sonicvibes_out(sonic, SV_IREG_SRS_SPACE, sonic->srs_space = 0x80);	/* SRS space off */
1237	snd_sonicvibes_out(sonic, SV_IREG_SRS_CENTER, sonic->srs_center = 0x00);/* SRS center off */
1238	snd_sonicvibes_out(sonic, SV_IREG_MPU401, sonic->mpu_switch = 0x05);	/* MPU-401 switch */
1239	snd_sonicvibes_out(sonic, SV_IREG_WAVE_SOURCE, sonic->wave_source = 0x00);	/* onboard ROM */
1240	snd_sonicvibes_out(sonic, SV_IREG_PCM_RATE_LOW, (8000 * 65536 / SV_FULLRATE) & 0xff);
1241	snd_sonicvibes_out(sonic, SV_IREG_PCM_RATE_HIGH, ((8000 * 65536 / SV_FULLRATE) >> 8) & 0xff);
1242	snd_sonicvibes_out(sonic, SV_IREG_LEFT_ADC, mge ? 0xd0 : 0xc0);
1243	snd_sonicvibes_out(sonic, SV_IREG_RIGHT_ADC, 0xc0);
1244	snd_sonicvibes_out(sonic, SV_IREG_LEFT_AUX1, 0x9f);
1245	snd_sonicvibes_out(sonic, SV_IREG_RIGHT_AUX1, 0x9f);
1246	snd_sonicvibes_out(sonic, SV_IREG_LEFT_CD, 0x9f);
1247	snd_sonicvibes_out(sonic, SV_IREG_RIGHT_CD, 0x9f);
1248	snd_sonicvibes_out(sonic, SV_IREG_LEFT_LINE, 0x9f);
1249	snd_sonicvibes_out(sonic, SV_IREG_RIGHT_LINE, 0x9f);
1250	snd_sonicvibes_out(sonic, SV_IREG_MIC, 0x8f);
1251	snd_sonicvibes_out(sonic, SV_IREG_LEFT_SYNTH, 0x9f);
1252	snd_sonicvibes_out(sonic, SV_IREG_RIGHT_SYNTH, 0x9f);
1253	snd_sonicvibes_out(sonic, SV_IREG_LEFT_AUX2, 0x9f);
1254	snd_sonicvibes_out(sonic, SV_IREG_RIGHT_AUX2, 0x9f);
1255	snd_sonicvibes_out(sonic, SV_IREG_LEFT_ANALOG, 0x9f);
1256	snd_sonicvibes_out(sonic, SV_IREG_RIGHT_ANALOG, 0x9f);
1257	snd_sonicvibes_out(sonic, SV_IREG_LEFT_PCM, 0xbf);
1258	snd_sonicvibes_out(sonic, SV_IREG_RIGHT_PCM, 0xbf);
1259	snd_sonicvibes_out(sonic, SV_IREG_ADC_OUTPUT_CTRL, 0xfc);
1260	sonic->revision = snd_sonicvibes_in(sonic, SV_IREG_REVISION);
1261
1262	if ((err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, sonic, &ops)) < 0) {
1263		snd_sonicvibes_free(sonic);
1264		return err;
1265	}
1266
1267	snd_sonicvibes_proc_init(sonic);
1268
1269	snd_card_set_dev(card, &pci->dev);
1270
1271	*rsonic = sonic;
1272	return 0;
1273}
1274
1275/*
1276 *  MIDI section
1277 */
1278
1279static struct snd_kcontrol_new snd_sonicvibes_midi_controls[] __devinitdata = {
1280SONICVIBES_SINGLE("SonicVibes Wave Source RAM", 0, SV_IREG_WAVE_SOURCE, 0, 1, 0),
1281SONICVIBES_SINGLE("SonicVibes Wave Source RAM+ROM", 0, SV_IREG_WAVE_SOURCE, 1, 1, 0),
1282SONICVIBES_SINGLE("SonicVibes Onboard Synth", 0, SV_IREG_MPU401, 0, 1, 0),
1283SONICVIBES_SINGLE("SonicVibes External Rx to Synth", 0, SV_IREG_MPU401, 1, 1, 0),
1284SONICVIBES_SINGLE("SonicVibes External Tx", 0, SV_IREG_MPU401, 2, 1, 0)
1285};
1286
1287static int snd_sonicvibes_midi_input_open(struct snd_mpu401 * mpu)
1288{
1289	struct sonicvibes *sonic = mpu->private_data;
1290	outb(sonic->irqmask &= ~SV_MIDI_MASK, SV_REG(sonic, IRQMASK));
1291	return 0;
1292}
1293
1294static void snd_sonicvibes_midi_input_close(struct snd_mpu401 * mpu)
1295{
1296	struct sonicvibes *sonic = mpu->private_data;
1297	outb(sonic->irqmask |= SV_MIDI_MASK, SV_REG(sonic, IRQMASK));
1298}
1299
1300static int __devinit snd_sonicvibes_midi(struct sonicvibes * sonic,
1301					 struct snd_rawmidi *rmidi)
1302{
1303	struct snd_mpu401 * mpu = rmidi->private_data;
1304	struct snd_card *card = sonic->card;
1305	struct snd_rawmidi_str *dir;
1306	unsigned int idx;
1307	int err;
1308
1309	mpu->private_data = sonic;
1310	mpu->open_input = snd_sonicvibes_midi_input_open;
1311	mpu->close_input = snd_sonicvibes_midi_input_close;
1312	dir = &rmidi->streams[SNDRV_RAWMIDI_STREAM_OUTPUT];
1313	for (idx = 0; idx < ARRAY_SIZE(snd_sonicvibes_midi_controls); idx++)
1314		if ((err = snd_ctl_add(card, snd_ctl_new1(&snd_sonicvibes_midi_controls[idx], sonic))) < 0)
1315			return err;
1316	return 0;
1317}
1318
1319static int __devinit snd_sonic_probe(struct pci_dev *pci,
1320				     const struct pci_device_id *pci_id)
1321{
1322	static int dev;
1323	struct snd_card *card;
1324	struct sonicvibes *sonic;
1325	struct snd_rawmidi *midi_uart;
1326	struct snd_opl3 *opl3;
1327	int idx, err;
1328
1329	if (dev >= SNDRV_CARDS)
1330		return -ENODEV;
1331	if (!enable[dev]) {
1332		dev++;
1333		return -ENOENT;
1334	}
1335
1336	card = snd_card_new(index[dev], id[dev], THIS_MODULE, 0);
1337	if (card == NULL)
1338		return -ENOMEM;
1339	for (idx = 0; idx < 5; idx++) {
1340		if (pci_resource_start(pci, idx) == 0 ||
1341		    !(pci_resource_flags(pci, idx) & IORESOURCE_IO)) {
1342			snd_card_free(card);
1343			return -ENODEV;
1344		}
1345	}
1346	if ((err = snd_sonicvibes_create(card, pci,
1347					 reverb[dev] ? 1 : 0,
1348					 mge[dev] ? 1 : 0,
1349					 &sonic)) < 0) {
1350		snd_card_free(card);
1351		return err;
1352	}
1353
1354	strcpy(card->driver, "SonicVibes");
1355	strcpy(card->shortname, "S3 SonicVibes");
1356	sprintf(card->longname, "%s rev %i at 0x%llx, irq %i",
1357		card->shortname,
1358		sonic->revision,
1359		(unsigned long long)pci_resource_start(pci, 1),
1360		sonic->irq);
1361
1362	if ((err = snd_sonicvibes_pcm(sonic, 0, NULL)) < 0) {
1363		snd_card_free(card);
1364		return err;
1365	}
1366	if ((err = snd_sonicvibes_mixer(sonic)) < 0) {
1367		snd_card_free(card);
1368		return err;
1369	}
1370	if ((err = snd_mpu401_uart_new(card, 0, MPU401_HW_SONICVIBES,
1371				       sonic->midi_port, MPU401_INFO_INTEGRATED,
1372				       sonic->irq, 0,
1373				       &midi_uart)) < 0) {
1374		snd_card_free(card);
1375		return err;
1376	}
1377	snd_sonicvibes_midi(sonic, midi_uart);
1378	if ((err = snd_opl3_create(card, sonic->synth_port,
1379				   sonic->synth_port + 2,
1380				   OPL3_HW_OPL3_SV, 1, &opl3)) < 0) {
1381		snd_card_free(card);
1382		return err;
1383	}
1384	if ((err = snd_opl3_hwdep_new(opl3, 0, 1, NULL)) < 0) {
1385		snd_card_free(card);
1386		return err;
1387	}
1388
1389	snd_sonicvibes_create_gameport(sonic);
1390
1391	if ((err = snd_card_register(card)) < 0) {
1392		snd_card_free(card);
1393		return err;
1394	}
1395
1396	pci_set_drvdata(pci, card);
1397	dev++;
1398	return 0;
1399}
1400
1401static void __devexit snd_sonic_remove(struct pci_dev *pci)
1402{
1403	snd_card_free(pci_get_drvdata(pci));
1404	pci_set_drvdata(pci, NULL);
1405}
1406
1407static struct pci_driver driver = {
1408	.name = "S3 SonicVibes",
1409	.id_table = snd_sonic_ids,
1410	.probe = snd_sonic_probe,
1411	.remove = __devexit_p(snd_sonic_remove),
1412};
1413
1414static int __init alsa_card_sonicvibes_init(void)
1415{
1416	return pci_register_driver(&driver);
1417}
1418
1419static void __exit alsa_card_sonicvibes_exit(void)
1420{
1421	pci_unregister_driver(&driver);
1422}
1423
1424module_init(alsa_card_sonicvibes_init)
1425module_exit(alsa_card_sonicvibes_exit)
1426