28 #include <linux/pci.h>
29 #include <linux/slab.h>
30 #include <linux/gameport.h>
31 #include <linux/module.h>
49 #if defined(CONFIG_GAMEPORT) || (defined(MODULE) && defined(CONFIG_GAMEPORT_MODULE))
50 #define SUPPORT_JOYSTICK 1
58 static unsigned int dmaio = 0x7a00;
67 MODULE_PARM_DESC(reverb,
"Enable reverb (SRAM is present) for S3 SonicVibes soundcard.");
71 MODULE_PARM_DESC(dmaio,
"DDMA i/o base address for S3 SonicVibes soundcard.");
77 #define SV_REG(sonic, x) ((sonic)->enh_port + SV_REG_##x)
79 #define SV_REG_CONTROL 0x00
80 #define SV_ENHANCED 0x01
82 #define SV_REVERB 0x04
83 #define SV_WAVETABLE 0x08
86 #define SV_REG_IRQMASK 0x01
87 #define SV_DMAA_MASK 0x01
88 #define SV_DMAC_MASK 0x04
89 #define SV_SPEC_MASK 0x08
90 #define SV_UD_MASK 0x40
91 #define SV_MIDI_MASK 0x80
92 #define SV_REG_STATUS 0x02
93 #define SV_DMAA_IRQ 0x01
94 #define SV_DMAC_IRQ 0x04
95 #define SV_SPEC_IRQ 0x08
96 #define SV_UD_IRQ 0x40
97 #define SV_MIDI_IRQ 0x80
98 #define SV_REG_INDEX 0x04
101 #define SV_REG_DATA 0x05
107 #define SV_IREG_LEFT_ADC 0x00
108 #define SV_IREG_RIGHT_ADC 0x01
109 #define SV_IREG_LEFT_AUX1 0x02
110 #define SV_IREG_RIGHT_AUX1 0x03
111 #define SV_IREG_LEFT_CD 0x04
112 #define SV_IREG_RIGHT_CD 0x05
113 #define SV_IREG_LEFT_LINE 0x06
114 #define SV_IREG_RIGHT_LINE 0x07
115 #define SV_IREG_MIC 0x08
116 #define SV_IREG_GAME_PORT 0x09
117 #define SV_IREG_LEFT_SYNTH 0x0a
118 #define SV_IREG_RIGHT_SYNTH 0x0b
119 #define SV_IREG_LEFT_AUX2 0x0c
120 #define SV_IREG_RIGHT_AUX2 0x0d
121 #define SV_IREG_LEFT_ANALOG 0x0e
122 #define SV_IREG_RIGHT_ANALOG 0x0f
123 #define SV_IREG_LEFT_PCM 0x10
124 #define SV_IREG_RIGHT_PCM 0x11
125 #define SV_IREG_DMA_DATA_FMT 0x12
126 #define SV_IREG_PC_ENABLE 0x13
127 #define SV_IREG_UD_BUTTON 0x14
128 #define SV_IREG_REVISION 0x15
129 #define SV_IREG_ADC_OUTPUT_CTRL 0x16
130 #define SV_IREG_DMA_A_UPPER 0x18
131 #define SV_IREG_DMA_A_LOWER 0x19
132 #define SV_IREG_DMA_C_UPPER 0x1c
133 #define SV_IREG_DMA_C_LOWER 0x1d
134 #define SV_IREG_PCM_RATE_LOW 0x1e
135 #define SV_IREG_PCM_RATE_HIGH 0x1f
136 #define SV_IREG_SYNTH_RATE_LOW 0x20
137 #define SV_IREG_SYNTH_RATE_HIGH 0x21
138 #define SV_IREG_ADC_CLOCK 0x22
139 #define SV_IREG_ADC_ALT_RATE 0x23
140 #define SV_IREG_ADC_PLL_M 0x24
141 #define SV_IREG_ADC_PLL_N 0x25
142 #define SV_IREG_SYNTH_PLL_M 0x26
143 #define SV_IREG_SYNTH_PLL_N 0x27
144 #define SV_IREG_MPU401 0x2a
145 #define SV_IREG_DRIVE_CTRL 0x2b
146 #define SV_IREG_SRS_SPACE 0x2c
147 #define SV_IREG_SRS_CENTER 0x2d
148 #define SV_IREG_WAVE_SOURCE 0x2e
149 #define SV_IREG_ANALOG_POWER 0x30
150 #define SV_IREG_DIGITAL_POWER 0x31
152 #define SV_IREG_ADC_PLL SV_IREG_ADC_PLL_M
153 #define SV_IREG_SYNTH_PLL SV_IREG_SYNTH_PLL_M
159 #define SV_DMA_ADDR0 0x00
160 #define SV_DMA_ADDR1 0x01
161 #define SV_DMA_ADDR2 0x02
162 #define SV_DMA_ADDR3 0x03
163 #define SV_DMA_COUNT0 0x04
164 #define SV_DMA_COUNT1 0x05
165 #define SV_DMA_COUNT2 0x06
166 #define SV_DMA_MODE 0x0b
167 #define SV_DMA_RESET 0x0d
168 #define SV_DMA_MASK 0x0f
174 #define SV_RECSRC_RESERVED (0x00<<5)
175 #define SV_RECSRC_CD (0x01<<5)
176 #define SV_RECSRC_DAC (0x02<<5)
177 #define SV_RECSRC_AUX2 (0x03<<5)
178 #define SV_RECSRC_LINE (0x04<<5)
179 #define SV_RECSRC_AUX1 (0x05<<5)
180 #define SV_RECSRC_MIC (0x06<<5)
181 #define SV_RECSRC_OUT (0x07<<5)
187 #define SV_FULLRATE 48000
188 #define SV_REFFREQUENCY 24576000
189 #define SV_ADCMULT 512
191 #define SV_MODE_PLAY 1
192 #define SV_MODE_CAPTURE 2
240 #ifdef SUPPORT_JOYSTICK
252 static struct snd_ratden sonicvibes_adc_clock = {
253 .num_min = 4000 * 65536,
254 .num_max = 48000
UL * 65536,
260 .rats = &sonicvibes_adc_clock,
267 static inline void snd_sonicvibes_setdmaa(
struct sonicvibes * sonic,
281 static inline void snd_sonicvibes_setdmac(
struct sonicvibes * sonic,
297 static inline unsigned int snd_sonicvibes_getdmaa(
struct sonicvibes * sonic)
302 static inline unsigned int snd_sonicvibes_getdmac(
struct sonicvibes * sonic)
308 static void snd_sonicvibes_out1(
struct sonicvibes * sonic,
318 static void snd_sonicvibes_out(
struct sonicvibes * sonic,
329 spin_unlock_irqrestore(&sonic->
reg_lock, flags);
332 static unsigned char snd_sonicvibes_in1(
struct sonicvibes * sonic,
unsigned char reg)
343 static unsigned char snd_sonicvibes_in(
struct sonicvibes * sonic,
unsigned char reg)
353 spin_unlock_irqrestore(&sonic->
reg_lock, flags);
358 static void snd_sonicvibes_debug(
struct sonicvibes * sonic)
364 " 0x00: left input = 0x%02x ", snd_sonicvibes_in(sonic, 0x00));
365 printk(
" 0x20: synth rate low = 0x%02x\n", snd_sonicvibes_in(sonic, 0x20));
367 " 0x01: right input = 0x%02x ", snd_sonicvibes_in(sonic, 0x01));
368 printk(
" 0x21: synth rate high = 0x%02x\n", snd_sonicvibes_in(sonic, 0x21));
370 " 0x02: left AUX1 = 0x%02x ", snd_sonicvibes_in(sonic, 0x02));
371 printk(
" 0x22: ADC clock = 0x%02x\n", snd_sonicvibes_in(sonic, 0x22));
373 " 0x03: right AUX1 = 0x%02x ", snd_sonicvibes_in(sonic, 0x03));
374 printk(
" 0x23: ADC alt rate = 0x%02x\n", snd_sonicvibes_in(sonic, 0x23));
376 " 0x04: left CD = 0x%02x ", snd_sonicvibes_in(sonic, 0x04));
377 printk(
" 0x24: ADC pll M = 0x%02x\n", snd_sonicvibes_in(sonic, 0x24));
379 " 0x05: right CD = 0x%02x ", snd_sonicvibes_in(sonic, 0x05));
380 printk(
" 0x25: ADC pll N = 0x%02x\n", snd_sonicvibes_in(sonic, 0x25));
382 " 0x06: left line = 0x%02x ", snd_sonicvibes_in(sonic, 0x06));
383 printk(
" 0x26: Synth pll M = 0x%02x\n", snd_sonicvibes_in(sonic, 0x26));
385 " 0x07: right line = 0x%02x ", snd_sonicvibes_in(sonic, 0x07));
386 printk(
" 0x27: Synth pll N = 0x%02x\n", snd_sonicvibes_in(sonic, 0x27));
388 " 0x08: MIC = 0x%02x ", snd_sonicvibes_in(sonic, 0x08));
389 printk(
" 0x28: --- = 0x%02x\n", snd_sonicvibes_in(sonic, 0x28));
391 " 0x09: Game port = 0x%02x ", snd_sonicvibes_in(sonic, 0x09));
392 printk(
" 0x29: --- = 0x%02x\n", snd_sonicvibes_in(sonic, 0x29));
394 " 0x0a: left synth = 0x%02x ", snd_sonicvibes_in(sonic, 0x0a));
395 printk(
" 0x2a: MPU401 = 0x%02x\n", snd_sonicvibes_in(sonic, 0x2a));
397 " 0x0b: right synth = 0x%02x ", snd_sonicvibes_in(sonic, 0x0b));
398 printk(
" 0x2b: drive ctrl = 0x%02x\n", snd_sonicvibes_in(sonic, 0x2b));
400 " 0x0c: left AUX2 = 0x%02x ", snd_sonicvibes_in(sonic, 0x0c));
401 printk(
" 0x2c: SRS space = 0x%02x\n", snd_sonicvibes_in(sonic, 0x2c));
403 " 0x0d: right AUX2 = 0x%02x ", snd_sonicvibes_in(sonic, 0x0d));
404 printk(
" 0x2d: SRS center = 0x%02x\n", snd_sonicvibes_in(sonic, 0x2d));
406 " 0x0e: left analog = 0x%02x ", snd_sonicvibes_in(sonic, 0x0e));
407 printk(
" 0x2e: wave source = 0x%02x\n", snd_sonicvibes_in(sonic, 0x2e));
409 " 0x0f: right analog = 0x%02x ", snd_sonicvibes_in(sonic, 0x0f));
410 printk(
" 0x2f: --- = 0x%02x\n", snd_sonicvibes_in(sonic, 0x2f));
412 " 0x10: left PCM = 0x%02x ", snd_sonicvibes_in(sonic, 0x10));
413 printk(
" 0x30: analog power = 0x%02x\n", snd_sonicvibes_in(sonic, 0x30));
415 " 0x11: right PCM = 0x%02x ", snd_sonicvibes_in(sonic, 0x11));
416 printk(
" 0x31: analog power = 0x%02x\n", snd_sonicvibes_in(sonic, 0x31));
418 " 0x12: DMA data format = 0x%02x ", snd_sonicvibes_in(sonic, 0x12));
419 printk(
" 0x32: --- = 0x%02x\n", snd_sonicvibes_in(sonic, 0x32));
421 " 0x13: P/C enable = 0x%02x ", snd_sonicvibes_in(sonic, 0x13));
422 printk(
" 0x33: --- = 0x%02x\n", snd_sonicvibes_in(sonic, 0x33));
424 " 0x14: U/D button = 0x%02x ", snd_sonicvibes_in(sonic, 0x14));
425 printk(
" 0x34: --- = 0x%02x\n", snd_sonicvibes_in(sonic, 0x34));
427 " 0x15: revision = 0x%02x ", snd_sonicvibes_in(sonic, 0x15));
428 printk(
" 0x35: --- = 0x%02x\n", snd_sonicvibes_in(sonic, 0x35));
430 " 0x16: ADC output ctrl = 0x%02x ", snd_sonicvibes_in(sonic, 0x16));
431 printk(
" 0x36: --- = 0x%02x\n", snd_sonicvibes_in(sonic, 0x36));
433 " 0x17: --- = 0x%02x ", snd_sonicvibes_in(sonic, 0x17));
434 printk(
" 0x37: --- = 0x%02x\n", snd_sonicvibes_in(sonic, 0x37));
436 " 0x18: DMA A upper cnt = 0x%02x ", snd_sonicvibes_in(sonic, 0x18));
437 printk(
" 0x38: --- = 0x%02x\n", snd_sonicvibes_in(sonic, 0x38));
439 " 0x19: DMA A lower cnt = 0x%02x ", snd_sonicvibes_in(sonic, 0x19));
440 printk(
" 0x39: --- = 0x%02x\n", snd_sonicvibes_in(sonic, 0x39));
442 " 0x1a: --- = 0x%02x ", snd_sonicvibes_in(sonic, 0x1a));
443 printk(
" 0x3a: --- = 0x%02x\n", snd_sonicvibes_in(sonic, 0x3a));
445 " 0x1b: --- = 0x%02x ", snd_sonicvibes_in(sonic, 0x1b));
446 printk(
" 0x3b: --- = 0x%02x\n", snd_sonicvibes_in(sonic, 0x3b));
448 " 0x1c: DMA C upper cnt = 0x%02x ", snd_sonicvibes_in(sonic, 0x1c));
449 printk(
" 0x3c: --- = 0x%02x\n", snd_sonicvibes_in(sonic, 0x3c));
451 " 0x1d: DMA C upper cnt = 0x%02x ", snd_sonicvibes_in(sonic, 0x1d));
452 printk(
" 0x3d: --- = 0x%02x\n", snd_sonicvibes_in(sonic, 0x3d));
454 " 0x1e: PCM rate low = 0x%02x ", snd_sonicvibes_in(sonic, 0x1e));
455 printk(
" 0x3e: --- = 0x%02x\n", snd_sonicvibes_in(sonic, 0x3e));
457 " 0x1f: PCM rate high = 0x%02x ", snd_sonicvibes_in(sonic, 0x1f));
458 printk(
" 0x3f: --- = 0x%02x\n", snd_sonicvibes_in(sonic, 0x3f));
463 static void snd_sonicvibes_setfmt(
struct sonicvibes * sonic,
480 spin_unlock_irqrestore(&sonic->
reg_lock, flags);
483 static void snd_sonicvibes_pll(
unsigned int rate,
488 unsigned int r,
m = 0,
n = 0;
489 unsigned int xm, xn,
xr, xd, metric = ~0
U;
496 for (r = 0; rate < 75000000 /
SV_ADCMULT; r += 0x20, rate <<= 1);
497 for (xn = 3; xn < 33; xn++)
498 for (xm = 3; xm < 257; xm++) {
519 static void snd_sonicvibes_setpll(
struct sonicvibes * sonic,
524 unsigned int r,
m,
n;
526 snd_sonicvibes_pll(rate, &r, &m, &n);
529 snd_sonicvibes_out1(sonic, reg, m);
530 snd_sonicvibes_out1(sonic, reg + 1, r | n);
531 spin_unlock_irqrestore(&sonic->
reg_lock, flags);
535 static void snd_sonicvibes_set_adc_rate(
struct sonicvibes * sonic,
unsigned int rate)
544 if ((48000 / div) == rate) {
553 spin_unlock_irqrestore(&sonic->
reg_lock, flags);
567 if ((48000 / div) == rate) {
571 snd_sonicvibes_pll(rate, &r, &m, &n);
581 static void snd_sonicvibes_set_dac_rate(
struct sonicvibes * sonic,
unsigned int rate)
592 spin_unlock_irqrestore(&sonic->
reg_lock, flags);
601 if (!(sonic->
enable & what)) {
606 if (sonic->
enable & what) {
625 if (status == 0xff) {
642 int vol, oleft, oright, mleft, mright;
667 oleft |= mleft & 0x80;
668 oright |= mright & 0x80;
686 return snd_sonicvibes_trigger(sonic, 1, cmd);
693 return snd_sonicvibes_trigger(sonic, 2, cmd);
711 unsigned char fmt = 0;
712 unsigned int size = snd_pcm_lib_buffer_bytes(substream);
713 unsigned int count = snd_pcm_lib_period_bytes(substream);
721 snd_sonicvibes_setfmt(sonic, ~3, fmt);
722 snd_sonicvibes_set_dac_rate(sonic, runtime->
rate);
724 snd_sonicvibes_setdmaa(sonic, runtime->
dma_addr, size);
735 unsigned char fmt = 0;
736 unsigned int size = snd_pcm_lib_buffer_bytes(substream);
737 unsigned int count = snd_pcm_lib_period_bytes(substream);
746 snd_sonicvibes_setfmt(sonic, ~0x30, fmt);
747 snd_sonicvibes_set_adc_rate(sonic, runtime->
rate);
749 snd_sonicvibes_setdmac(sonic, runtime->
dma_addr, size);
763 ptr = sonic->
p_dma_size - snd_sonicvibes_getdmaa(sonic);
764 return bytes_to_frames(substream->
runtime, ptr);
773 ptr = sonic->
c_dma_size - snd_sonicvibes_getdmac(sonic);
774 return bytes_to_frames(substream->
runtime, ptr);
789 .period_bytes_min = 32,
790 .period_bytes_max = (128*1024),
808 .period_bytes_min = 32,
809 .period_bytes_max = (128*1024),
822 runtime->
hw = snd_sonicvibes_playback;
834 runtime->
hw = snd_sonicvibes_capture;
836 &snd_sonicvibes_hw_constraints_adc_clock);
858 static struct snd_pcm_ops snd_sonicvibes_playback_ops = {
859 .open = snd_sonicvibes_playback_open,
860 .close = snd_sonicvibes_playback_close,
862 .hw_params = snd_sonicvibes_hw_params,
863 .hw_free = snd_sonicvibes_hw_free,
864 .prepare = snd_sonicvibes_playback_prepare,
865 .trigger = snd_sonicvibes_playback_trigger,
866 .pointer = snd_sonicvibes_playback_pointer,
869 static struct snd_pcm_ops snd_sonicvibes_capture_ops = {
870 .open = snd_sonicvibes_capture_open,
871 .close = snd_sonicvibes_capture_close,
873 .hw_params = snd_sonicvibes_hw_params,
874 .hw_free = snd_sonicvibes_hw_free,
875 .prepare = snd_sonicvibes_capture_prepare,
876 .trigger = snd_sonicvibes_capture_trigger,
877 .pointer = snd_sonicvibes_capture_pointer,
885 if ((err =
snd_pcm_new(sonic->
card,
"s3_86c617", device, 1, 1, &pcm)) < 0)
910 #define SONICVIBES_MUX(xname, xindex) \
911 { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xindex, \
912 .info = snd_sonicvibes_info_mux, \
913 .get = snd_sonicvibes_get_mux, .put = snd_sonicvibes_put_mux }
917 static char *texts[7] = {
918 "CD",
"PCM",
"Aux1",
"Line",
"Aux0",
"Mic",
"Mix"
944 unsigned short left,
right, oval1, oval2;
947 if (ucontrol->
value.enumerated.item[0] >= 7 ||
948 ucontrol->
value.enumerated.item[1] >= 7)
950 left = (ucontrol->
value.enumerated.item[0] + 1) << 5;
951 right = (ucontrol->
value.enumerated.item[1] + 1) << 5;
957 change = left != oval1 || right != oval2;
964 #define SONICVIBES_SINGLE(xname, xindex, reg, shift, mask, invert) \
965 { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xindex, \
966 .info = snd_sonicvibes_info_single, \
967 .get = snd_sonicvibes_get_single, .put = snd_sonicvibes_put_single, \
968 .private_value = reg | (shift << 8) | (mask << 16) | (invert << 24) }
990 ucontrol->
value.integer.value[0] = (snd_sonicvibes_in1(sonic, reg)>> shift) & mask;
993 ucontrol->
value.integer.value[0] = mask - ucontrol->
value.integer.value[0];
1005 unsigned short val, oval;
1007 val = (ucontrol->
value.integer.value[0] &
mask);
1012 oval = snd_sonicvibes_in1(sonic, reg);
1013 val = (oval & ~(mask << shift)) |
val;
1014 change = val != oval;
1015 snd_sonicvibes_out1(sonic, reg, val);
1020 #define SONICVIBES_DOUBLE(xname, xindex, left_reg, right_reg, shift_left, shift_right, mask, invert) \
1021 { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xindex, \
1022 .info = snd_sonicvibes_info_double, \
1023 .get = snd_sonicvibes_get_double, .put = snd_sonicvibes_put_double, \
1024 .private_value = left_reg | (right_reg << 8) | (shift_left << 16) | (shift_right << 19) | (mask << 24) | (invert << 22) }
1048 ucontrol->
value.integer.value[0] = (snd_sonicvibes_in1(sonic, left_reg) >> shift_left) & mask;
1049 ucontrol->
value.integer.value[1] = (snd_sonicvibes_in1(sonic, right_reg) >>
shift_right) & mask;
1052 ucontrol->
value.integer.value[0] = mask - ucontrol->
value.integer.value[0];
1053 ucontrol->
value.integer.value[1] = mask - ucontrol->
value.integer.value[1];
1068 unsigned short val1, val2, oval1, oval2;
1070 val1 = ucontrol->
value.integer.value[0] &
mask;
1071 val2 = ucontrol->
value.integer.value[1] &
mask;
1076 val1 <<= shift_left;
1079 oval1 = snd_sonicvibes_in1(sonic, left_reg);
1080 oval2 = snd_sonicvibes_in1(sonic, right_reg);
1081 val1 = (oval1 & ~(mask << shift_left)) | val1;
1083 change = val1 != oval1 || val2 != oval2;
1084 snd_sonicvibes_out1(sonic, left_reg, val1);
1085 snd_sonicvibes_out1(sonic, right_reg, val2);
1114 static void snd_sonicvibes_master_free(
struct snd_kcontrol *kcontrol)
1133 for (idx = 0; idx <
ARRAY_SIZE(snd_sonicvibes_controls); idx++) {
1138 case 1: kctl->
private_free = snd_sonicvibes_master_free;
break;
1155 snd_iprintf(buffer,
"SRS 3D : %s\n",
1156 sonic->
srs_space & 0x80 ?
"off" :
"on");
1157 snd_iprintf(buffer,
"SRS Space : %s\n",
1158 tmp == 0x00 ?
"100%" :
1159 tmp == 0x01 ?
"75%" :
1160 tmp == 0x02 ?
"50%" :
1161 tmp == 0x03 ?
"25%" :
"0%");
1163 snd_iprintf(buffer,
"SRS Center : %s\n",
1164 tmp == 0x00 ?
"100%" :
1165 tmp == 0x01 ?
"75%" :
1166 tmp == 0x02 ?
"50%" :
1167 tmp == 0x03 ?
"25%" :
"0%");
1169 snd_iprintf(buffer,
"WaveTable Source : %s\n",
1170 tmp == 0x00 ?
"on-board ROM" :
1171 tmp == 0x01 ?
"PCI bus" :
"on-board ROM + PCI bus");
1173 snd_iprintf(buffer,
"Onboard synth : %s\n", tmp & 0x01 ?
"on" :
"off");
1174 snd_iprintf(buffer,
"Ext. Rx to synth : %s\n", tmp & 0x02 ?
"on" :
"off");
1175 snd_iprintf(buffer,
"MIDI to ext. Tx : %s\n", tmp & 0x04 ?
"on" :
"off");
1182 if (! snd_card_proc_new(sonic->
card,
"sonicvibes", &entry))
1183 snd_info_set_text_ops(entry, sonic, snd_sonicvibes_proc_read);
1190 #ifdef SUPPORT_JOYSTICK
1198 sonic->gameport = gp = gameport_allocate_port();
1200 printk(
KERN_ERR "sonicvibes: cannot allocate memory for gameport\n");
1204 gameport_set_name(gp,
"SonicVibes Gameport");
1206 gameport_set_dev_parent(gp, &sonic->
pci->dev);
1209 gameport_register_port(gp);
1216 static void snd_sonicvibes_free_gameport(
struct sonicvibes *sonic)
1218 if (sonic->gameport) {
1220 sonic->gameport =
NULL;
1224 static inline int snd_sonicvibes_create_gameport(
struct sonicvibes *sonic) {
return -
ENOSYS; }
1225 static inline void snd_sonicvibes_free_gameport(
struct sonicvibes *sonic) { }
1228 static int snd_sonicvibes_free(
struct sonicvibes *sonic)
1230 snd_sonicvibes_free_gameport(sonic);
1231 pci_write_config_dword(sonic->
pci, 0x40, sonic->
dmaa_port);
1232 pci_write_config_dword(sonic->
pci, 0x48, sonic->
dmac_port);
1233 if (sonic->
irq >= 0)
1243 static int snd_sonicvibes_dev_free(
struct snd_device *device)
1246 return snd_sonicvibes_free(sonic);
1256 unsigned int dmaa, dmac;
1259 .dev_free = snd_sonicvibes_dev_free,
1268 pci_set_consistent_dma_mask(pci,
DMA_BIT_MASK(24)) < 0) {
1275 if (sonic ==
NULL) {
1297 KBUILD_MODNAME, sonic)) {
1299 snd_sonicvibes_free(sonic);
1304 pci_read_config_dword(pci, 0x40, &dmaa);
1305 pci_read_config_dword(pci, 0x48, &dmac);
1312 snd_printk(
KERN_INFO "BIOS did not allocate DDMA channel A i/o, allocated at 0x%x\n", dmaa);
1317 snd_printk(
KERN_INFO "BIOS did not allocate DDMA channel C i/o, allocated at 0x%x\n", dmac);
1319 pci_write_config_dword(pci, 0x40, dmaa);
1320 pci_write_config_dword(pci, 0x48, dmac);
1323 snd_sonicvibes_free(sonic);
1324 snd_printk(
KERN_ERR "unable to grab DDMA-A port at 0x%x-0x%x\n", dmaa, dmaa + 0x10 - 1);
1328 snd_sonicvibes_free(sonic);
1329 snd_printk(
KERN_ERR "unable to grab DDMA-C port at 0x%x-0x%x\n", dmac, dmac + 0x10 - 1);
1333 pci_read_config_dword(pci, 0x40, &sonic->
dmaa_port);
1334 pci_read_config_dword(pci, 0x48, &sonic->
dmac_port);
1337 pci_write_config_dword(pci, 0x40, sonic->
dmaa_port | 9);
1338 pci_write_config_dword(pci, 0x48, sonic->
dmac_port | 9);
1383 snd_sonicvibes_debug(sonic);
1388 snd_sonicvibes_free(sonic);
1392 snd_sonicvibes_proc_init(sonic);
1404 static struct snd_kcontrol_new snd_sonicvibes_midi_controls[] __devinitdata = {
1412 static int snd_sonicvibes_midi_input_open(
struct snd_mpu401 * mpu)
1419 static void snd_sonicvibes_midi_input_close(
struct snd_mpu401 * mpu)
1435 mpu->
open_input = snd_sonicvibes_midi_input_open;
1436 mpu->
close_input = snd_sonicvibes_midi_input_close;
1438 for (idx = 0; idx <
ARRAY_SIZE(snd_sonicvibes_midi_controls); idx++)
1464 for (idx = 0; idx < 5; idx++) {
1471 if ((err = snd_sonicvibes_create(card, pci,
1472 reverb[dev] ? 1 : 0,
1487 if ((err = snd_sonicvibes_pcm(sonic, 0,
NULL)) < 0) {
1491 if ((err = snd_sonicvibes_mixer(sonic)) < 0) {
1499 -1, &midi_uart)) < 0) {
1503 snd_sonicvibes_midi(sonic, midi_uart);
1515 snd_sonicvibes_create_gameport(sonic);
1522 pci_set_drvdata(pci, card);
1530 pci_set_drvdata(pci,
NULL);
1533 static struct pci_driver sonicvibes_driver = {
1534 .name = KBUILD_MODNAME,
1535 .id_table = snd_sonic_ids,
1536 .probe = snd_sonic_probe,