aboutsummaryrefslogtreecommitdiffstats
path: root/sound/pci/trident
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@ppc970.osdl.org>2005-04-16 18:20:36 -0400
committerLinus Torvalds <torvalds@ppc970.osdl.org>2005-04-16 18:20:36 -0400
commit1da177e4c3f41524e886b7f1b8a0c1fc7321cac2 (patch)
tree0bba044c4ce775e45a88a51686b5d9f90697ea9d /sound/pci/trident
Linux-2.6.12-rc2v2.6.12-rc2
Initial git repository build. I'm not bothering with the full history, even though we have it. We can create a separate "historical" git archive of that later if we want to, and in the meantime it's about 3.2GB when imported into git - space that would just make the early git days unnecessarily complicated, when we don't have a lot of good infrastructure for it. Let it rip!
Diffstat (limited to 'sound/pci/trident')
-rw-r--r--sound/pci/trident/Makefile19
-rw-r--r--sound/pci/trident/trident.c196
-rw-r--r--sound/pci/trident/trident_main.c3991
-rw-r--r--sound/pci/trident/trident_memory.c476
-rw-r--r--sound/pci/trident/trident_synth.c1031
5 files changed, 5713 insertions, 0 deletions
diff --git a/sound/pci/trident/Makefile b/sound/pci/trident/Makefile
new file mode 100644
index 000000000000..65bc5b703239
--- /dev/null
+++ b/sound/pci/trident/Makefile
@@ -0,0 +1,19 @@
1#
2# Makefile for ALSA
3# Copyright (c) 2001 by Jaroslav Kysela <perex@suse.cz>
4#
5
6snd-trident-objs := trident.o trident_main.o trident_memory.o
7snd-trident-synth-objs := trident_synth.o
8
9#
10# this function returns:
11# "m" - CONFIG_SND_SEQUENCER is m
12# <empty string> - CONFIG_SND_SEQUENCER is undefined
13# otherwise parameter #1 value
14#
15sequencer = $(if $(subst y,,$(CONFIG_SND_SEQUENCER)),$(if $(1),m),$(if $(CONFIG_SND_SEQUENCER),$(1)))
16
17# Toplevel Module Dependency
18obj-$(CONFIG_SND_TRIDENT) += snd-trident.o
19obj-$(call sequencer,$(CONFIG_SND_TRIDENT)) += snd-trident-synth.o
diff --git a/sound/pci/trident/trident.c b/sound/pci/trident/trident.c
new file mode 100644
index 000000000000..ad58e08d66e2
--- /dev/null
+++ b/sound/pci/trident/trident.c
@@ -0,0 +1,196 @@
1/*
2 * Driver for Trident 4DWave DX/NX & SiS SI7018 Audio PCI soundcard
3 *
4 * Driver was originated by Trident <audio@tridentmicro.com>
5 * Fri Feb 19 15:55:28 MST 1999
6 *
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21 *
22 */
23
24#include <sound/driver.h>
25#include <linux/init.h>
26#include <linux/pci.h>
27#include <linux/time.h>
28#include <linux/moduleparam.h>
29#include <sound/core.h>
30#include <sound/trident.h>
31#include <sound/initval.h>
32
33MODULE_AUTHOR("Jaroslav Kysela <perex@suse.cz>, <audio@tridentmicro.com>");
34MODULE_DESCRIPTION("Trident 4D-WaveDX/NX & SiS SI7018");
35MODULE_LICENSE("GPL");
36MODULE_SUPPORTED_DEVICE("{{Trident,4DWave DX},"
37 "{Trident,4DWave NX},"
38 "{SiS,SI7018 PCI Audio},"
39 "{Best Union,Miss Melody 4DWave PCI},"
40 "{HIS,4DWave PCI},"
41 "{Warpspeed,ONSpeed 4DWave PCI},"
42 "{Aztech Systems,PCI 64-Q3D},"
43 "{Addonics,SV 750},"
44 "{CHIC,True Sound 4Dwave},"
45 "{Shark,Predator4D-PCI},"
46 "{Jaton,SonicWave 4D},"
47 "{Hoontech,SoundTrack Digital 4DWave NX}}");
48
49static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-MAX */
50static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* ID for this card */
51static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP; /* Enable this card */
52static int pcm_channels[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 32};
53static int wavetable_size[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 8192};
54
55module_param_array(index, int, NULL, 0444);
56MODULE_PARM_DESC(index, "Index value for Trident 4DWave PCI soundcard.");
57module_param_array(id, charp, NULL, 0444);
58MODULE_PARM_DESC(id, "ID string for Trident 4DWave PCI soundcard.");
59module_param_array(enable, bool, NULL, 0444);
60MODULE_PARM_DESC(enable, "Enable Trident 4DWave PCI soundcard.");
61module_param_array(pcm_channels, int, NULL, 0444);
62MODULE_PARM_DESC(pcm_channels, "Number of hardware channels assigned for PCM.");
63module_param_array(wavetable_size, int, NULL, 0444);
64MODULE_PARM_DESC(wavetable_size, "Maximum memory size in kB for wavetable synth.");
65
66static struct pci_device_id snd_trident_ids[] = {
67 { 0x1023, 0x2000, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, /* Trident 4DWave DX PCI Audio */
68 { 0x1023, 0x2001, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, /* Trident 4DWave NX PCI Audio */
69 { 0x1039, 0x7018, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, /* SiS SI7018 PCI Audio */
70 { 0, }
71};
72
73MODULE_DEVICE_TABLE(pci, snd_trident_ids);
74
75static int __devinit snd_trident_probe(struct pci_dev *pci,
76 const struct pci_device_id *pci_id)
77{
78 static int dev;
79 snd_card_t *card;
80 trident_t *trident;
81 const char *str;
82 int err, pcm_dev = 0;
83
84 if (dev >= SNDRV_CARDS)
85 return -ENODEV;
86 if (!enable[dev]) {
87 dev++;
88 return -ENOENT;
89 }
90
91 card = snd_card_new(index[dev], id[dev], THIS_MODULE, 0);
92 if (card == NULL)
93 return -ENOMEM;
94
95 if ((err = snd_trident_create(card, pci,
96 pcm_channels[dev],
97 ((pci->vendor << 16) | pci->device) == TRIDENT_DEVICE_ID_SI7018 ? 1 : 2,
98 wavetable_size[dev],
99 &trident)) < 0) {
100 snd_card_free(card);
101 return err;
102 }
103
104 switch (trident->device) {
105 case TRIDENT_DEVICE_ID_DX:
106 str = "TRID4DWAVEDX";
107 break;
108 case TRIDENT_DEVICE_ID_NX:
109 str = "TRID4DWAVENX";
110 break;
111 case TRIDENT_DEVICE_ID_SI7018:
112 str = "SI7018";
113 break;
114 default:
115 str = "Unknown";
116 }
117 strcpy(card->driver, str);
118 if (trident->device == TRIDENT_DEVICE_ID_SI7018) {
119 strcpy(card->shortname, "SiS ");
120 } else {
121 strcpy(card->shortname, "Trident ");
122 }
123 strcat(card->shortname, card->driver);
124 sprintf(card->longname, "%s PCI Audio at 0x%lx, irq %d",
125 card->shortname, trident->port, trident->irq);
126
127 if ((err = snd_trident_pcm(trident, pcm_dev++, NULL)) < 0) {
128 snd_card_free(card);
129 return err;
130 }
131 switch (trident->device) {
132 case TRIDENT_DEVICE_ID_DX:
133 case TRIDENT_DEVICE_ID_NX:
134 if ((err = snd_trident_foldback_pcm(trident, pcm_dev++, NULL)) < 0) {
135 snd_card_free(card);
136 return err;
137 }
138 break;
139 }
140 if (trident->device == TRIDENT_DEVICE_ID_NX || trident->device == TRIDENT_DEVICE_ID_SI7018) {
141 if ((err = snd_trident_spdif_pcm(trident, pcm_dev++, NULL)) < 0) {
142 snd_card_free(card);
143 return err;
144 }
145 }
146 if ((err = snd_mpu401_uart_new(card, 0, MPU401_HW_TRID4DWAVE,
147 trident->midi_port, 1,
148 trident->irq, 0, &trident->rmidi)) < 0) {
149 snd_card_free(card);
150 return err;
151 }
152
153#if defined(CONFIG_SND_SEQUENCER) || (defined(MODULE) && defined(CONFIG_SND_SEQUENCER_MODULE))
154 if ((err = snd_trident_attach_synthesizer(trident)) < 0) {
155 snd_card_free(card);
156 return err;
157 }
158#endif
159
160 snd_trident_create_gameport(trident);
161
162 if ((err = snd_card_register(card)) < 0) {
163 snd_card_free(card);
164 return err;
165 }
166 pci_set_drvdata(pci, card);
167 dev++;
168 return 0;
169}
170
171static void __devexit snd_trident_remove(struct pci_dev *pci)
172{
173 snd_card_free(pci_get_drvdata(pci));
174 pci_set_drvdata(pci, NULL);
175}
176
177static struct pci_driver driver = {
178 .name = "Trident4DWaveAudio",
179 .id_table = snd_trident_ids,
180 .probe = snd_trident_probe,
181 .remove = __devexit_p(snd_trident_remove),
182 SND_PCI_PM_CALLBACKS
183};
184
185static int __init alsa_card_trident_init(void)
186{
187 return pci_module_init(&driver);
188}
189
190static void __exit alsa_card_trident_exit(void)
191{
192 pci_unregister_driver(&driver);
193}
194
195module_init(alsa_card_trident_init)
196module_exit(alsa_card_trident_exit)
diff --git a/sound/pci/trident/trident_main.c b/sound/pci/trident/trident_main.c
new file mode 100644
index 000000000000..ccd5ca2ba16f
--- /dev/null
+++ b/sound/pci/trident/trident_main.c
@@ -0,0 +1,3991 @@
1/*
2 * Maintained by Jaroslav Kysela <perex@suse.cz>
3 * Originated by audio@tridentmicro.com
4 * Fri Feb 19 15:55:28 MST 1999
5 * Routines for control of Trident 4DWave (DX and NX) chip
6 *
7 * BUGS:
8 *
9 * TODO:
10 * ---
11 *
12 * This program is free software; you can redistribute it and/or modify
13 * it under the terms of the GNU General Public License as published by
14 * the Free Software Foundation; either version 2 of the License, or
15 * (at your option) any later version.
16 *
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software
24 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
25 *
26 *
27 * SiS7018 S/PDIF support by Thomas Winischhofer <thomas@winischhofer.net>
28 */
29
30#include <sound/driver.h>
31#include <linux/delay.h>
32#include <linux/init.h>
33#include <linux/interrupt.h>
34#include <linux/pci.h>
35#include <linux/slab.h>
36#include <linux/vmalloc.h>
37#include <linux/gameport.h>
38
39#include <sound/core.h>
40#include <sound/info.h>
41#include <sound/control.h>
42#include <sound/trident.h>
43#include <sound/asoundef.h>
44
45#include <asm/io.h>
46
47static int snd_trident_pcm_mixer_build(trident_t *trident, snd_trident_voice_t * voice, snd_pcm_substream_t *substream);
48static int snd_trident_pcm_mixer_free(trident_t *trident, snd_trident_voice_t * voice, snd_pcm_substream_t *substream);
49static irqreturn_t snd_trident_interrupt(int irq, void *dev_id, struct pt_regs *regs);
50#ifdef CONFIG_PM
51static int snd_trident_suspend(snd_card_t *card, pm_message_t state);
52static int snd_trident_resume(snd_card_t *card);
53#endif
54static int snd_trident_sis_reset(trident_t *trident);
55
56static void snd_trident_clear_voices(trident_t * trident, unsigned short v_min, unsigned short v_max);
57static int snd_trident_free(trident_t *trident);
58
59/*
60 * common I/O routines
61 */
62
63
64#if 0
65static void snd_trident_print_voice_regs(trident_t *trident, int voice)
66{
67 unsigned int val, tmp;
68
69 printk("Trident voice %i:\n", voice);
70 outb(voice, TRID_REG(trident, T4D_LFO_GC_CIR));
71 val = inl(TRID_REG(trident, CH_LBA));
72 printk("LBA: 0x%x\n", val);
73 val = inl(TRID_REG(trident, CH_GVSEL_PAN_VOL_CTRL_EC));
74 printk("GVSel: %i\n", val >> 31);
75 printk("Pan: 0x%x\n", (val >> 24) & 0x7f);
76 printk("Vol: 0x%x\n", (val >> 16) & 0xff);
77 printk("CTRL: 0x%x\n", (val >> 12) & 0x0f);
78 printk("EC: 0x%x\n", val & 0x0fff);
79 if (trident->device != TRIDENT_DEVICE_ID_NX) {
80 val = inl(TRID_REG(trident, CH_DX_CSO_ALPHA_FMS));
81 printk("CSO: 0x%x\n", val >> 16);
82 printk("Alpha: 0x%x\n", (val >> 4) & 0x0fff);
83 printk("FMS: 0x%x\n", val & 0x0f);
84 val = inl(TRID_REG(trident, CH_DX_ESO_DELTA));
85 printk("ESO: 0x%x\n", val >> 16);
86 printk("Delta: 0x%x\n", val & 0xffff);
87 val = inl(TRID_REG(trident, CH_DX_FMC_RVOL_CVOL));
88 } else { // TRIDENT_DEVICE_ID_NX
89 val = inl(TRID_REG(trident, CH_NX_DELTA_CSO));
90 tmp = (val >> 24) & 0xff;
91 printk("CSO: 0x%x\n", val & 0x00ffffff);
92 val = inl(TRID_REG(trident, CH_NX_DELTA_ESO));
93 tmp |= (val >> 16) & 0xff00;
94 printk("Delta: 0x%x\n", tmp);
95 printk("ESO: 0x%x\n", val & 0x00ffffff);
96 val = inl(TRID_REG(trident, CH_NX_ALPHA_FMS_FMC_RVOL_CVOL));
97 printk("Alpha: 0x%x\n", val >> 20);
98 printk("FMS: 0x%x\n", (val >> 16) & 0x0f);
99 }
100 printk("FMC: 0x%x\n", (val >> 14) & 3);
101 printk("RVol: 0x%x\n", (val >> 7) & 0x7f);
102 printk("CVol: 0x%x\n", val & 0x7f);
103}
104#endif
105
106/*---------------------------------------------------------------------------
107 unsigned short snd_trident_codec_read(ac97_t *ac97, unsigned short reg)
108
109 Description: This routine will do all of the reading from the external
110 CODEC (AC97).
111
112 Parameters: ac97 - ac97 codec structure
113 reg - CODEC register index, from AC97 Hal.
114
115 returns: 16 bit value read from the AC97.
116
117 ---------------------------------------------------------------------------*/
118static unsigned short snd_trident_codec_read(ac97_t *ac97, unsigned short reg)
119{
120 unsigned int data = 0, treg;
121 unsigned short count = 0xffff;
122 unsigned long flags;
123 trident_t *trident = ac97->private_data;
124
125 spin_lock_irqsave(&trident->reg_lock, flags);
126 if (trident->device == TRIDENT_DEVICE_ID_DX) {
127 data = (DX_AC97_BUSY_READ | (reg & 0x000000ff));
128 outl(data, TRID_REG(trident, DX_ACR1_AC97_R));
129 do {
130 data = inl(TRID_REG(trident, DX_ACR1_AC97_R));
131 if ((data & DX_AC97_BUSY_READ) == 0)
132 break;
133 } while (--count);
134 } else if (trident->device == TRIDENT_DEVICE_ID_NX) {
135 data = (NX_AC97_BUSY_READ | (reg & 0x000000ff));
136 treg = ac97->num == 0 ? NX_ACR2_AC97_R_PRIMARY : NX_ACR3_AC97_R_SECONDARY;
137 outl(data, TRID_REG(trident, treg));
138 do {
139 data = inl(TRID_REG(trident, treg));
140 if ((data & 0x00000C00) == 0)
141 break;
142 } while (--count);
143 } else if (trident->device == TRIDENT_DEVICE_ID_SI7018) {
144 data = SI_AC97_BUSY_READ | SI_AC97_AUDIO_BUSY | (reg & 0x000000ff);
145 if (ac97->num == 1)
146 data |= SI_AC97_SECONDARY;
147 outl(data, TRID_REG(trident, SI_AC97_READ));
148 do {
149 data = inl(TRID_REG(trident, SI_AC97_READ));
150 if ((data & (SI_AC97_BUSY_READ)) == 0)
151 break;
152 } while (--count);
153 }
154
155 if (count == 0 && !trident->ac97_detect) {
156 snd_printk("ac97 codec read TIMEOUT [0x%x/0x%x]!!!\n", reg, data);
157 data = 0;
158 }
159
160 spin_unlock_irqrestore(&trident->reg_lock, flags);
161 return ((unsigned short) (data >> 16));
162}
163
164/*---------------------------------------------------------------------------
165 void snd_trident_codec_write(ac97_t *ac97, unsigned short reg, unsigned short wdata)
166
167 Description: This routine will do all of the writing to the external
168 CODEC (AC97).
169
170 Parameters: ac97 - ac97 codec structure
171 reg - CODEC register index, from AC97 Hal.
172 data - Lower 16 bits are the data to write to CODEC.
173
174 returns: TRUE if everything went ok, else FALSE.
175
176 ---------------------------------------------------------------------------*/
177static void snd_trident_codec_write(ac97_t *ac97, unsigned short reg, unsigned short wdata)
178{
179 unsigned int address, data;
180 unsigned short count = 0xffff;
181 unsigned long flags;
182 trident_t *trident = ac97->private_data;
183
184 data = ((unsigned long) wdata) << 16;
185
186 spin_lock_irqsave(&trident->reg_lock, flags);
187 if (trident->device == TRIDENT_DEVICE_ID_DX) {
188 address = DX_ACR0_AC97_W;
189
190 /* read AC-97 write register status */
191 do {
192 if ((inw(TRID_REG(trident, address)) & DX_AC97_BUSY_WRITE) == 0)
193 break;
194 } while (--count);
195
196 data |= (DX_AC97_BUSY_WRITE | (reg & 0x000000ff));
197 } else if (trident->device == TRIDENT_DEVICE_ID_NX) {
198 address = NX_ACR1_AC97_W;
199
200 /* read AC-97 write register status */
201 do {
202 if ((inw(TRID_REG(trident, address)) & NX_AC97_BUSY_WRITE) == 0)
203 break;
204 } while (--count);
205
206 data |= (NX_AC97_BUSY_WRITE | (ac97->num << 8) | (reg & 0x000000ff));
207 } else if (trident->device == TRIDENT_DEVICE_ID_SI7018) {
208 address = SI_AC97_WRITE;
209
210 /* read AC-97 write register status */
211 do {
212 if ((inw(TRID_REG(trident, address)) & (SI_AC97_BUSY_WRITE)) == 0)
213 break;
214 } while (--count);
215
216 data |= SI_AC97_BUSY_WRITE | SI_AC97_AUDIO_BUSY | (reg & 0x000000ff);
217 if (ac97->num == 1)
218 data |= SI_AC97_SECONDARY;
219 } else {
220 address = 0; /* keep GCC happy */
221 count = 0; /* return */
222 }
223
224 if (count == 0) {
225 spin_unlock_irqrestore(&trident->reg_lock, flags);
226 return;
227 }
228 outl(data, TRID_REG(trident, address));
229 spin_unlock_irqrestore(&trident->reg_lock, flags);
230}
231
232/*---------------------------------------------------------------------------
233 void snd_trident_enable_eso(trident_t *trident)
234
235 Description: This routine will enable end of loop interrupts.
236 End of loop interrupts will occur when a running
237 channel reaches ESO.
238 Also enables middle of loop interrupts.
239
240 Parameters: trident - pointer to target device class for 4DWave.
241
242 ---------------------------------------------------------------------------*/
243
244static void snd_trident_enable_eso(trident_t * trident)
245{
246 unsigned int val;
247
248 val = inl(TRID_REG(trident, T4D_LFO_GC_CIR));
249 val |= ENDLP_IE;
250 val |= MIDLP_IE;
251 if (trident->device == TRIDENT_DEVICE_ID_SI7018)
252 val |= BANK_B_EN;
253 outl(val, TRID_REG(trident, T4D_LFO_GC_CIR));
254}
255
256/*---------------------------------------------------------------------------
257 void snd_trident_disable_eso(trident_t *trident)
258
259 Description: This routine will disable end of loop interrupts.
260 End of loop interrupts will occur when a running
261 channel reaches ESO.
262 Also disables middle of loop interrupts.
263
264 Parameters:
265 trident - pointer to target device class for 4DWave.
266
267 returns: TRUE if everything went ok, else FALSE.
268
269 ---------------------------------------------------------------------------*/
270
271static void snd_trident_disable_eso(trident_t * trident)
272{
273 unsigned int tmp;
274
275 tmp = inl(TRID_REG(trident, T4D_LFO_GC_CIR));
276 tmp &= ~ENDLP_IE;
277 tmp &= ~MIDLP_IE;
278 outl(tmp, TRID_REG(trident, T4D_LFO_GC_CIR));
279}
280
281/*---------------------------------------------------------------------------
282 void snd_trident_start_voice(trident_t * trident, unsigned int voice)
283
284 Description: Start a voice, any channel 0 thru 63.
285 This routine automatically handles the fact that there are
286 more than 32 channels available.
287
288 Parameters : voice - Voice number 0 thru n.
289 trident - pointer to target device class for 4DWave.
290
291 Return Value: None.
292
293 ---------------------------------------------------------------------------*/
294
295void snd_trident_start_voice(trident_t * trident, unsigned int voice)
296{
297 unsigned int mask = 1 << (voice & 0x1f);
298 unsigned int reg = (voice & 0x20) ? T4D_START_B : T4D_START_A;
299
300 outl(mask, TRID_REG(trident, reg));
301}
302
303/*---------------------------------------------------------------------------
304 void snd_trident_stop_voice(trident_t * trident, unsigned int voice)
305
306 Description: Stop a voice, any channel 0 thru 63.
307 This routine automatically handles the fact that there are
308 more than 32 channels available.
309
310 Parameters : voice - Voice number 0 thru n.
311 trident - pointer to target device class for 4DWave.
312
313 Return Value: None.
314
315 ---------------------------------------------------------------------------*/
316
317void snd_trident_stop_voice(trident_t * trident, unsigned int voice)
318{
319 unsigned int mask = 1 << (voice & 0x1f);
320 unsigned int reg = (voice & 0x20) ? T4D_STOP_B : T4D_STOP_A;
321
322 outl(mask, TRID_REG(trident, reg));
323}
324
325/*---------------------------------------------------------------------------
326 int snd_trident_allocate_pcm_channel(trident_t *trident)
327
328 Description: Allocate hardware channel in Bank B (32-63).
329
330 Parameters : trident - pointer to target device class for 4DWave.
331
332 Return Value: hardware channel - 32-63 or -1 when no channel is available
333
334 ---------------------------------------------------------------------------*/
335
336static int snd_trident_allocate_pcm_channel(trident_t * trident)
337{
338 int idx;
339
340 if (trident->ChanPCMcnt >= trident->ChanPCM)
341 return -1;
342 for (idx = 31; idx >= 0; idx--) {
343 if (!(trident->ChanMap[T4D_BANK_B] & (1 << idx))) {
344 trident->ChanMap[T4D_BANK_B] |= 1 << idx;
345 trident->ChanPCMcnt++;
346 return idx + 32;
347 }
348 }
349 return -1;
350}
351
352/*---------------------------------------------------------------------------
353 void snd_trident_free_pcm_channel(int channel)
354
355 Description: Free hardware channel in Bank B (32-63)
356
357 Parameters : trident - pointer to target device class for 4DWave.
358 channel - hardware channel number 0-63
359
360 Return Value: none
361
362 ---------------------------------------------------------------------------*/
363
364static void snd_trident_free_pcm_channel(trident_t *trident, int channel)
365{
366 if (channel < 32 || channel > 63)
367 return;
368 channel &= 0x1f;
369 if (trident->ChanMap[T4D_BANK_B] & (1 << channel)) {
370 trident->ChanMap[T4D_BANK_B] &= ~(1 << channel);
371 trident->ChanPCMcnt--;
372 }
373}
374
375/*---------------------------------------------------------------------------
376 unsigned int snd_trident_allocate_synth_channel(void)
377
378 Description: Allocate hardware channel in Bank A (0-31).
379
380 Parameters : trident - pointer to target device class for 4DWave.
381
382 Return Value: hardware channel - 0-31 or -1 when no channel is available
383
384 ---------------------------------------------------------------------------*/
385
386static int snd_trident_allocate_synth_channel(trident_t * trident)
387{
388 int idx;
389
390 for (idx = 31; idx >= 0; idx--) {
391 if (!(trident->ChanMap[T4D_BANK_A] & (1 << idx))) {
392 trident->ChanMap[T4D_BANK_A] |= 1 << idx;
393 trident->synth.ChanSynthCount++;
394 return idx;
395 }
396 }
397 return -1;
398}
399
400/*---------------------------------------------------------------------------
401 void snd_trident_free_synth_channel( int channel )
402
403 Description: Free hardware channel in Bank B (0-31).
404
405 Parameters : trident - pointer to target device class for 4DWave.
406 channel - hardware channel number 0-63
407
408 Return Value: none
409
410 ---------------------------------------------------------------------------*/
411
412static void snd_trident_free_synth_channel(trident_t *trident, int channel)
413{
414 if (channel < 0 || channel > 31)
415 return;
416 channel &= 0x1f;
417 if (trident->ChanMap[T4D_BANK_A] & (1 << channel)) {
418 trident->ChanMap[T4D_BANK_A] &= ~(1 << channel);
419 trident->synth.ChanSynthCount--;
420 }
421}
422
423/*---------------------------------------------------------------------------
424 snd_trident_write_voice_regs
425
426 Description: This routine will complete and write the 5 hardware channel
427 registers to hardware.
428
429 Paramters: trident - pointer to target device class for 4DWave.
430 voice - synthesizer voice structure
431 Each register field.
432
433 ---------------------------------------------------------------------------*/
434
435void snd_trident_write_voice_regs(trident_t * trident,
436 snd_trident_voice_t * voice)
437{
438 unsigned int FmcRvolCvol;
439 unsigned int regs[5];
440
441 regs[1] = voice->LBA;
442 regs[4] = (voice->GVSel << 31) |
443 ((voice->Pan & 0x0000007f) << 24) |
444 ((voice->CTRL & 0x0000000f) << 12);
445 FmcRvolCvol = ((voice->FMC & 3) << 14) |
446 ((voice->RVol & 0x7f) << 7) |
447 (voice->CVol & 0x7f);
448
449 switch (trident->device) {
450 case TRIDENT_DEVICE_ID_SI7018:
451 regs[4] |= voice->number > 31 ?
452 (voice->Vol & 0x000003ff) :
453 ((voice->Vol & 0x00003fc) << (16-2)) |
454 (voice->EC & 0x00000fff);
455 regs[0] = (voice->CSO << 16) | ((voice->Alpha & 0x00000fff) << 4) | (voice->FMS & 0x0000000f);
456 regs[2] = (voice->ESO << 16) | (voice->Delta & 0x0ffff);
457 regs[3] = (voice->Attribute << 16) | FmcRvolCvol;
458 break;
459 case TRIDENT_DEVICE_ID_DX:
460 regs[4] |= ((voice->Vol & 0x000003fc) << (16-2)) |
461 (voice->EC & 0x00000fff);
462 regs[0] = (voice->CSO << 16) | ((voice->Alpha & 0x00000fff) << 4) | (voice->FMS & 0x0000000f);
463 regs[2] = (voice->ESO << 16) | (voice->Delta & 0x0ffff);
464 regs[3] = FmcRvolCvol;
465 break;
466 case TRIDENT_DEVICE_ID_NX:
467 regs[4] |= ((voice->Vol & 0x000003fc) << (16-2)) |
468 (voice->EC & 0x00000fff);
469 regs[0] = (voice->Delta << 24) | (voice->CSO & 0x00ffffff);
470 regs[2] = ((voice->Delta << 16) & 0xff000000) | (voice->ESO & 0x00ffffff);
471 regs[3] = (voice->Alpha << 20) | ((voice->FMS & 0x0000000f) << 16) | FmcRvolCvol;
472 break;
473 default:
474 snd_BUG();
475 }
476
477 outb(voice->number, TRID_REG(trident, T4D_LFO_GC_CIR));
478 outl(regs[0], TRID_REG(trident, CH_START + 0));
479 outl(regs[1], TRID_REG(trident, CH_START + 4));
480 outl(regs[2], TRID_REG(trident, CH_START + 8));
481 outl(regs[3], TRID_REG(trident, CH_START + 12));
482 outl(regs[4], TRID_REG(trident, CH_START + 16));
483
484#if 0
485 printk("written %i channel:\n", voice->number);
486 printk(" regs[0] = 0x%x/0x%x\n", regs[0], inl(TRID_REG(trident, CH_START + 0)));
487 printk(" regs[1] = 0x%x/0x%x\n", regs[1], inl(TRID_REG(trident, CH_START + 4)));
488 printk(" regs[2] = 0x%x/0x%x\n", regs[2], inl(TRID_REG(trident, CH_START + 8)));
489 printk(" regs[3] = 0x%x/0x%x\n", regs[3], inl(TRID_REG(trident, CH_START + 12)));
490 printk(" regs[4] = 0x%x/0x%x\n", regs[4], inl(TRID_REG(trident, CH_START + 16)));
491#endif
492}
493
494/*---------------------------------------------------------------------------
495 snd_trident_write_cso_reg
496
497 Description: This routine will write the new CSO offset
498 register to hardware.
499
500 Paramters: trident - pointer to target device class for 4DWave.
501 voice - synthesizer voice structure
502 CSO - new CSO value
503
504 ---------------------------------------------------------------------------*/
505
506static void snd_trident_write_cso_reg(trident_t * trident, snd_trident_voice_t * voice, unsigned int CSO)
507{
508 voice->CSO = CSO;
509 outb(voice->number, TRID_REG(trident, T4D_LFO_GC_CIR));
510 if (trident->device != TRIDENT_DEVICE_ID_NX) {
511 outw(voice->CSO, TRID_REG(trident, CH_DX_CSO_ALPHA_FMS) + 2);
512 } else {
513 outl((voice->Delta << 24) | (voice->CSO & 0x00ffffff), TRID_REG(trident, CH_NX_DELTA_CSO));
514 }
515}
516
517/*---------------------------------------------------------------------------
518 snd_trident_write_eso_reg
519
520 Description: This routine will write the new ESO offset
521 register to hardware.
522
523 Paramters: trident - pointer to target device class for 4DWave.
524 voice - synthesizer voice structure
525 ESO - new ESO value
526
527 ---------------------------------------------------------------------------*/
528
529static void snd_trident_write_eso_reg(trident_t * trident, snd_trident_voice_t * voice, unsigned int ESO)
530{
531 voice->ESO = ESO;
532 outb(voice->number, TRID_REG(trident, T4D_LFO_GC_CIR));
533 if (trident->device != TRIDENT_DEVICE_ID_NX) {
534 outw(voice->ESO, TRID_REG(trident, CH_DX_ESO_DELTA) + 2);
535 } else {
536 outl(((voice->Delta << 16) & 0xff000000) | (voice->ESO & 0x00ffffff), TRID_REG(trident, CH_NX_DELTA_ESO));
537 }
538}
539
540/*---------------------------------------------------------------------------
541 snd_trident_write_vol_reg
542
543 Description: This routine will write the new voice volume
544 register to hardware.
545
546 Paramters: trident - pointer to target device class for 4DWave.
547 voice - synthesizer voice structure
548 Vol - new voice volume
549
550 ---------------------------------------------------------------------------*/
551
552static void snd_trident_write_vol_reg(trident_t * trident, snd_trident_voice_t * voice, unsigned int Vol)
553{
554 voice->Vol = Vol;
555 outb(voice->number, TRID_REG(trident, T4D_LFO_GC_CIR));
556 switch (trident->device) {
557 case TRIDENT_DEVICE_ID_DX:
558 case TRIDENT_DEVICE_ID_NX:
559 outb(voice->Vol >> 2, TRID_REG(trident, CH_GVSEL_PAN_VOL_CTRL_EC + 2));
560 break;
561 case TRIDENT_DEVICE_ID_SI7018:
562 // printk("voice->Vol = 0x%x\n", voice->Vol);
563 outw((voice->CTRL << 12) | voice->Vol, TRID_REG(trident, CH_GVSEL_PAN_VOL_CTRL_EC));
564 break;
565 }
566}
567
568/*---------------------------------------------------------------------------
569 snd_trident_write_pan_reg
570
571 Description: This routine will write the new voice pan
572 register to hardware.
573
574 Paramters: trident - pointer to target device class for 4DWave.
575 voice - synthesizer voice structure
576 Pan - new pan value
577
578 ---------------------------------------------------------------------------*/
579
580static void snd_trident_write_pan_reg(trident_t * trident, snd_trident_voice_t * voice, unsigned int Pan)
581{
582 voice->Pan = Pan;
583 outb(voice->number, TRID_REG(trident, T4D_LFO_GC_CIR));
584 outb(((voice->GVSel & 0x01) << 7) | (voice->Pan & 0x7f), TRID_REG(trident, CH_GVSEL_PAN_VOL_CTRL_EC + 3));
585}
586
587/*---------------------------------------------------------------------------
588 snd_trident_write_rvol_reg
589
590 Description: This routine will write the new reverb volume
591 register to hardware.
592
593 Paramters: trident - pointer to target device class for 4DWave.
594 voice - synthesizer voice structure
595 RVol - new reverb volume
596
597 ---------------------------------------------------------------------------*/
598
599static void snd_trident_write_rvol_reg(trident_t * trident, snd_trident_voice_t * voice, unsigned int RVol)
600{
601 voice->RVol = RVol;
602 outb(voice->number, TRID_REG(trident, T4D_LFO_GC_CIR));
603 outw(((voice->FMC & 0x0003) << 14) | ((voice->RVol & 0x007f) << 7) | (voice->CVol & 0x007f),
604 TRID_REG(trident, trident->device == TRIDENT_DEVICE_ID_NX ? CH_NX_ALPHA_FMS_FMC_RVOL_CVOL : CH_DX_FMC_RVOL_CVOL));
605}
606
607/*---------------------------------------------------------------------------
608 snd_trident_write_cvol_reg
609
610 Description: This routine will write the new chorus volume
611 register to hardware.
612
613 Paramters: trident - pointer to target device class for 4DWave.
614 voice - synthesizer voice structure
615 CVol - new chorus volume
616
617 ---------------------------------------------------------------------------*/
618
619static void snd_trident_write_cvol_reg(trident_t * trident, snd_trident_voice_t * voice, unsigned int CVol)
620{
621 voice->CVol = CVol;
622 outb(voice->number, TRID_REG(trident, T4D_LFO_GC_CIR));
623 outw(((voice->FMC & 0x0003) << 14) | ((voice->RVol & 0x007f) << 7) | (voice->CVol & 0x007f),
624 TRID_REG(trident, trident->device == TRIDENT_DEVICE_ID_NX ? CH_NX_ALPHA_FMS_FMC_RVOL_CVOL : CH_DX_FMC_RVOL_CVOL));
625}
626
627/*---------------------------------------------------------------------------
628 snd_trident_convert_rate
629
630 Description: This routine converts rate in HZ to hardware delta value.
631
632 Paramters: trident - pointer to target device class for 4DWave.
633 rate - Real or Virtual channel number.
634
635 Returns: Delta value.
636
637 ---------------------------------------------------------------------------*/
638static unsigned int snd_trident_convert_rate(unsigned int rate)
639{
640 unsigned int delta;
641
642 // We special case 44100 and 8000 since rounding with the equation
643 // does not give us an accurate enough value. For 11025 and 22050
644 // the equation gives us the best answer. All other frequencies will
645 // also use the equation. JDW
646 if (rate == 44100)
647 delta = 0xeb3;
648 else if (rate == 8000)
649 delta = 0x2ab;
650 else if (rate == 48000)
651 delta = 0x1000;
652 else
653 delta = (((rate << 12) + 24000) / 48000) & 0x0000ffff;
654 return delta;
655}
656
657/*---------------------------------------------------------------------------
658 snd_trident_convert_adc_rate
659
660 Description: This routine converts rate in HZ to hardware delta value.
661
662 Paramters: trident - pointer to target device class for 4DWave.
663 rate - Real or Virtual channel number.
664
665 Returns: Delta value.
666
667 ---------------------------------------------------------------------------*/
668static unsigned int snd_trident_convert_adc_rate(unsigned int rate)
669{
670 unsigned int delta;
671
672 // We special case 44100 and 8000 since rounding with the equation
673 // does not give us an accurate enough value. For 11025 and 22050
674 // the equation gives us the best answer. All other frequencies will
675 // also use the equation. JDW
676 if (rate == 44100)
677 delta = 0x116a;
678 else if (rate == 8000)
679 delta = 0x6000;
680 else if (rate == 48000)
681 delta = 0x1000;
682 else
683 delta = ((48000 << 12) / rate) & 0x0000ffff;
684 return delta;
685}
686
687/*---------------------------------------------------------------------------
688 snd_trident_spurious_threshold
689
690 Description: This routine converts rate in HZ to spurious threshold.
691
692 Paramters: trident - pointer to target device class for 4DWave.
693 rate - Real or Virtual channel number.
694
695 Returns: Delta value.
696
697 ---------------------------------------------------------------------------*/
698static unsigned int snd_trident_spurious_threshold(unsigned int rate, unsigned int period_size)
699{
700 unsigned int res = (rate * period_size) / 48000;
701 if (res < 64)
702 res = res / 2;
703 else
704 res -= 32;
705 return res;
706}
707
708/*---------------------------------------------------------------------------
709 snd_trident_control_mode
710
711 Description: This routine returns a control mode for a PCM channel.
712
713 Paramters: trident - pointer to target device class for 4DWave.
714 substream - PCM substream
715
716 Returns: Control value.
717
718 ---------------------------------------------------------------------------*/
719static unsigned int snd_trident_control_mode(snd_pcm_substream_t *substream)
720{
721 unsigned int CTRL;
722 snd_pcm_runtime_t *runtime = substream->runtime;
723
724 /* set ctrl mode
725 CTRL default: 8-bit (unsigned) mono, loop mode enabled
726 */
727 CTRL = 0x00000001;
728 if (snd_pcm_format_width(runtime->format) == 16)
729 CTRL |= 0x00000008; // 16-bit data
730 if (snd_pcm_format_signed(runtime->format))
731 CTRL |= 0x00000002; // signed data
732 if (runtime->channels > 1)
733 CTRL |= 0x00000004; // stereo data
734 return CTRL;
735}
736
737/*
738 * PCM part
739 */
740
741/*---------------------------------------------------------------------------
742 snd_trident_ioctl
743
744 Description: Device I/O control handler for playback/capture parameters.
745
746 Paramters: substream - PCM substream class
747 cmd - what ioctl message to process
748 arg - additional message infoarg
749
750 Returns: Error status
751
752 ---------------------------------------------------------------------------*/
753
754static int snd_trident_ioctl(snd_pcm_substream_t * substream,
755 unsigned int cmd,
756 void *arg)
757{
758 /* FIXME: it seems that with small periods the behaviour of
759 trident hardware is unpredictable and interrupt generator
760 is broken */
761 return snd_pcm_lib_ioctl(substream, cmd, arg);
762}
763
764/*---------------------------------------------------------------------------
765 snd_trident_allocate_pcm_mem
766
767 Description: Allocate PCM ring buffer for given substream
768
769 Parameters: substream - PCM substream class
770 hw_params - hardware parameters
771
772 Returns: Error status
773
774 ---------------------------------------------------------------------------*/
775
776static int snd_trident_allocate_pcm_mem(snd_pcm_substream_t * substream,
777 snd_pcm_hw_params_t * hw_params)
778{
779 trident_t *trident = snd_pcm_substream_chip(substream);
780 snd_pcm_runtime_t *runtime = substream->runtime;
781 snd_trident_voice_t *voice = (snd_trident_voice_t *) runtime->private_data;
782 int err;
783
784 if ((err = snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(hw_params))) < 0)
785 return err;
786 if (trident->tlb.entries) {
787 if (err > 0) { /* change */
788 if (voice->memblk)
789 snd_trident_free_pages(trident, voice->memblk);
790 voice->memblk = snd_trident_alloc_pages(trident, substream);
791 if (voice->memblk == NULL)
792 return -ENOMEM;
793 }
794 }
795 return 0;
796}
797
798/*---------------------------------------------------------------------------
799 snd_trident_allocate_evoice
800
801 Description: Allocate extra voice as interrupt generator
802
803 Parameters: substream - PCM substream class
804 hw_params - hardware parameters
805
806 Returns: Error status
807
808 ---------------------------------------------------------------------------*/
809
810static int snd_trident_allocate_evoice(snd_pcm_substream_t * substream,
811 snd_pcm_hw_params_t * hw_params)
812{
813 trident_t *trident = snd_pcm_substream_chip(substream);
814 snd_pcm_runtime_t *runtime = substream->runtime;
815 snd_trident_voice_t *voice = (snd_trident_voice_t *) runtime->private_data;
816 snd_trident_voice_t *evoice = voice->extra;
817
818 /* voice management */
819
820 if (params_buffer_size(hw_params) / 2 != params_period_size(hw_params)) {
821 if (evoice == NULL) {
822 evoice = snd_trident_alloc_voice(trident, SNDRV_TRIDENT_VOICE_TYPE_PCM, 0, 0);
823 if (evoice == NULL)
824 return -ENOMEM;
825 voice->extra = evoice;
826 evoice->substream = substream;
827 }
828 } else {
829 if (evoice != NULL) {
830 snd_trident_free_voice(trident, evoice);
831 voice->extra = evoice = NULL;
832 }
833 }
834
835 return 0;
836}
837
838/*---------------------------------------------------------------------------
839 snd_trident_hw_params
840
841 Description: Set the hardware parameters for the playback device.
842
843 Parameters: substream - PCM substream class
844 hw_params - hardware parameters
845
846 Returns: Error status
847
848 ---------------------------------------------------------------------------*/
849
850static int snd_trident_hw_params(snd_pcm_substream_t * substream,
851 snd_pcm_hw_params_t * hw_params)
852{
853 int err;
854
855 err = snd_trident_allocate_pcm_mem(substream, hw_params);
856 if (err >= 0)
857 err = snd_trident_allocate_evoice(substream, hw_params);
858 return err;
859}
860
861/*---------------------------------------------------------------------------
862 snd_trident_playback_hw_free
863
864 Description: Release the hardware resources for the playback device.
865
866 Parameters: substream - PCM substream class
867
868 Returns: Error status
869
870 ---------------------------------------------------------------------------*/
871
872static int snd_trident_hw_free(snd_pcm_substream_t * substream)
873{
874 trident_t *trident = snd_pcm_substream_chip(substream);
875 snd_pcm_runtime_t *runtime = substream->runtime;
876 snd_trident_voice_t *voice = (snd_trident_voice_t *) runtime->private_data;
877 snd_trident_voice_t *evoice = voice ? voice->extra : NULL;
878
879 if (trident->tlb.entries) {
880 if (voice && voice->memblk) {
881 snd_trident_free_pages(trident, voice->memblk);
882 voice->memblk = NULL;
883 }
884 }
885 snd_pcm_lib_free_pages(substream);
886 if (evoice != NULL) {
887 snd_trident_free_voice(trident, evoice);
888 voice->extra = NULL;
889 }
890 return 0;
891}
892
893/*---------------------------------------------------------------------------
894 snd_trident_playback_prepare
895
896 Description: Prepare playback device for playback.
897
898 Parameters: substream - PCM substream class
899
900 Returns: Error status
901
902 ---------------------------------------------------------------------------*/
903
904static int snd_trident_playback_prepare(snd_pcm_substream_t * substream)
905{
906 trident_t *trident = snd_pcm_substream_chip(substream);
907 snd_pcm_runtime_t *runtime = substream->runtime;
908 snd_trident_voice_t *voice = (snd_trident_voice_t *) runtime->private_data;
909 snd_trident_voice_t *evoice = voice->extra;
910 snd_trident_pcm_mixer_t *mix = &trident->pcm_mixer[substream->number];
911
912 spin_lock_irq(&trident->reg_lock);
913
914 /* set delta (rate) value */
915 voice->Delta = snd_trident_convert_rate(runtime->rate);
916 voice->spurious_threshold = snd_trident_spurious_threshold(runtime->rate, runtime->period_size);
917
918 /* set Loop Begin Address */
919 if (voice->memblk)
920 voice->LBA = voice->memblk->offset;
921 else
922 voice->LBA = runtime->dma_addr;
923
924 voice->CSO = 0;
925 voice->ESO = runtime->buffer_size - 1; /* in samples */
926 voice->CTRL = snd_trident_control_mode(substream);
927 voice->FMC = 3;
928 voice->GVSel = 1;
929 voice->EC = 0;
930 voice->Alpha = 0;
931 voice->FMS = 0;
932 voice->Vol = mix->vol;
933 voice->RVol = mix->rvol;
934 voice->CVol = mix->cvol;
935 voice->Pan = mix->pan;
936 voice->Attribute = 0;
937#if 0
938 voice->Attribute = (1<<(30-16))|(2<<(26-16))|
939 (0<<(24-16))|(0x1f<<(19-16));
940#else
941 voice->Attribute = 0;
942#endif
943
944 snd_trident_write_voice_regs(trident, voice);
945
946 if (evoice != NULL) {
947 evoice->Delta = voice->Delta;
948 evoice->spurious_threshold = voice->spurious_threshold;
949 evoice->LBA = voice->LBA;
950 evoice->CSO = 0;
951 evoice->ESO = (runtime->period_size * 2) + 4 - 1; /* in samples */
952 evoice->CTRL = voice->CTRL;
953 evoice->FMC = 3;
954 evoice->GVSel = trident->device == TRIDENT_DEVICE_ID_SI7018 ? 0 : 1;
955 evoice->EC = 0;
956 evoice->Alpha = 0;
957 evoice->FMS = 0;
958 evoice->Vol = 0x3ff; /* mute */
959 evoice->RVol = evoice->CVol = 0x7f; /* mute */
960 evoice->Pan = 0x7f; /* mute */
961#if 0
962 evoice->Attribute = (1<<(30-16))|(2<<(26-16))|
963 (0<<(24-16))|(0x1f<<(19-16));
964#else
965 evoice->Attribute = 0;
966#endif
967 snd_trident_write_voice_regs(trident, evoice);
968 evoice->isync2 = 1;
969 evoice->isync_mark = runtime->period_size;
970 evoice->ESO = (runtime->period_size * 2) - 1;
971 }
972
973 spin_unlock_irq(&trident->reg_lock);
974
975 return 0;
976}
977
978/*---------------------------------------------------------------------------
979 snd_trident_capture_hw_params
980
981 Description: Set the hardware parameters for the capture device.
982
983 Parameters: substream - PCM substream class
984 hw_params - hardware parameters
985
986 Returns: Error status
987
988 ---------------------------------------------------------------------------*/
989
990static int snd_trident_capture_hw_params(snd_pcm_substream_t * substream,
991 snd_pcm_hw_params_t * hw_params)
992{
993 return snd_trident_allocate_pcm_mem(substream, hw_params);
994}
995
996/*---------------------------------------------------------------------------
997 snd_trident_capture_prepare
998
999 Description: Prepare capture device for playback.
1000
1001 Parameters: substream - PCM substream class
1002
1003 Returns: Error status
1004
1005 ---------------------------------------------------------------------------*/
1006
1007static int snd_trident_capture_prepare(snd_pcm_substream_t * substream)
1008{
1009 trident_t *trident = snd_pcm_substream_chip(substream);
1010 snd_pcm_runtime_t *runtime = substream->runtime;
1011 snd_trident_voice_t *voice = (snd_trident_voice_t *) runtime->private_data;
1012 unsigned int val, ESO_bytes;
1013
1014 spin_lock_irq(&trident->reg_lock);
1015
1016 // Initilize the channel and set channel Mode
1017 outb(0, TRID_REG(trident, LEGACY_DMAR15));
1018
1019 // Set DMA channel operation mode register
1020 outb(0x54, TRID_REG(trident, LEGACY_DMAR11));
1021
1022 // Set channel buffer Address, DMAR0 expects contiguous PCI memory area
1023 voice->LBA = runtime->dma_addr;
1024 outl(voice->LBA, TRID_REG(trident, LEGACY_DMAR0));
1025 if (voice->memblk)
1026 voice->LBA = voice->memblk->offset;
1027
1028 // set ESO
1029 ESO_bytes = snd_pcm_lib_buffer_bytes(substream) - 1;
1030 outb((ESO_bytes & 0x00ff0000) >> 16, TRID_REG(trident, LEGACY_DMAR6));
1031 outw((ESO_bytes & 0x0000ffff), TRID_REG(trident, LEGACY_DMAR4));
1032 ESO_bytes++;
1033
1034 // Set channel sample rate, 4.12 format
1035 val = (((unsigned int) 48000L << 12) + (runtime->rate/2)) / runtime->rate;
1036 outw(val, TRID_REG(trident, T4D_SBDELTA_DELTA_R));
1037
1038 // Set channel interrupt blk length
1039 if (snd_pcm_format_width(runtime->format) == 16) {
1040 val = (unsigned short) ((ESO_bytes >> 1) - 1);
1041 } else {
1042 val = (unsigned short) (ESO_bytes - 1);
1043 }
1044
1045 outl((val << 16) | val, TRID_REG(trident, T4D_SBBL_SBCL));
1046
1047 // Right now, set format and start to run captureing,
1048 // continuous run loop enable.
1049 trident->bDMAStart = 0x19; // 0001 1001b
1050
1051 if (snd_pcm_format_width(runtime->format) == 16)
1052 trident->bDMAStart |= 0x80;
1053 if (snd_pcm_format_signed(runtime->format))
1054 trident->bDMAStart |= 0x20;
1055 if (runtime->channels > 1)
1056 trident->bDMAStart |= 0x40;
1057
1058 // Prepare capture intr channel
1059
1060 voice->Delta = snd_trident_convert_rate(runtime->rate);
1061 voice->spurious_threshold = snd_trident_spurious_threshold(runtime->rate, runtime->period_size);
1062 voice->isync = 1;
1063 voice->isync_mark = runtime->period_size;
1064 voice->isync_max = runtime->buffer_size;
1065
1066 // Set voice parameters
1067 voice->CSO = 0;
1068 voice->ESO = voice->isync_ESO = (runtime->period_size * 2) + 6 - 1;
1069 voice->CTRL = snd_trident_control_mode(substream);
1070 voice->FMC = 3;
1071 voice->RVol = 0x7f;
1072 voice->CVol = 0x7f;
1073 voice->GVSel = 1;
1074 voice->Pan = 0x7f; /* mute */
1075 voice->Vol = 0x3ff; /* mute */
1076 voice->EC = 0;
1077 voice->Alpha = 0;
1078 voice->FMS = 0;
1079 voice->Attribute = 0;
1080
1081 snd_trident_write_voice_regs(trident, voice);
1082
1083 spin_unlock_irq(&trident->reg_lock);
1084 return 0;
1085}
1086
1087/*---------------------------------------------------------------------------
1088 snd_trident_si7018_capture_hw_params
1089
1090 Description: Set the hardware parameters for the capture device.
1091
1092 Parameters: substream - PCM substream class
1093 hw_params - hardware parameters
1094
1095 Returns: Error status
1096
1097 ---------------------------------------------------------------------------*/
1098
1099static int snd_trident_si7018_capture_hw_params(snd_pcm_substream_t * substream,
1100 snd_pcm_hw_params_t * hw_params)
1101{
1102 int err;
1103
1104 if ((err = snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(hw_params))) < 0)
1105 return err;
1106
1107 return snd_trident_allocate_evoice(substream, hw_params);
1108}
1109
1110/*---------------------------------------------------------------------------
1111 snd_trident_si7018_capture_hw_free
1112
1113 Description: Release the hardware resources for the capture device.
1114
1115 Parameters: substream - PCM substream class
1116
1117 Returns: Error status
1118
1119 ---------------------------------------------------------------------------*/
1120
1121static int snd_trident_si7018_capture_hw_free(snd_pcm_substream_t * substream)
1122{
1123 trident_t *trident = snd_pcm_substream_chip(substream);
1124 snd_pcm_runtime_t *runtime = substream->runtime;
1125 snd_trident_voice_t *voice = (snd_trident_voice_t *) runtime->private_data;
1126 snd_trident_voice_t *evoice = voice ? voice->extra : NULL;
1127
1128 snd_pcm_lib_free_pages(substream);
1129 if (evoice != NULL) {
1130 snd_trident_free_voice(trident, evoice);
1131 voice->extra = NULL;
1132 }
1133 return 0;
1134}
1135
1136/*---------------------------------------------------------------------------
1137 snd_trident_si7018_capture_prepare
1138
1139 Description: Prepare capture device for playback.
1140
1141 Parameters: substream - PCM substream class
1142
1143 Returns: Error status
1144
1145 ---------------------------------------------------------------------------*/
1146
1147static int snd_trident_si7018_capture_prepare(snd_pcm_substream_t * substream)
1148{
1149 trident_t *trident = snd_pcm_substream_chip(substream);
1150 snd_pcm_runtime_t *runtime = substream->runtime;
1151 snd_trident_voice_t *voice = (snd_trident_voice_t *) runtime->private_data;
1152 snd_trident_voice_t *evoice = voice->extra;
1153
1154 spin_lock_irq(&trident->reg_lock);
1155
1156 voice->LBA = runtime->dma_addr;
1157 voice->Delta = snd_trident_convert_adc_rate(runtime->rate);
1158 voice->spurious_threshold = snd_trident_spurious_threshold(runtime->rate, runtime->period_size);
1159
1160 // Set voice parameters
1161 voice->CSO = 0;
1162 voice->ESO = runtime->buffer_size - 1; /* in samples */
1163 voice->CTRL = snd_trident_control_mode(substream);
1164 voice->FMC = 0;
1165 voice->RVol = 0;
1166 voice->CVol = 0;
1167 voice->GVSel = 1;
1168 voice->Pan = T4D_DEFAULT_PCM_PAN;
1169 voice->Vol = 0;
1170 voice->EC = 0;
1171 voice->Alpha = 0;
1172 voice->FMS = 0;
1173
1174 voice->Attribute = (2 << (30-16)) |
1175 (2 << (26-16)) |
1176 (2 << (24-16)) |
1177 (1 << (23-16));
1178
1179 snd_trident_write_voice_regs(trident, voice);
1180
1181 if (evoice != NULL) {
1182 evoice->Delta = snd_trident_convert_rate(runtime->rate);
1183 evoice->spurious_threshold = voice->spurious_threshold;
1184 evoice->LBA = voice->LBA;
1185 evoice->CSO = 0;
1186 evoice->ESO = (runtime->period_size * 2) + 20 - 1; /* in samples, 20 means correction */
1187 evoice->CTRL = voice->CTRL;
1188 evoice->FMC = 3;
1189 evoice->GVSel = 0;
1190 evoice->EC = 0;
1191 evoice->Alpha = 0;
1192 evoice->FMS = 0;
1193 evoice->Vol = 0x3ff; /* mute */
1194 evoice->RVol = evoice->CVol = 0x7f; /* mute */
1195 evoice->Pan = 0x7f; /* mute */
1196 evoice->Attribute = 0;
1197 snd_trident_write_voice_regs(trident, evoice);
1198 evoice->isync2 = 1;
1199 evoice->isync_mark = runtime->period_size;
1200 evoice->ESO = (runtime->period_size * 2) - 1;
1201 }
1202
1203 spin_unlock_irq(&trident->reg_lock);
1204 return 0;
1205}
1206
1207/*---------------------------------------------------------------------------
1208 snd_trident_foldback_prepare
1209
1210 Description: Prepare foldback capture device for playback.
1211
1212 Parameters: substream - PCM substream class
1213
1214 Returns: Error status
1215
1216 ---------------------------------------------------------------------------*/
1217
1218static int snd_trident_foldback_prepare(snd_pcm_substream_t * substream)
1219{
1220 trident_t *trident = snd_pcm_substream_chip(substream);
1221 snd_pcm_runtime_t *runtime = substream->runtime;
1222 snd_trident_voice_t *voice = (snd_trident_voice_t *) runtime->private_data;
1223 snd_trident_voice_t *evoice = voice->extra;
1224
1225 spin_lock_irq(&trident->reg_lock);
1226
1227 /* Set channel buffer Address */
1228 if (voice->memblk)
1229 voice->LBA = voice->memblk->offset;
1230 else
1231 voice->LBA = runtime->dma_addr;
1232
1233 /* set target ESO for channel */
1234 voice->ESO = runtime->buffer_size - 1; /* in samples */
1235
1236 /* set sample rate */
1237 voice->Delta = 0x1000;
1238 voice->spurious_threshold = snd_trident_spurious_threshold(48000, runtime->period_size);
1239
1240 voice->CSO = 0;
1241 voice->CTRL = snd_trident_control_mode(substream);
1242 voice->FMC = 3;
1243 voice->RVol = 0x7f;
1244 voice->CVol = 0x7f;
1245 voice->GVSel = 1;
1246 voice->Pan = 0x7f; /* mute */
1247 voice->Vol = 0x3ff; /* mute */
1248 voice->EC = 0;
1249 voice->Alpha = 0;
1250 voice->FMS = 0;
1251 voice->Attribute = 0;
1252
1253 /* set up capture channel */
1254 outb(((voice->number & 0x3f) | 0x80), TRID_REG(trident, T4D_RCI + voice->foldback_chan));
1255
1256 snd_trident_write_voice_regs(trident, voice);
1257
1258 if (evoice != NULL) {
1259 evoice->Delta = voice->Delta;
1260 evoice->spurious_threshold = voice->spurious_threshold;
1261 evoice->LBA = voice->LBA;
1262 evoice->CSO = 0;
1263 evoice->ESO = (runtime->period_size * 2) + 4 - 1; /* in samples */
1264 evoice->CTRL = voice->CTRL;
1265 evoice->FMC = 3;
1266 evoice->GVSel = trident->device == TRIDENT_DEVICE_ID_SI7018 ? 0 : 1;
1267 evoice->EC = 0;
1268 evoice->Alpha = 0;
1269 evoice->FMS = 0;
1270 evoice->Vol = 0x3ff; /* mute */
1271 evoice->RVol = evoice->CVol = 0x7f; /* mute */
1272 evoice->Pan = 0x7f; /* mute */
1273 evoice->Attribute = 0;
1274 snd_trident_write_voice_regs(trident, evoice);
1275 evoice->isync2 = 1;
1276 evoice->isync_mark = runtime->period_size;
1277 evoice->ESO = (runtime->period_size * 2) - 1;
1278 }
1279
1280 spin_unlock_irq(&trident->reg_lock);
1281 return 0;
1282}
1283
1284/*---------------------------------------------------------------------------
1285 snd_trident_spdif_hw_params
1286
1287 Description: Set the hardware parameters for the spdif device.
1288
1289 Parameters: substream - PCM substream class
1290 hw_params - hardware parameters
1291
1292 Returns: Error status
1293
1294 ---------------------------------------------------------------------------*/
1295
1296static int snd_trident_spdif_hw_params(snd_pcm_substream_t * substream,
1297 snd_pcm_hw_params_t * hw_params)
1298{
1299 trident_t *trident = snd_pcm_substream_chip(substream);
1300 unsigned int old_bits = 0, change = 0;
1301 int err;
1302
1303 err = snd_trident_allocate_pcm_mem(substream, hw_params);
1304 if (err < 0)
1305 return err;
1306
1307 if (trident->device == TRIDENT_DEVICE_ID_SI7018) {
1308 err = snd_trident_allocate_evoice(substream, hw_params);
1309 if (err < 0)
1310 return err;
1311 }
1312
1313 /* prepare SPDIF channel */
1314 spin_lock_irq(&trident->reg_lock);
1315 old_bits = trident->spdif_pcm_bits;
1316 if (old_bits & IEC958_AES0_PROFESSIONAL)
1317 trident->spdif_pcm_bits &= ~IEC958_AES0_PRO_FS;
1318 else
1319 trident->spdif_pcm_bits &= ~(IEC958_AES3_CON_FS << 24);
1320 if (params_rate(hw_params) >= 48000) {
1321 trident->spdif_pcm_ctrl = 0x3c; // 48000 Hz
1322 trident->spdif_pcm_bits |=
1323 trident->spdif_bits & IEC958_AES0_PROFESSIONAL ?
1324 IEC958_AES0_PRO_FS_48000 :
1325 (IEC958_AES3_CON_FS_48000 << 24);
1326 }
1327 else if (params_rate(hw_params) >= 44100) {
1328 trident->spdif_pcm_ctrl = 0x3e; // 44100 Hz
1329 trident->spdif_pcm_bits |=
1330 trident->spdif_bits & IEC958_AES0_PROFESSIONAL ?
1331 IEC958_AES0_PRO_FS_44100 :
1332 (IEC958_AES3_CON_FS_44100 << 24);
1333 }
1334 else {
1335 trident->spdif_pcm_ctrl = 0x3d; // 32000 Hz
1336 trident->spdif_pcm_bits |=
1337 trident->spdif_bits & IEC958_AES0_PROFESSIONAL ?
1338 IEC958_AES0_PRO_FS_32000 :
1339 (IEC958_AES3_CON_FS_32000 << 24);
1340 }
1341 change = old_bits != trident->spdif_pcm_bits;
1342 spin_unlock_irq(&trident->reg_lock);
1343
1344 if (change)
1345 snd_ctl_notify(trident->card, SNDRV_CTL_EVENT_MASK_VALUE, &trident->spdif_pcm_ctl->id);
1346
1347 return 0;
1348}
1349
1350/*---------------------------------------------------------------------------
1351 snd_trident_spdif_prepare
1352
1353 Description: Prepare SPDIF device for playback.
1354
1355 Parameters: substream - PCM substream class
1356
1357 Returns: Error status
1358
1359 ---------------------------------------------------------------------------*/
1360
1361static int snd_trident_spdif_prepare(snd_pcm_substream_t * substream)
1362{
1363 trident_t *trident = snd_pcm_substream_chip(substream);
1364 snd_pcm_runtime_t *runtime = substream->runtime;
1365 snd_trident_voice_t *voice = (snd_trident_voice_t *) runtime->private_data;
1366 snd_trident_voice_t *evoice = voice->extra;
1367 snd_trident_pcm_mixer_t *mix = &trident->pcm_mixer[substream->number];
1368 unsigned int RESO, LBAO;
1369 unsigned int temp;
1370
1371 spin_lock_irq(&trident->reg_lock);
1372
1373 if (trident->device != TRIDENT_DEVICE_ID_SI7018) {
1374
1375 /* set delta (rate) value */
1376 voice->Delta = snd_trident_convert_rate(runtime->rate);
1377 voice->spurious_threshold = snd_trident_spurious_threshold(runtime->rate, runtime->period_size);
1378
1379 /* set Loop Back Address */
1380 LBAO = runtime->dma_addr;
1381 if (voice->memblk)
1382 voice->LBA = voice->memblk->offset;
1383 else
1384 voice->LBA = LBAO;
1385
1386 voice->isync = 1;
1387 voice->isync3 = 1;
1388 voice->isync_mark = runtime->period_size;
1389 voice->isync_max = runtime->buffer_size;
1390
1391 /* set target ESO for channel */
1392 RESO = runtime->buffer_size - 1;
1393 voice->ESO = voice->isync_ESO = (runtime->period_size * 2) + 6 - 1;
1394
1395 /* set ctrl mode */
1396 voice->CTRL = snd_trident_control_mode(substream);
1397
1398 voice->FMC = 3;
1399 voice->RVol = 0x7f;
1400 voice->CVol = 0x7f;
1401 voice->GVSel = 1;
1402 voice->Pan = 0x7f;
1403 voice->Vol = 0x3ff;
1404 voice->EC = 0;
1405 voice->CSO = 0;
1406 voice->Alpha = 0;
1407 voice->FMS = 0;
1408 voice->Attribute = 0;
1409
1410 /* prepare surrogate IRQ channel */
1411 snd_trident_write_voice_regs(trident, voice);
1412
1413 outw((RESO & 0xffff), TRID_REG(trident, NX_SPESO));
1414 outb((RESO >> 16), TRID_REG(trident, NX_SPESO + 2));
1415 outl((LBAO & 0xfffffffc), TRID_REG(trident, NX_SPLBA));
1416 outw((voice->CSO & 0xffff), TRID_REG(trident, NX_SPCTRL_SPCSO));
1417 outb((voice->CSO >> 16), TRID_REG(trident, NX_SPCTRL_SPCSO + 2));
1418
1419 /* set SPDIF setting */
1420 outb(trident->spdif_pcm_ctrl, TRID_REG(trident, NX_SPCTRL_SPCSO + 3));
1421 outl(trident->spdif_pcm_bits, TRID_REG(trident, NX_SPCSTATUS));
1422
1423 } else { /* SiS */
1424
1425 /* set delta (rate) value */
1426 voice->Delta = 0x800;
1427 voice->spurious_threshold = snd_trident_spurious_threshold(48000, runtime->period_size);
1428
1429 /* set Loop Begin Address */
1430 if (voice->memblk)
1431 voice->LBA = voice->memblk->offset;
1432 else
1433 voice->LBA = runtime->dma_addr;
1434
1435 voice->CSO = 0;
1436 voice->ESO = runtime->buffer_size - 1; /* in samples */
1437 voice->CTRL = snd_trident_control_mode(substream);
1438 voice->FMC = 3;
1439 voice->GVSel = 1;
1440 voice->EC = 0;
1441 voice->Alpha = 0;
1442 voice->FMS = 0;
1443 voice->Vol = mix->vol;
1444 voice->RVol = mix->rvol;
1445 voice->CVol = mix->cvol;
1446 voice->Pan = mix->pan;
1447 voice->Attribute = (1<<(30-16))|(7<<(26-16))|
1448 (0<<(24-16))|(0<<(19-16));
1449
1450 snd_trident_write_voice_regs(trident, voice);
1451
1452 if (evoice != NULL) {
1453 evoice->Delta = voice->Delta;
1454 evoice->spurious_threshold = voice->spurious_threshold;
1455 evoice->LBA = voice->LBA;
1456 evoice->CSO = 0;
1457 evoice->ESO = (runtime->period_size * 2) + 4 - 1; /* in samples */
1458 evoice->CTRL = voice->CTRL;
1459 evoice->FMC = 3;
1460 evoice->GVSel = trident->device == TRIDENT_DEVICE_ID_SI7018 ? 0 : 1;
1461 evoice->EC = 0;
1462 evoice->Alpha = 0;
1463 evoice->FMS = 0;
1464 evoice->Vol = 0x3ff; /* mute */
1465 evoice->RVol = evoice->CVol = 0x7f; /* mute */
1466 evoice->Pan = 0x7f; /* mute */
1467 evoice->Attribute = 0;
1468 snd_trident_write_voice_regs(trident, evoice);
1469 evoice->isync2 = 1;
1470 evoice->isync_mark = runtime->period_size;
1471 evoice->ESO = (runtime->period_size * 2) - 1;
1472 }
1473
1474 outl(trident->spdif_pcm_bits, TRID_REG(trident, SI_SPDIF_CS));
1475 temp = inl(TRID_REG(trident, T4D_LFO_GC_CIR));
1476 temp &= ~(1<<19);
1477 outl(temp, TRID_REG(trident, T4D_LFO_GC_CIR));
1478 temp = inl(TRID_REG(trident, SI_SERIAL_INTF_CTRL));
1479 temp |= SPDIF_EN;
1480 outl(temp, TRID_REG(trident, SI_SERIAL_INTF_CTRL));
1481 }
1482
1483 spin_unlock_irq(&trident->reg_lock);
1484
1485 return 0;
1486}
1487
1488/*---------------------------------------------------------------------------
1489 snd_trident_trigger
1490
1491 Description: Start/stop devices
1492
1493 Parameters: substream - PCM substream class
1494 cmd - trigger command (STOP, GO)
1495
1496 Returns: Error status
1497
1498 ---------------------------------------------------------------------------*/
1499
1500static int snd_trident_trigger(snd_pcm_substream_t *substream,
1501 int cmd)
1502
1503{
1504 trident_t *trident = snd_pcm_substream_chip(substream);
1505 struct list_head *pos;
1506 snd_pcm_substream_t *s;
1507 unsigned int what, whati, capture_flag, spdif_flag;
1508 snd_trident_voice_t *voice, *evoice;
1509 unsigned int val, go;
1510
1511 switch (cmd) {
1512 case SNDRV_PCM_TRIGGER_START:
1513 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
1514 case SNDRV_PCM_TRIGGER_RESUME:
1515 go = 1;
1516 break;
1517 case SNDRV_PCM_TRIGGER_STOP:
1518 case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
1519 case SNDRV_PCM_TRIGGER_SUSPEND:
1520 go = 0;
1521 break;
1522 default:
1523 return -EINVAL;
1524 }
1525 what = whati = capture_flag = spdif_flag = 0;
1526 spin_lock(&trident->reg_lock);
1527 val = inl(TRID_REG(trident, T4D_STIMER)) & 0x00ffffff;
1528 snd_pcm_group_for_each(pos, substream) {
1529 s = snd_pcm_group_substream_entry(pos);
1530 if ((trident_t *) snd_pcm_substream_chip(s) == trident) {
1531 voice = (snd_trident_voice_t *) s->runtime->private_data;
1532 evoice = voice->extra;
1533 what |= 1 << (voice->number & 0x1f);
1534 if (evoice == NULL) {
1535 whati |= 1 << (voice->number & 0x1f);
1536 } else {
1537 what |= 1 << (evoice->number & 0x1f);
1538 whati |= 1 << (evoice->number & 0x1f);
1539 if (go)
1540 evoice->stimer = val;
1541 }
1542 if (go) {
1543 voice->running = 1;
1544 voice->stimer = val;
1545 } else {
1546 voice->running = 0;
1547 }
1548 snd_pcm_trigger_done(s, substream);
1549 if (voice->capture)
1550 capture_flag = 1;
1551 if (voice->spdif)
1552 spdif_flag = 1;
1553 }
1554 }
1555 if (spdif_flag) {
1556 if (trident->device != TRIDENT_DEVICE_ID_SI7018) {
1557 outl(trident->spdif_pcm_bits, TRID_REG(trident, NX_SPCSTATUS));
1558 outb(trident->spdif_pcm_ctrl, TRID_REG(trident, NX_SPCTRL_SPCSO + 3));
1559 } else {
1560 outl(trident->spdif_pcm_bits, TRID_REG(trident, SI_SPDIF_CS));
1561 val = inl(TRID_REG(trident, SI_SERIAL_INTF_CTRL)) | SPDIF_EN;
1562 outl(val, TRID_REG(trident, SI_SERIAL_INTF_CTRL));
1563 }
1564 }
1565 if (!go)
1566 outl(what, TRID_REG(trident, T4D_STOP_B));
1567 val = inl(TRID_REG(trident, T4D_AINTEN_B));
1568 if (go) {
1569 val |= whati;
1570 } else {
1571 val &= ~whati;
1572 }
1573 outl(val, TRID_REG(trident, T4D_AINTEN_B));
1574 if (go) {
1575 outl(what, TRID_REG(trident, T4D_START_B));
1576
1577 if (capture_flag && trident->device != TRIDENT_DEVICE_ID_SI7018)
1578 outb(trident->bDMAStart, TRID_REG(trident, T4D_SBCTRL_SBE2R_SBDD));
1579 } else {
1580 if (capture_flag && trident->device != TRIDENT_DEVICE_ID_SI7018)
1581 outb(0x00, TRID_REG(trident, T4D_SBCTRL_SBE2R_SBDD));
1582 }
1583 spin_unlock(&trident->reg_lock);
1584 return 0;
1585}
1586
1587/*---------------------------------------------------------------------------
1588 snd_trident_playback_pointer
1589
1590 Description: This routine return the playback position
1591
1592 Parameters: substream - PCM substream class
1593
1594 Returns: position of buffer
1595
1596 ---------------------------------------------------------------------------*/
1597
1598static snd_pcm_uframes_t snd_trident_playback_pointer(snd_pcm_substream_t * substream)
1599{
1600 trident_t *trident = snd_pcm_substream_chip(substream);
1601 snd_pcm_runtime_t *runtime = substream->runtime;
1602 snd_trident_voice_t *voice = (snd_trident_voice_t *) runtime->private_data;
1603 unsigned int cso;
1604
1605 if (!voice->running)
1606 return 0;
1607
1608 spin_lock(&trident->reg_lock);
1609
1610 outb(voice->number, TRID_REG(trident, T4D_LFO_GC_CIR));
1611
1612 if (trident->device != TRIDENT_DEVICE_ID_NX) {
1613 cso = inw(TRID_REG(trident, CH_DX_CSO_ALPHA_FMS + 2));
1614 } else { // ID_4DWAVE_NX
1615 cso = (unsigned int) inl(TRID_REG(trident, CH_NX_DELTA_CSO)) & 0x00ffffff;
1616 }
1617
1618 spin_unlock(&trident->reg_lock);
1619
1620 if (cso >= runtime->buffer_size)
1621 cso = 0;
1622
1623 return cso;
1624}
1625
1626/*---------------------------------------------------------------------------
1627 snd_trident_capture_pointer
1628
1629 Description: This routine return the capture position
1630
1631 Paramters: pcm1 - PCM device class
1632
1633 Returns: position of buffer
1634
1635 ---------------------------------------------------------------------------*/
1636
1637static snd_pcm_uframes_t snd_trident_capture_pointer(snd_pcm_substream_t * substream)
1638{
1639 trident_t *trident = snd_pcm_substream_chip(substream);
1640 snd_pcm_runtime_t *runtime = substream->runtime;
1641 snd_trident_voice_t *voice = (snd_trident_voice_t *) runtime->private_data;
1642 unsigned int result;
1643
1644 if (!voice->running)
1645 return 0;
1646
1647 result = inw(TRID_REG(trident, T4D_SBBL_SBCL));
1648 if (runtime->channels > 1)
1649 result >>= 1;
1650 if (result > 0)
1651 result = runtime->buffer_size - result;
1652
1653 return result;
1654}
1655
1656/*---------------------------------------------------------------------------
1657 snd_trident_spdif_pointer
1658
1659 Description: This routine return the SPDIF playback position
1660
1661 Parameters: substream - PCM substream class
1662
1663 Returns: position of buffer
1664
1665 ---------------------------------------------------------------------------*/
1666
1667static snd_pcm_uframes_t snd_trident_spdif_pointer(snd_pcm_substream_t * substream)
1668{
1669 trident_t *trident = snd_pcm_substream_chip(substream);
1670 snd_pcm_runtime_t *runtime = substream->runtime;
1671 snd_trident_voice_t *voice = (snd_trident_voice_t *) runtime->private_data;
1672 unsigned int result;
1673
1674 if (!voice->running)
1675 return 0;
1676
1677 result = inl(TRID_REG(trident, NX_SPCTRL_SPCSO)) & 0x00ffffff;
1678
1679 return result;
1680}
1681
1682/*
1683 * Playback support device description
1684 */
1685
1686static snd_pcm_hardware_t snd_trident_playback =
1687{
1688 .info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED |
1689 SNDRV_PCM_INFO_BLOCK_TRANSFER |
1690 SNDRV_PCM_INFO_MMAP_VALID | SNDRV_PCM_INFO_SYNC_START |
1691 SNDRV_PCM_INFO_PAUSE | SNDRV_PCM_INFO_RESUME),
1692 .formats = (SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S16_LE |
1693 SNDRV_PCM_FMTBIT_S8 | SNDRV_PCM_FMTBIT_U16_LE),
1694 .rates = SNDRV_PCM_RATE_CONTINUOUS | SNDRV_PCM_RATE_8000_48000,
1695 .rate_min = 4000,
1696 .rate_max = 48000,
1697 .channels_min = 1,
1698 .channels_max = 2,
1699 .buffer_bytes_max = (256*1024),
1700 .period_bytes_min = 64,
1701 .period_bytes_max = (256*1024),
1702 .periods_min = 1,
1703 .periods_max = 1024,
1704 .fifo_size = 0,
1705};
1706
1707/*
1708 * Capture support device description
1709 */
1710
1711static snd_pcm_hardware_t snd_trident_capture =
1712{
1713 .info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED |
1714 SNDRV_PCM_INFO_BLOCK_TRANSFER |
1715 SNDRV_PCM_INFO_MMAP_VALID | SNDRV_PCM_INFO_SYNC_START |
1716 SNDRV_PCM_INFO_PAUSE | SNDRV_PCM_INFO_RESUME),
1717 .formats = (SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S16_LE |
1718 SNDRV_PCM_FMTBIT_S8 | SNDRV_PCM_FMTBIT_U16_LE),
1719 .rates = SNDRV_PCM_RATE_CONTINUOUS | SNDRV_PCM_RATE_8000_48000,
1720 .rate_min = 4000,
1721 .rate_max = 48000,
1722 .channels_min = 1,
1723 .channels_max = 2,
1724 .buffer_bytes_max = (128*1024),
1725 .period_bytes_min = 64,
1726 .period_bytes_max = (128*1024),
1727 .periods_min = 1,
1728 .periods_max = 1024,
1729 .fifo_size = 0,
1730};
1731
1732/*
1733 * Foldback capture support device description
1734 */
1735
1736static snd_pcm_hardware_t snd_trident_foldback =
1737{
1738 .info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED |
1739 SNDRV_PCM_INFO_BLOCK_TRANSFER |
1740 SNDRV_PCM_INFO_MMAP_VALID | SNDRV_PCM_INFO_SYNC_START |
1741 SNDRV_PCM_INFO_PAUSE | SNDRV_PCM_INFO_RESUME),
1742 .formats = SNDRV_PCM_FMTBIT_S16_LE,
1743 .rates = SNDRV_PCM_RATE_48000,
1744 .rate_min = 48000,
1745 .rate_max = 48000,
1746 .channels_min = 2,
1747 .channels_max = 2,
1748 .buffer_bytes_max = (128*1024),
1749 .period_bytes_min = 64,
1750 .period_bytes_max = (128*1024),
1751 .periods_min = 1,
1752 .periods_max = 1024,
1753 .fifo_size = 0,
1754};
1755
1756/*
1757 * SPDIF playback support device description
1758 */
1759
1760static snd_pcm_hardware_t snd_trident_spdif =
1761{
1762 .info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED |
1763 SNDRV_PCM_INFO_BLOCK_TRANSFER |
1764 SNDRV_PCM_INFO_MMAP_VALID | SNDRV_PCM_INFO_SYNC_START |
1765 SNDRV_PCM_INFO_PAUSE | SNDRV_PCM_INFO_RESUME),
1766 .formats = SNDRV_PCM_FMTBIT_S16_LE,
1767 .rates = (SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 |
1768 SNDRV_PCM_RATE_48000),
1769 .rate_min = 32000,
1770 .rate_max = 48000,
1771 .channels_min = 2,
1772 .channels_max = 2,
1773 .buffer_bytes_max = (128*1024),
1774 .period_bytes_min = 64,
1775 .period_bytes_max = (128*1024),
1776 .periods_min = 1,
1777 .periods_max = 1024,
1778 .fifo_size = 0,
1779};
1780
1781static snd_pcm_hardware_t snd_trident_spdif_7018 =
1782{
1783 .info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED |
1784 SNDRV_PCM_INFO_BLOCK_TRANSFER |
1785 SNDRV_PCM_INFO_MMAP_VALID | SNDRV_PCM_INFO_SYNC_START |
1786 SNDRV_PCM_INFO_PAUSE | SNDRV_PCM_INFO_RESUME),
1787 .formats = SNDRV_PCM_FMTBIT_S16_LE,
1788 .rates = SNDRV_PCM_RATE_48000,
1789 .rate_min = 48000,
1790 .rate_max = 48000,
1791 .channels_min = 2,
1792 .channels_max = 2,
1793 .buffer_bytes_max = (128*1024),
1794 .period_bytes_min = 64,
1795 .period_bytes_max = (128*1024),
1796 .periods_min = 1,
1797 .periods_max = 1024,
1798 .fifo_size = 0,
1799};
1800
1801static void snd_trident_pcm_free_substream(snd_pcm_runtime_t *runtime)
1802{
1803 snd_trident_voice_t *voice = (snd_trident_voice_t *) runtime->private_data;
1804 trident_t *trident;
1805
1806 if (voice) {
1807 trident = voice->trident;
1808 snd_trident_free_voice(trident, voice);
1809 }
1810}
1811
1812static int snd_trident_playback_open(snd_pcm_substream_t * substream)
1813{
1814 trident_t *trident = snd_pcm_substream_chip(substream);
1815 snd_pcm_runtime_t *runtime = substream->runtime;
1816 snd_trident_voice_t *voice;
1817
1818 voice = snd_trident_alloc_voice(trident, SNDRV_TRIDENT_VOICE_TYPE_PCM, 0, 0);
1819 if (voice == NULL)
1820 return -EAGAIN;
1821 snd_trident_pcm_mixer_build(trident, voice, substream);
1822 voice->substream = substream;
1823 runtime->private_data = voice;
1824 runtime->private_free = snd_trident_pcm_free_substream;
1825 runtime->hw = snd_trident_playback;
1826 snd_pcm_set_sync(substream);
1827 snd_pcm_hw_constraint_minmax(runtime, SNDRV_PCM_HW_PARAM_BUFFER_SIZE, 0, 64*1024);
1828 return 0;
1829}
1830
1831/*---------------------------------------------------------------------------
1832 snd_trident_playback_close
1833
1834 Description: This routine will close the 4DWave playback device. For now
1835 we will simply free the dma transfer buffer.
1836
1837 Parameters: substream - PCM substream class
1838
1839 ---------------------------------------------------------------------------*/
1840static int snd_trident_playback_close(snd_pcm_substream_t * substream)
1841{
1842 trident_t *trident = snd_pcm_substream_chip(substream);
1843 snd_pcm_runtime_t *runtime = substream->runtime;
1844 snd_trident_voice_t *voice = (snd_trident_voice_t *) runtime->private_data;
1845
1846 snd_trident_pcm_mixer_free(trident, voice, substream);
1847 return 0;
1848}
1849
1850/*---------------------------------------------------------------------------
1851 snd_trident_spdif_open
1852
1853 Description: This routine will open the 4DWave SPDIF device.
1854
1855 Parameters: substream - PCM substream class
1856
1857 Returns: status - success or failure flag
1858
1859 ---------------------------------------------------------------------------*/
1860
1861static int snd_trident_spdif_open(snd_pcm_substream_t * substream)
1862{
1863 trident_t *trident = snd_pcm_substream_chip(substream);
1864 snd_trident_voice_t *voice;
1865 snd_pcm_runtime_t *runtime = substream->runtime;
1866
1867 voice = snd_trident_alloc_voice(trident, SNDRV_TRIDENT_VOICE_TYPE_PCM, 0, 0);
1868 if (voice == NULL)
1869 return -EAGAIN;
1870 voice->spdif = 1;
1871 voice->substream = substream;
1872 spin_lock_irq(&trident->reg_lock);
1873 trident->spdif_pcm_bits = trident->spdif_bits;
1874 spin_unlock_irq(&trident->reg_lock);
1875
1876 runtime->private_data = voice;
1877 runtime->private_free = snd_trident_pcm_free_substream;
1878 if (trident->device == TRIDENT_DEVICE_ID_SI7018) {
1879 runtime->hw = snd_trident_spdif;
1880 } else {
1881 runtime->hw = snd_trident_spdif_7018;
1882 }
1883
1884 trident->spdif_pcm_ctl->vd[0].access &= ~SNDRV_CTL_ELEM_ACCESS_INACTIVE;
1885 snd_ctl_notify(trident->card, SNDRV_CTL_EVENT_MASK_VALUE |
1886 SNDRV_CTL_EVENT_MASK_INFO, &trident->spdif_pcm_ctl->id);
1887
1888 snd_pcm_hw_constraint_minmax(runtime, SNDRV_PCM_HW_PARAM_BUFFER_SIZE, 0, 64*1024);
1889 return 0;
1890}
1891
1892
1893/*---------------------------------------------------------------------------
1894 snd_trident_spdif_close
1895
1896 Description: This routine will close the 4DWave SPDIF device.
1897
1898 Parameters: substream - PCM substream class
1899
1900 ---------------------------------------------------------------------------*/
1901
1902static int snd_trident_spdif_close(snd_pcm_substream_t * substream)
1903{
1904 trident_t *trident = snd_pcm_substream_chip(substream);
1905 unsigned int temp;
1906
1907 spin_lock_irq(&trident->reg_lock);
1908 // restore default SPDIF setting
1909 if (trident->device != TRIDENT_DEVICE_ID_SI7018) {
1910 outb(trident->spdif_ctrl, TRID_REG(trident, NX_SPCTRL_SPCSO + 3));
1911 outl(trident->spdif_bits, TRID_REG(trident, NX_SPCSTATUS));
1912 } else {
1913 outl(trident->spdif_bits, TRID_REG(trident, SI_SPDIF_CS));
1914 temp = inl(TRID_REG(trident, SI_SERIAL_INTF_CTRL));
1915 if (trident->spdif_ctrl) {
1916 temp |= SPDIF_EN;
1917 } else {
1918 temp &= ~SPDIF_EN;
1919 }
1920 outl(temp, TRID_REG(trident, SI_SERIAL_INTF_CTRL));
1921 }
1922 spin_unlock_irq(&trident->reg_lock);
1923 trident->spdif_pcm_ctl->vd[0].access |= SNDRV_CTL_ELEM_ACCESS_INACTIVE;
1924 snd_ctl_notify(trident->card, SNDRV_CTL_EVENT_MASK_VALUE |
1925 SNDRV_CTL_EVENT_MASK_INFO, &trident->spdif_pcm_ctl->id);
1926 return 0;
1927}
1928
1929/*---------------------------------------------------------------------------
1930 snd_trident_capture_open
1931
1932 Description: This routine will open the 4DWave capture device.
1933
1934 Parameters: substream - PCM substream class
1935
1936 Returns: status - success or failure flag
1937
1938 ---------------------------------------------------------------------------*/
1939
1940static int snd_trident_capture_open(snd_pcm_substream_t * substream)
1941{
1942 trident_t *trident = snd_pcm_substream_chip(substream);
1943 snd_trident_voice_t *voice;
1944 snd_pcm_runtime_t *runtime = substream->runtime;
1945
1946 voice = snd_trident_alloc_voice(trident, SNDRV_TRIDENT_VOICE_TYPE_PCM, 0, 0);
1947 if (voice == NULL)
1948 return -EAGAIN;
1949 voice->capture = 1;
1950 voice->substream = substream;
1951 runtime->private_data = voice;
1952 runtime->private_free = snd_trident_pcm_free_substream;
1953 runtime->hw = snd_trident_capture;
1954 snd_pcm_set_sync(substream);
1955 snd_pcm_hw_constraint_minmax(runtime, SNDRV_PCM_HW_PARAM_BUFFER_SIZE, 0, 64*1024);
1956 return 0;
1957}
1958
1959/*---------------------------------------------------------------------------
1960 snd_trident_capture_close
1961
1962 Description: This routine will close the 4DWave capture device. For now
1963 we will simply free the dma transfer buffer.
1964
1965 Parameters: substream - PCM substream class
1966
1967 ---------------------------------------------------------------------------*/
1968static int snd_trident_capture_close(snd_pcm_substream_t * substream)
1969{
1970 return 0;
1971}
1972
1973/*---------------------------------------------------------------------------
1974 snd_trident_foldback_open
1975
1976 Description: This routine will open the 4DWave foldback capture device.
1977
1978 Parameters: substream - PCM substream class
1979
1980 Returns: status - success or failure flag
1981
1982 ---------------------------------------------------------------------------*/
1983
1984static int snd_trident_foldback_open(snd_pcm_substream_t * substream)
1985{
1986 trident_t *trident = snd_pcm_substream_chip(substream);
1987 snd_trident_voice_t *voice;
1988 snd_pcm_runtime_t *runtime = substream->runtime;
1989
1990 voice = snd_trident_alloc_voice(trident, SNDRV_TRIDENT_VOICE_TYPE_PCM, 0, 0);
1991 if (voice == NULL)
1992 return -EAGAIN;
1993 voice->foldback_chan = substream->number;
1994 voice->substream = substream;
1995 runtime->private_data = voice;
1996 runtime->private_free = snd_trident_pcm_free_substream;
1997 runtime->hw = snd_trident_foldback;
1998 snd_pcm_hw_constraint_minmax(runtime, SNDRV_PCM_HW_PARAM_BUFFER_SIZE, 0, 64*1024);
1999 return 0;
2000}
2001
2002/*---------------------------------------------------------------------------
2003 snd_trident_foldback_close
2004
2005 Description: This routine will close the 4DWave foldback capture device.
2006 For now we will simply free the dma transfer buffer.
2007
2008 Parameters: substream - PCM substream class
2009
2010 ---------------------------------------------------------------------------*/
2011static int snd_trident_foldback_close(snd_pcm_substream_t * substream)
2012{
2013 trident_t *trident = snd_pcm_substream_chip(substream);
2014 snd_trident_voice_t *voice;
2015 snd_pcm_runtime_t *runtime = substream->runtime;
2016 voice = (snd_trident_voice_t *) runtime->private_data;
2017
2018 /* stop capture channel */
2019 spin_lock_irq(&trident->reg_lock);
2020 outb(0x00, TRID_REG(trident, T4D_RCI + voice->foldback_chan));
2021 spin_unlock_irq(&trident->reg_lock);
2022 return 0;
2023}
2024
2025/*---------------------------------------------------------------------------
2026 PCM operations
2027 ---------------------------------------------------------------------------*/
2028
2029static snd_pcm_ops_t snd_trident_playback_ops = {
2030 .open = snd_trident_playback_open,
2031 .close = snd_trident_playback_close,
2032 .ioctl = snd_trident_ioctl,
2033 .hw_params = snd_trident_hw_params,
2034 .hw_free = snd_trident_hw_free,
2035 .prepare = snd_trident_playback_prepare,
2036 .trigger = snd_trident_trigger,
2037 .pointer = snd_trident_playback_pointer,
2038};
2039
2040static snd_pcm_ops_t snd_trident_nx_playback_ops = {
2041 .open = snd_trident_playback_open,
2042 .close = snd_trident_playback_close,
2043 .ioctl = snd_trident_ioctl,
2044 .hw_params = snd_trident_hw_params,
2045 .hw_free = snd_trident_hw_free,
2046 .prepare = snd_trident_playback_prepare,
2047 .trigger = snd_trident_trigger,
2048 .pointer = snd_trident_playback_pointer,
2049 .page = snd_pcm_sgbuf_ops_page,
2050};
2051
2052static snd_pcm_ops_t snd_trident_capture_ops = {
2053 .open = snd_trident_capture_open,
2054 .close = snd_trident_capture_close,
2055 .ioctl = snd_trident_ioctl,
2056 .hw_params = snd_trident_capture_hw_params,
2057 .hw_free = snd_trident_hw_free,
2058 .prepare = snd_trident_capture_prepare,
2059 .trigger = snd_trident_trigger,
2060 .pointer = snd_trident_capture_pointer,
2061};
2062
2063static snd_pcm_ops_t snd_trident_si7018_capture_ops = {
2064 .open = snd_trident_capture_open,
2065 .close = snd_trident_capture_close,
2066 .ioctl = snd_trident_ioctl,
2067 .hw_params = snd_trident_si7018_capture_hw_params,
2068 .hw_free = snd_trident_si7018_capture_hw_free,
2069 .prepare = snd_trident_si7018_capture_prepare,
2070 .trigger = snd_trident_trigger,
2071 .pointer = snd_trident_playback_pointer,
2072};
2073
2074static snd_pcm_ops_t snd_trident_foldback_ops = {
2075 .open = snd_trident_foldback_open,
2076 .close = snd_trident_foldback_close,
2077 .ioctl = snd_trident_ioctl,
2078 .hw_params = snd_trident_hw_params,
2079 .hw_free = snd_trident_hw_free,
2080 .prepare = snd_trident_foldback_prepare,
2081 .trigger = snd_trident_trigger,
2082 .pointer = snd_trident_playback_pointer,
2083};
2084
2085static snd_pcm_ops_t snd_trident_nx_foldback_ops = {
2086 .open = snd_trident_foldback_open,
2087 .close = snd_trident_foldback_close,
2088 .ioctl = snd_trident_ioctl,
2089 .hw_params = snd_trident_hw_params,
2090 .hw_free = snd_trident_hw_free,
2091 .prepare = snd_trident_foldback_prepare,
2092 .trigger = snd_trident_trigger,
2093 .pointer = snd_trident_playback_pointer,
2094 .page = snd_pcm_sgbuf_ops_page,
2095};
2096
2097static snd_pcm_ops_t snd_trident_spdif_ops = {
2098 .open = snd_trident_spdif_open,
2099 .close = snd_trident_spdif_close,
2100 .ioctl = snd_trident_ioctl,
2101 .hw_params = snd_trident_spdif_hw_params,
2102 .hw_free = snd_trident_hw_free,
2103 .prepare = snd_trident_spdif_prepare,
2104 .trigger = snd_trident_trigger,
2105 .pointer = snd_trident_spdif_pointer,
2106};
2107
2108static snd_pcm_ops_t snd_trident_spdif_7018_ops = {
2109 .open = snd_trident_spdif_open,
2110 .close = snd_trident_spdif_close,
2111 .ioctl = snd_trident_ioctl,
2112 .hw_params = snd_trident_spdif_hw_params,
2113 .hw_free = snd_trident_hw_free,
2114 .prepare = snd_trident_spdif_prepare,
2115 .trigger = snd_trident_trigger,
2116 .pointer = snd_trident_playback_pointer,
2117};
2118
2119/*---------------------------------------------------------------------------
2120 snd_trident_pcm_free
2121
2122 Description: This routine release the 4DWave private data.
2123
2124 Paramters: private_data - pointer to 4DWave device info.
2125
2126 Returns: None
2127
2128 ---------------------------------------------------------------------------*/
2129static void snd_trident_pcm_free(snd_pcm_t *pcm)
2130{
2131 trident_t *trident = pcm->private_data;
2132 trident->pcm = NULL;
2133 snd_pcm_lib_preallocate_free_for_all(pcm);
2134}
2135
2136static void snd_trident_foldback_pcm_free(snd_pcm_t *pcm)
2137{
2138 trident_t *trident = pcm->private_data;
2139 trident->foldback = NULL;
2140 snd_pcm_lib_preallocate_free_for_all(pcm);
2141}
2142
2143static void snd_trident_spdif_pcm_free(snd_pcm_t *pcm)
2144{
2145 trident_t *trident = pcm->private_data;
2146 trident->spdif = NULL;
2147 snd_pcm_lib_preallocate_free_for_all(pcm);
2148}
2149
2150/*---------------------------------------------------------------------------
2151 snd_trident_pcm
2152
2153 Description: This routine registers the 4DWave device for PCM support.
2154
2155 Paramters: trident - pointer to target device class for 4DWave.
2156
2157 Returns: None
2158
2159 ---------------------------------------------------------------------------*/
2160
2161int __devinit snd_trident_pcm(trident_t * trident, int device, snd_pcm_t ** rpcm)
2162{
2163 snd_pcm_t *pcm;
2164 int err;
2165
2166 if (rpcm)
2167 *rpcm = NULL;
2168 if ((err = snd_pcm_new(trident->card, "trident_dx_nx", device, trident->ChanPCM, 1, &pcm)) < 0)
2169 return err;
2170
2171 pcm->private_data = trident;
2172 pcm->private_free = snd_trident_pcm_free;
2173
2174 if (trident->tlb.entries) {
2175 snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_trident_nx_playback_ops);
2176 } else {
2177 snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_trident_playback_ops);
2178 }
2179 snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE,
2180 trident->device != TRIDENT_DEVICE_ID_SI7018 ?
2181 &snd_trident_capture_ops :
2182 &snd_trident_si7018_capture_ops);
2183
2184 pcm->info_flags = 0;
2185 pcm->dev_subclass = SNDRV_PCM_SUBCLASS_GENERIC_MIX;
2186 strcpy(pcm->name, "Trident 4DWave");
2187 trident->pcm = pcm;
2188
2189 if (trident->tlb.entries) {
2190 snd_pcm_substream_t *substream;
2191 for (substream = pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream; substream; substream = substream->next)
2192 snd_pcm_lib_preallocate_pages(substream, SNDRV_DMA_TYPE_DEV_SG,
2193 snd_dma_pci_data(trident->pci),
2194 64*1024, 128*1024);
2195 snd_pcm_lib_preallocate_pages(pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream,
2196 SNDRV_DMA_TYPE_DEV, snd_dma_pci_data(trident->pci),
2197 64*1024, 128*1024);
2198 } else {
2199 snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV,
2200 snd_dma_pci_data(trident->pci), 64*1024, 128*1024);
2201 }
2202
2203 if (rpcm)
2204 *rpcm = pcm;
2205 return 0;
2206}
2207
2208/*---------------------------------------------------------------------------
2209 snd_trident_foldback_pcm
2210
2211 Description: This routine registers the 4DWave device for foldback PCM support.
2212
2213 Paramters: trident - pointer to target device class for 4DWave.
2214
2215 Returns: None
2216
2217 ---------------------------------------------------------------------------*/
2218
2219int __devinit snd_trident_foldback_pcm(trident_t * trident, int device, snd_pcm_t ** rpcm)
2220{
2221 snd_pcm_t *foldback;
2222 int err;
2223 int num_chan = 3;
2224 snd_pcm_substream_t *substream;
2225
2226 if (rpcm)
2227 *rpcm = NULL;
2228 if (trident->device == TRIDENT_DEVICE_ID_NX)
2229 num_chan = 4;
2230 if ((err = snd_pcm_new(trident->card, "trident_dx_nx", device, 0, num_chan, &foldback)) < 0)
2231 return err;
2232
2233 foldback->private_data = trident;
2234 foldback->private_free = snd_trident_foldback_pcm_free;
2235 if (trident->tlb.entries)
2236 snd_pcm_set_ops(foldback, SNDRV_PCM_STREAM_CAPTURE, &snd_trident_nx_foldback_ops);
2237 else
2238 snd_pcm_set_ops(foldback, SNDRV_PCM_STREAM_CAPTURE, &snd_trident_foldback_ops);
2239 foldback->info_flags = 0;
2240 strcpy(foldback->name, "Trident 4DWave");
2241 substream = foldback->streams[SNDRV_PCM_STREAM_CAPTURE].substream;
2242 strcpy(substream->name, "Front Mixer");
2243 substream = substream->next;
2244 strcpy(substream->name, "Reverb Mixer");
2245 substream = substream->next;
2246 strcpy(substream->name, "Chorus Mixer");
2247 if (num_chan == 4) {
2248 substream = substream->next;
2249 strcpy(substream->name, "Second AC'97 ADC");
2250 }
2251 trident->foldback = foldback;
2252
2253 if (trident->tlb.entries)
2254 snd_pcm_lib_preallocate_pages_for_all(foldback, SNDRV_DMA_TYPE_DEV_SG,
2255 snd_dma_pci_data(trident->pci), 0, 128*1024);
2256 else
2257 snd_pcm_lib_preallocate_pages_for_all(foldback, SNDRV_DMA_TYPE_DEV,
2258 snd_dma_pci_data(trident->pci), 64*1024, 128*1024);
2259
2260 if (rpcm)
2261 *rpcm = foldback;
2262 return 0;
2263}
2264
2265/*---------------------------------------------------------------------------
2266 snd_trident_spdif
2267
2268 Description: This routine registers the 4DWave-NX device for SPDIF support.
2269
2270 Paramters: trident - pointer to target device class for 4DWave-NX.
2271
2272 Returns: None
2273
2274 ---------------------------------------------------------------------------*/
2275
2276int __devinit snd_trident_spdif_pcm(trident_t * trident, int device, snd_pcm_t ** rpcm)
2277{
2278 snd_pcm_t *spdif;
2279 int err;
2280
2281 if (rpcm)
2282 *rpcm = NULL;
2283 if ((err = snd_pcm_new(trident->card, "trident_dx_nx IEC958", device, 1, 0, &spdif)) < 0)
2284 return err;
2285
2286 spdif->private_data = trident;
2287 spdif->private_free = snd_trident_spdif_pcm_free;
2288 if (trident->device != TRIDENT_DEVICE_ID_SI7018) {
2289 snd_pcm_set_ops(spdif, SNDRV_PCM_STREAM_PLAYBACK, &snd_trident_spdif_ops);
2290 } else {
2291 snd_pcm_set_ops(spdif, SNDRV_PCM_STREAM_PLAYBACK, &snd_trident_spdif_7018_ops);
2292 }
2293 spdif->info_flags = 0;
2294 strcpy(spdif->name, "Trident 4DWave IEC958");
2295 trident->spdif = spdif;
2296
2297 snd_pcm_lib_preallocate_pages_for_all(spdif, SNDRV_DMA_TYPE_DEV, snd_dma_pci_data(trident->pci), 64*1024, 128*1024);
2298
2299 if (rpcm)
2300 *rpcm = spdif;
2301 return 0;
2302}
2303
2304/*
2305 * Mixer part
2306 */
2307
2308
2309/*---------------------------------------------------------------------------
2310 snd_trident_spdif_control
2311
2312 Description: enable/disable S/PDIF out from ac97 mixer
2313 ---------------------------------------------------------------------------*/
2314
2315static int snd_trident_spdif_control_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
2316{
2317 uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
2318 uinfo->count = 1;
2319 uinfo->value.integer.min = 0;
2320 uinfo->value.integer.max = 1;
2321 return 0;
2322}
2323
2324static int snd_trident_spdif_control_get(snd_kcontrol_t * kcontrol,
2325 snd_ctl_elem_value_t * ucontrol)
2326{
2327 trident_t *trident = snd_kcontrol_chip(kcontrol);
2328 unsigned char val;
2329
2330 spin_lock_irq(&trident->reg_lock);
2331 val = trident->spdif_ctrl;
2332 ucontrol->value.integer.value[0] = val == kcontrol->private_value;
2333 spin_unlock_irq(&trident->reg_lock);
2334 return 0;
2335}
2336
2337static int snd_trident_spdif_control_put(snd_kcontrol_t * kcontrol,
2338 snd_ctl_elem_value_t * ucontrol)
2339{
2340 trident_t *trident = snd_kcontrol_chip(kcontrol);
2341 unsigned char val;
2342 int change;
2343
2344 val = ucontrol->value.integer.value[0] ? (unsigned char) kcontrol->private_value : 0x00;
2345 spin_lock_irq(&trident->reg_lock);
2346 /* S/PDIF C Channel bits 0-31 : 48khz, SCMS disabled */
2347 change = trident->spdif_ctrl != val;
2348 trident->spdif_ctrl = val;
2349 if (trident->device != TRIDENT_DEVICE_ID_SI7018) {
2350 if ((inb(TRID_REG(trident, NX_SPCTRL_SPCSO + 3)) & 0x10) == 0) {
2351 outl(trident->spdif_bits, TRID_REG(trident, NX_SPCSTATUS));
2352 outb(trident->spdif_ctrl, TRID_REG(trident, NX_SPCTRL_SPCSO + 3));
2353 }
2354 } else {
2355 if (trident->spdif == NULL) {
2356 unsigned int temp;
2357 outl(trident->spdif_bits, TRID_REG(trident, SI_SPDIF_CS));
2358 temp = inl(TRID_REG(trident, SI_SERIAL_INTF_CTRL)) & ~SPDIF_EN;
2359 if (val)
2360 temp |= SPDIF_EN;
2361 outl(temp, TRID_REG(trident, SI_SERIAL_INTF_CTRL));
2362 }
2363 }
2364 spin_unlock_irq(&trident->reg_lock);
2365 return change;
2366}
2367
2368static snd_kcontrol_new_t snd_trident_spdif_control __devinitdata =
2369{
2370 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2371 .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,SWITCH),
2372 .info = snd_trident_spdif_control_info,
2373 .get = snd_trident_spdif_control_get,
2374 .put = snd_trident_spdif_control_put,
2375 .private_value = 0x28,
2376};
2377
2378/*---------------------------------------------------------------------------
2379 snd_trident_spdif_default
2380
2381 Description: put/get the S/PDIF default settings
2382 ---------------------------------------------------------------------------*/
2383
2384static int snd_trident_spdif_default_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
2385{
2386 uinfo->type = SNDRV_CTL_ELEM_TYPE_IEC958;
2387 uinfo->count = 1;
2388 return 0;
2389}
2390
2391static int snd_trident_spdif_default_get(snd_kcontrol_t * kcontrol,
2392 snd_ctl_elem_value_t * ucontrol)
2393{
2394 trident_t *trident = snd_kcontrol_chip(kcontrol);
2395
2396 spin_lock_irq(&trident->reg_lock);
2397 ucontrol->value.iec958.status[0] = (trident->spdif_bits >> 0) & 0xff;
2398 ucontrol->value.iec958.status[1] = (trident->spdif_bits >> 8) & 0xff;
2399 ucontrol->value.iec958.status[2] = (trident->spdif_bits >> 16) & 0xff;
2400 ucontrol->value.iec958.status[3] = (trident->spdif_bits >> 24) & 0xff;
2401 spin_unlock_irq(&trident->reg_lock);
2402 return 0;
2403}
2404
2405static int snd_trident_spdif_default_put(snd_kcontrol_t * kcontrol,
2406 snd_ctl_elem_value_t * ucontrol)
2407{
2408 trident_t *trident = snd_kcontrol_chip(kcontrol);
2409 unsigned int val;
2410 int change;
2411
2412 val = (ucontrol->value.iec958.status[0] << 0) |
2413 (ucontrol->value.iec958.status[1] << 8) |
2414 (ucontrol->value.iec958.status[2] << 16) |
2415 (ucontrol->value.iec958.status[3] << 24);
2416 spin_lock_irq(&trident->reg_lock);
2417 change = trident->spdif_bits != val;
2418 trident->spdif_bits = val;
2419 if (trident->device != TRIDENT_DEVICE_ID_SI7018) {
2420 if ((inb(TRID_REG(trident, NX_SPCTRL_SPCSO + 3)) & 0x10) == 0)
2421 outl(trident->spdif_bits, TRID_REG(trident, NX_SPCSTATUS));
2422 } else {
2423 if (trident->spdif == NULL)
2424 outl(trident->spdif_bits, TRID_REG(trident, SI_SPDIF_CS));
2425 }
2426 spin_unlock_irq(&trident->reg_lock);
2427 return change;
2428}
2429
2430static snd_kcontrol_new_t snd_trident_spdif_default __devinitdata =
2431{
2432 .iface = SNDRV_CTL_ELEM_IFACE_PCM,
2433 .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,DEFAULT),
2434 .info = snd_trident_spdif_default_info,
2435 .get = snd_trident_spdif_default_get,
2436 .put = snd_trident_spdif_default_put
2437};
2438
2439/*---------------------------------------------------------------------------
2440 snd_trident_spdif_mask
2441
2442 Description: put/get the S/PDIF mask
2443 ---------------------------------------------------------------------------*/
2444
2445static int snd_trident_spdif_mask_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
2446{
2447 uinfo->type = SNDRV_CTL_ELEM_TYPE_IEC958;
2448 uinfo->count = 1;
2449 return 0;
2450}
2451
2452static int snd_trident_spdif_mask_get(snd_kcontrol_t * kcontrol,
2453 snd_ctl_elem_value_t * ucontrol)
2454{
2455 ucontrol->value.iec958.status[0] = 0xff;
2456 ucontrol->value.iec958.status[1] = 0xff;
2457 ucontrol->value.iec958.status[2] = 0xff;
2458 ucontrol->value.iec958.status[3] = 0xff;
2459 return 0;
2460}
2461
2462static snd_kcontrol_new_t snd_trident_spdif_mask __devinitdata =
2463{
2464 .access = SNDRV_CTL_ELEM_ACCESS_READ,
2465 .iface = SNDRV_CTL_ELEM_IFACE_PCM,
2466 .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,MASK),
2467 .info = snd_trident_spdif_mask_info,
2468 .get = snd_trident_spdif_mask_get,
2469};
2470
2471/*---------------------------------------------------------------------------
2472 snd_trident_spdif_stream
2473
2474 Description: put/get the S/PDIF stream settings
2475 ---------------------------------------------------------------------------*/
2476
2477static int snd_trident_spdif_stream_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
2478{
2479 uinfo->type = SNDRV_CTL_ELEM_TYPE_IEC958;
2480 uinfo->count = 1;
2481 return 0;
2482}
2483
2484static int snd_trident_spdif_stream_get(snd_kcontrol_t * kcontrol,
2485 snd_ctl_elem_value_t * ucontrol)
2486{
2487 trident_t *trident = snd_kcontrol_chip(kcontrol);
2488
2489 spin_lock_irq(&trident->reg_lock);
2490 ucontrol->value.iec958.status[0] = (trident->spdif_pcm_bits >> 0) & 0xff;
2491 ucontrol->value.iec958.status[1] = (trident->spdif_pcm_bits >> 8) & 0xff;
2492 ucontrol->value.iec958.status[2] = (trident->spdif_pcm_bits >> 16) & 0xff;
2493 ucontrol->value.iec958.status[3] = (trident->spdif_pcm_bits >> 24) & 0xff;
2494 spin_unlock_irq(&trident->reg_lock);
2495 return 0;
2496}
2497
2498static int snd_trident_spdif_stream_put(snd_kcontrol_t * kcontrol,
2499 snd_ctl_elem_value_t * ucontrol)
2500{
2501 trident_t *trident = snd_kcontrol_chip(kcontrol);
2502 unsigned int val;
2503 int change;
2504
2505 val = (ucontrol->value.iec958.status[0] << 0) |
2506 (ucontrol->value.iec958.status[1] << 8) |
2507 (ucontrol->value.iec958.status[2] << 16) |
2508 (ucontrol->value.iec958.status[3] << 24);
2509 spin_lock_irq(&trident->reg_lock);
2510 change = trident->spdif_pcm_bits != val;
2511 trident->spdif_pcm_bits = val;
2512 if (trident->spdif != NULL) {
2513 if (trident->device != TRIDENT_DEVICE_ID_SI7018) {
2514 outl(trident->spdif_pcm_bits, TRID_REG(trident, NX_SPCSTATUS));
2515 } else {
2516 outl(trident->spdif_bits, TRID_REG(trident, SI_SPDIF_CS));
2517 }
2518 }
2519 spin_unlock_irq(&trident->reg_lock);
2520 return change;
2521}
2522
2523static snd_kcontrol_new_t snd_trident_spdif_stream __devinitdata =
2524{
2525 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | SNDRV_CTL_ELEM_ACCESS_INACTIVE,
2526 .iface = SNDRV_CTL_ELEM_IFACE_PCM,
2527 .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,PCM_STREAM),
2528 .info = snd_trident_spdif_stream_info,
2529 .get = snd_trident_spdif_stream_get,
2530 .put = snd_trident_spdif_stream_put
2531};
2532
2533/*---------------------------------------------------------------------------
2534 snd_trident_ac97_control
2535
2536 Description: enable/disable rear path for ac97
2537 ---------------------------------------------------------------------------*/
2538
2539static int snd_trident_ac97_control_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
2540{
2541 uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
2542 uinfo->count = 1;
2543 uinfo->value.integer.min = 0;
2544 uinfo->value.integer.max = 1;
2545 return 0;
2546}
2547
2548static int snd_trident_ac97_control_get(snd_kcontrol_t * kcontrol,
2549 snd_ctl_elem_value_t * ucontrol)
2550{
2551 trident_t *trident = snd_kcontrol_chip(kcontrol);
2552 unsigned char val;
2553
2554 spin_lock_irq(&trident->reg_lock);
2555 val = trident->ac97_ctrl = inl(TRID_REG(trident, NX_ACR0_AC97_COM_STAT));
2556 ucontrol->value.integer.value[0] = (val & (1 << kcontrol->private_value)) ? 1 : 0;
2557 spin_unlock_irq(&trident->reg_lock);
2558 return 0;
2559}
2560
2561static int snd_trident_ac97_control_put(snd_kcontrol_t * kcontrol,
2562 snd_ctl_elem_value_t * ucontrol)
2563{
2564 trident_t *trident = snd_kcontrol_chip(kcontrol);
2565 unsigned char val;
2566 int change = 0;
2567
2568 spin_lock_irq(&trident->reg_lock);
2569 val = trident->ac97_ctrl = inl(TRID_REG(trident, NX_ACR0_AC97_COM_STAT));
2570 val &= ~(1 << kcontrol->private_value);
2571 if (ucontrol->value.integer.value[0])
2572 val |= 1 << kcontrol->private_value;
2573 change = val != trident->ac97_ctrl;
2574 trident->ac97_ctrl = val;
2575 outl(trident->ac97_ctrl = val, TRID_REG(trident, NX_ACR0_AC97_COM_STAT));
2576 spin_unlock_irq(&trident->reg_lock);
2577 return change;
2578}
2579
2580static snd_kcontrol_new_t snd_trident_ac97_rear_control __devinitdata =
2581{
2582 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2583 .name = "Rear Path",
2584 .info = snd_trident_ac97_control_info,
2585 .get = snd_trident_ac97_control_get,
2586 .put = snd_trident_ac97_control_put,
2587 .private_value = 4,
2588};
2589
2590/*---------------------------------------------------------------------------
2591 snd_trident_vol_control
2592
2593 Description: wave & music volume control
2594 ---------------------------------------------------------------------------*/
2595
2596static int snd_trident_vol_control_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
2597{
2598 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
2599 uinfo->count = 2;
2600 uinfo->value.integer.min = 0;
2601 uinfo->value.integer.max = 255;
2602 return 0;
2603}
2604
2605static int snd_trident_vol_control_get(snd_kcontrol_t * kcontrol,
2606 snd_ctl_elem_value_t * ucontrol)
2607{
2608 trident_t *trident = snd_kcontrol_chip(kcontrol);
2609 unsigned int val;
2610
2611 val = trident->musicvol_wavevol;
2612 ucontrol->value.integer.value[0] = 255 - ((val >> kcontrol->private_value) & 0xff);
2613 ucontrol->value.integer.value[1] = 255 - ((val >> (kcontrol->private_value + 8)) & 0xff);
2614 return 0;
2615}
2616
2617static int snd_trident_vol_control_put(snd_kcontrol_t * kcontrol,
2618 snd_ctl_elem_value_t * ucontrol)
2619{
2620 trident_t *trident = snd_kcontrol_chip(kcontrol);
2621 unsigned int val;
2622 int change = 0;
2623
2624 spin_lock_irq(&trident->reg_lock);
2625 val = trident->musicvol_wavevol;
2626 val &= ~(0xffff << kcontrol->private_value);
2627 val |= ((255 - (ucontrol->value.integer.value[0] & 0xff)) |
2628 ((255 - (ucontrol->value.integer.value[1] & 0xff)) << 8)) << kcontrol->private_value;
2629 change = val != trident->musicvol_wavevol;
2630 outl(trident->musicvol_wavevol = val, TRID_REG(trident, T4D_MUSICVOL_WAVEVOL));
2631 spin_unlock_irq(&trident->reg_lock);
2632 return change;
2633}
2634
2635static snd_kcontrol_new_t snd_trident_vol_music_control __devinitdata =
2636{
2637 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2638 .name = "Music Playback Volume",
2639 .info = snd_trident_vol_control_info,
2640 .get = snd_trident_vol_control_get,
2641 .put = snd_trident_vol_control_put,
2642 .private_value = 16,
2643};
2644
2645static snd_kcontrol_new_t snd_trident_vol_wave_control __devinitdata =
2646{
2647 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2648 .name = "Wave Playback Volume",
2649 .info = snd_trident_vol_control_info,
2650 .get = snd_trident_vol_control_get,
2651 .put = snd_trident_vol_control_put,
2652 .private_value = 0,
2653};
2654
2655/*---------------------------------------------------------------------------
2656 snd_trident_pcm_vol_control
2657
2658 Description: PCM front volume control
2659 ---------------------------------------------------------------------------*/
2660
2661static int snd_trident_pcm_vol_control_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
2662{
2663 trident_t *trident = snd_kcontrol_chip(kcontrol);
2664
2665 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
2666 uinfo->count = 1;
2667 uinfo->value.integer.min = 0;
2668 uinfo->value.integer.max = 255;
2669 if (trident->device == TRIDENT_DEVICE_ID_SI7018)
2670 uinfo->value.integer.max = 1023;
2671 return 0;
2672}
2673
2674static int snd_trident_pcm_vol_control_get(snd_kcontrol_t * kcontrol,
2675 snd_ctl_elem_value_t * ucontrol)
2676{
2677 trident_t *trident = snd_kcontrol_chip(kcontrol);
2678 snd_trident_pcm_mixer_t *mix = &trident->pcm_mixer[snd_ctl_get_ioffnum(kcontrol, &ucontrol->id)];
2679
2680 if (trident->device == TRIDENT_DEVICE_ID_SI7018) {
2681 ucontrol->value.integer.value[0] = 1023 - mix->vol;
2682 } else {
2683 ucontrol->value.integer.value[0] = 255 - (mix->vol>>2);
2684 }
2685 return 0;
2686}
2687
2688static int snd_trident_pcm_vol_control_put(snd_kcontrol_t * kcontrol,
2689 snd_ctl_elem_value_t * ucontrol)
2690{
2691 trident_t *trident = snd_kcontrol_chip(kcontrol);
2692 snd_trident_pcm_mixer_t *mix = &trident->pcm_mixer[snd_ctl_get_ioffnum(kcontrol, &ucontrol->id)];
2693 unsigned int val;
2694 int change = 0;
2695
2696 if (trident->device == TRIDENT_DEVICE_ID_SI7018) {
2697 val = 1023 - (ucontrol->value.integer.value[0] & 1023);
2698 } else {
2699 val = (255 - (ucontrol->value.integer.value[0] & 255)) << 2;
2700 }
2701 spin_lock_irq(&trident->reg_lock);
2702 change = val != mix->vol;
2703 mix->vol = val;
2704 if (mix->voice != NULL)
2705 snd_trident_write_vol_reg(trident, mix->voice, val);
2706 spin_unlock_irq(&trident->reg_lock);
2707 return change;
2708}
2709
2710static snd_kcontrol_new_t snd_trident_pcm_vol_control __devinitdata =
2711{
2712 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2713 .name = "PCM Front Playback Volume",
2714 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | SNDRV_CTL_ELEM_ACCESS_INACTIVE,
2715 .count = 32,
2716 .info = snd_trident_pcm_vol_control_info,
2717 .get = snd_trident_pcm_vol_control_get,
2718 .put = snd_trident_pcm_vol_control_put,
2719};
2720
2721/*---------------------------------------------------------------------------
2722 snd_trident_pcm_pan_control
2723
2724 Description: PCM front pan control
2725 ---------------------------------------------------------------------------*/
2726
2727static int snd_trident_pcm_pan_control_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
2728{
2729 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
2730 uinfo->count = 1;
2731 uinfo->value.integer.min = 0;
2732 uinfo->value.integer.max = 127;
2733 return 0;
2734}
2735
2736static int snd_trident_pcm_pan_control_get(snd_kcontrol_t * kcontrol,
2737 snd_ctl_elem_value_t * ucontrol)
2738{
2739 trident_t *trident = snd_kcontrol_chip(kcontrol);
2740 snd_trident_pcm_mixer_t *mix = &trident->pcm_mixer[snd_ctl_get_ioffnum(kcontrol, &ucontrol->id)];
2741
2742 ucontrol->value.integer.value[0] = mix->pan;
2743 if (ucontrol->value.integer.value[0] & 0x40) {
2744 ucontrol->value.integer.value[0] = (0x3f - (ucontrol->value.integer.value[0] & 0x3f));
2745 } else {
2746 ucontrol->value.integer.value[0] |= 0x40;
2747 }
2748 return 0;
2749}
2750
2751static int snd_trident_pcm_pan_control_put(snd_kcontrol_t * kcontrol,
2752 snd_ctl_elem_value_t * ucontrol)
2753{
2754 trident_t *trident = snd_kcontrol_chip(kcontrol);
2755 snd_trident_pcm_mixer_t *mix = &trident->pcm_mixer[snd_ctl_get_ioffnum(kcontrol, &ucontrol->id)];
2756 unsigned char val;
2757 int change = 0;
2758
2759 if (ucontrol->value.integer.value[0] & 0x40)
2760 val = ucontrol->value.integer.value[0] & 0x3f;
2761 else
2762 val = (0x3f - (ucontrol->value.integer.value[0] & 0x3f)) | 0x40;
2763 spin_lock_irq(&trident->reg_lock);
2764 change = val != mix->pan;
2765 mix->pan = val;
2766 if (mix->voice != NULL)
2767 snd_trident_write_pan_reg(trident, mix->voice, val);
2768 spin_unlock_irq(&trident->reg_lock);
2769 return change;
2770}
2771
2772static snd_kcontrol_new_t snd_trident_pcm_pan_control __devinitdata =
2773{
2774 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2775 .name = "PCM Pan Playback Control",
2776 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | SNDRV_CTL_ELEM_ACCESS_INACTIVE,
2777 .count = 32,
2778 .info = snd_trident_pcm_pan_control_info,
2779 .get = snd_trident_pcm_pan_control_get,
2780 .put = snd_trident_pcm_pan_control_put,
2781};
2782
2783/*---------------------------------------------------------------------------
2784 snd_trident_pcm_rvol_control
2785
2786 Description: PCM reverb volume control
2787 ---------------------------------------------------------------------------*/
2788
2789static int snd_trident_pcm_rvol_control_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
2790{
2791 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
2792 uinfo->count = 1;
2793 uinfo->value.integer.min = 0;
2794 uinfo->value.integer.max = 127;
2795 return 0;
2796}
2797
2798static int snd_trident_pcm_rvol_control_get(snd_kcontrol_t * kcontrol,
2799 snd_ctl_elem_value_t * ucontrol)
2800{
2801 trident_t *trident = snd_kcontrol_chip(kcontrol);
2802 snd_trident_pcm_mixer_t *mix = &trident->pcm_mixer[snd_ctl_get_ioffnum(kcontrol, &ucontrol->id)];
2803
2804 ucontrol->value.integer.value[0] = 127 - mix->rvol;
2805 return 0;
2806}
2807
2808static int snd_trident_pcm_rvol_control_put(snd_kcontrol_t * kcontrol,
2809 snd_ctl_elem_value_t * ucontrol)
2810{
2811 trident_t *trident = snd_kcontrol_chip(kcontrol);
2812 snd_trident_pcm_mixer_t *mix = &trident->pcm_mixer[snd_ctl_get_ioffnum(kcontrol, &ucontrol->id)];
2813 unsigned short val;
2814 int change = 0;
2815
2816 val = 0x7f - (ucontrol->value.integer.value[0] & 0x7f);
2817 spin_lock_irq(&trident->reg_lock);
2818 change = val != mix->rvol;
2819 mix->rvol = val;
2820 if (mix->voice != NULL)
2821 snd_trident_write_rvol_reg(trident, mix->voice, val);
2822 spin_unlock_irq(&trident->reg_lock);
2823 return change;
2824}
2825
2826static snd_kcontrol_new_t snd_trident_pcm_rvol_control __devinitdata =
2827{
2828 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2829 .name = "PCM Reverb Playback Volume",
2830 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | SNDRV_CTL_ELEM_ACCESS_INACTIVE,
2831 .count = 32,
2832 .info = snd_trident_pcm_rvol_control_info,
2833 .get = snd_trident_pcm_rvol_control_get,
2834 .put = snd_trident_pcm_rvol_control_put,
2835};
2836
2837/*---------------------------------------------------------------------------
2838 snd_trident_pcm_cvol_control
2839
2840 Description: PCM chorus volume control
2841 ---------------------------------------------------------------------------*/
2842
2843static int snd_trident_pcm_cvol_control_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
2844{
2845 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
2846 uinfo->count = 1;
2847 uinfo->value.integer.min = 0;
2848 uinfo->value.integer.max = 127;
2849 return 0;
2850}
2851
2852static int snd_trident_pcm_cvol_control_get(snd_kcontrol_t * kcontrol,
2853 snd_ctl_elem_value_t * ucontrol)
2854{
2855 trident_t *trident = snd_kcontrol_chip(kcontrol);
2856 snd_trident_pcm_mixer_t *mix = &trident->pcm_mixer[snd_ctl_get_ioffnum(kcontrol, &ucontrol->id)];
2857
2858 ucontrol->value.integer.value[0] = 127 - mix->cvol;
2859 return 0;
2860}
2861
2862static int snd_trident_pcm_cvol_control_put(snd_kcontrol_t * kcontrol,
2863 snd_ctl_elem_value_t * ucontrol)
2864{
2865 trident_t *trident = snd_kcontrol_chip(kcontrol);
2866 snd_trident_pcm_mixer_t *mix = &trident->pcm_mixer[snd_ctl_get_ioffnum(kcontrol, &ucontrol->id)];
2867 unsigned short val;
2868 int change = 0;
2869
2870 val = 0x7f - (ucontrol->value.integer.value[0] & 0x7f);
2871 spin_lock_irq(&trident->reg_lock);
2872 change = val != mix->cvol;
2873 mix->cvol = val;
2874 if (mix->voice != NULL)
2875 snd_trident_write_cvol_reg(trident, mix->voice, val);
2876 spin_unlock_irq(&trident->reg_lock);
2877 return change;
2878}
2879
2880static snd_kcontrol_new_t snd_trident_pcm_cvol_control __devinitdata =
2881{
2882 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2883 .name = "PCM Chorus Playback Volume",
2884 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | SNDRV_CTL_ELEM_ACCESS_INACTIVE,
2885 .count = 32,
2886 .info = snd_trident_pcm_cvol_control_info,
2887 .get = snd_trident_pcm_cvol_control_get,
2888 .put = snd_trident_pcm_cvol_control_put,
2889};
2890
2891static void snd_trident_notify_pcm_change1(snd_card_t * card, snd_kcontrol_t *kctl, int num, int activate)
2892{
2893 snd_ctl_elem_id_t id;
2894
2895 snd_runtime_check(kctl != NULL, return);
2896 if (activate)
2897 kctl->vd[num].access &= ~SNDRV_CTL_ELEM_ACCESS_INACTIVE;
2898 else
2899 kctl->vd[num].access |= SNDRV_CTL_ELEM_ACCESS_INACTIVE;
2900 snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_VALUE |
2901 SNDRV_CTL_EVENT_MASK_INFO,
2902 snd_ctl_build_ioff(&id, kctl, num));
2903}
2904
2905static void snd_trident_notify_pcm_change(trident_t *trident, snd_trident_pcm_mixer_t *tmix, int num, int activate)
2906{
2907 snd_trident_notify_pcm_change1(trident->card, trident->ctl_vol, num, activate);
2908 snd_trident_notify_pcm_change1(trident->card, trident->ctl_pan, num, activate);
2909 snd_trident_notify_pcm_change1(trident->card, trident->ctl_rvol, num, activate);
2910 snd_trident_notify_pcm_change1(trident->card, trident->ctl_cvol, num, activate);
2911}
2912
2913static int snd_trident_pcm_mixer_build(trident_t *trident, snd_trident_voice_t *voice, snd_pcm_substream_t *substream)
2914{
2915 snd_trident_pcm_mixer_t *tmix;
2916
2917 snd_assert(trident != NULL && voice != NULL && substream != NULL, return -EINVAL);
2918 tmix = &trident->pcm_mixer[substream->number];
2919 tmix->voice = voice;
2920 tmix->vol = T4D_DEFAULT_PCM_VOL;
2921 tmix->pan = T4D_DEFAULT_PCM_PAN;
2922 tmix->rvol = T4D_DEFAULT_PCM_RVOL;
2923 tmix->cvol = T4D_DEFAULT_PCM_CVOL;
2924 snd_trident_notify_pcm_change(trident, tmix, substream->number, 1);
2925 return 0;
2926}
2927
2928static int snd_trident_pcm_mixer_free(trident_t *trident, snd_trident_voice_t *voice, snd_pcm_substream_t *substream)
2929{
2930 snd_trident_pcm_mixer_t *tmix;
2931
2932 snd_assert(trident != NULL && substream != NULL, return -EINVAL);
2933 tmix = &trident->pcm_mixer[substream->number];
2934 tmix->voice = NULL;
2935 snd_trident_notify_pcm_change(trident, tmix, substream->number, 0);
2936 return 0;
2937}
2938
2939/*---------------------------------------------------------------------------
2940 snd_trident_mixer
2941
2942 Description: This routine registers the 4DWave device for mixer support.
2943
2944 Paramters: trident - pointer to target device class for 4DWave.
2945
2946 Returns: None
2947
2948 ---------------------------------------------------------------------------*/
2949
2950static int __devinit snd_trident_mixer(trident_t * trident, int pcm_spdif_device)
2951{
2952 ac97_template_t _ac97;
2953 snd_card_t * card = trident->card;
2954 snd_kcontrol_t *kctl;
2955 snd_ctl_elem_value_t *uctl;
2956 int idx, err, retries = 2;
2957 static ac97_bus_ops_t ops = {
2958 .write = snd_trident_codec_write,
2959 .read = snd_trident_codec_read,
2960 };
2961
2962 uctl = kcalloc(1, sizeof(*uctl), GFP_KERNEL);
2963 if (!uctl)
2964 return -ENOMEM;
2965
2966 if ((err = snd_ac97_bus(trident->card, 0, &ops, NULL, &trident->ac97_bus)) < 0)
2967 goto __out;
2968
2969 memset(&_ac97, 0, sizeof(_ac97));
2970 _ac97.private_data = trident;
2971 trident->ac97_detect = 1;
2972
2973 __again:
2974 if ((err = snd_ac97_mixer(trident->ac97_bus, &_ac97, &trident->ac97)) < 0) {
2975 if (trident->device == TRIDENT_DEVICE_ID_SI7018) {
2976 if ((err = snd_trident_sis_reset(trident)) < 0)
2977 goto __out;
2978 if (retries-- > 0)
2979 goto __again;
2980 err = -EIO;
2981 }
2982 goto __out;
2983 }
2984
2985 /* secondary codec? */
2986 if (trident->device == TRIDENT_DEVICE_ID_SI7018 &&
2987 (inl(TRID_REG(trident, SI_SERIAL_INTF_CTRL)) & SI_AC97_PRIMARY_READY) != 0) {
2988 _ac97.num = 1;
2989 err = snd_ac97_mixer(trident->ac97_bus, &_ac97, &trident->ac97_sec);
2990 if (err < 0)
2991 snd_printk("SI7018: the secondary codec - invalid access\n");
2992#if 0 // only for my testing purpose --jk
2993 {
2994 ac97_t *mc97;
2995 err = snd_ac97_modem(trident->card, &_ac97, &mc97);
2996 if (err < 0)
2997 snd_printk("snd_ac97_modem returned error %i\n", err);
2998 }
2999#endif
3000 }
3001
3002 trident->ac97_detect = 0;
3003
3004 if (trident->device != TRIDENT_DEVICE_ID_SI7018) {
3005 if ((err = snd_ctl_add(card, kctl = snd_ctl_new1(&snd_trident_vol_wave_control, trident))) < 0)
3006 goto __out;
3007 kctl->put(kctl, uctl);
3008 if ((err = snd_ctl_add(card, kctl = snd_ctl_new1(&snd_trident_vol_music_control, trident))) < 0)
3009 goto __out;
3010 kctl->put(kctl, uctl);
3011 outl(trident->musicvol_wavevol = 0x00000000, TRID_REG(trident, T4D_MUSICVOL_WAVEVOL));
3012 } else {
3013 outl(trident->musicvol_wavevol = 0xffff0000, TRID_REG(trident, T4D_MUSICVOL_WAVEVOL));
3014 }
3015
3016 for (idx = 0; idx < 32; idx++) {
3017 snd_trident_pcm_mixer_t *tmix;
3018
3019 tmix = &trident->pcm_mixer[idx];
3020 tmix->voice = NULL;
3021 }
3022 if ((trident->ctl_vol = snd_ctl_new1(&snd_trident_pcm_vol_control, trident)) == NULL)
3023 goto __nomem;
3024 if ((err = snd_ctl_add(card, trident->ctl_vol)))
3025 goto __out;
3026
3027 if ((trident->ctl_pan = snd_ctl_new1(&snd_trident_pcm_pan_control, trident)) == NULL)
3028 goto __nomem;
3029 if ((err = snd_ctl_add(card, trident->ctl_pan)))
3030 goto __out;
3031
3032 if ((trident->ctl_rvol = snd_ctl_new1(&snd_trident_pcm_rvol_control, trident)) == NULL)
3033 goto __nomem;
3034 if ((err = snd_ctl_add(card, trident->ctl_rvol)))
3035 goto __out;
3036
3037 if ((trident->ctl_cvol = snd_ctl_new1(&snd_trident_pcm_cvol_control, trident)) == NULL)
3038 goto __nomem;
3039 if ((err = snd_ctl_add(card, trident->ctl_cvol)))
3040 goto __out;
3041
3042 if (trident->device == TRIDENT_DEVICE_ID_NX) {
3043 if ((err = snd_ctl_add(card, kctl = snd_ctl_new1(&snd_trident_ac97_rear_control, trident))) < 0)
3044 goto __out;
3045 kctl->put(kctl, uctl);
3046 }
3047 if (trident->device == TRIDENT_DEVICE_ID_NX || trident->device == TRIDENT_DEVICE_ID_SI7018) {
3048
3049 kctl = snd_ctl_new1(&snd_trident_spdif_control, trident);
3050 if (kctl == NULL) {
3051 err = -ENOMEM;
3052 goto __out;
3053 }
3054 if (trident->ac97->ext_id & AC97_EI_SPDIF)
3055 kctl->id.index++;
3056 if (trident->ac97_sec && (trident->ac97_sec->ext_id & AC97_EI_SPDIF))
3057 kctl->id.index++;
3058 idx = kctl->id.index;
3059 if ((err = snd_ctl_add(card, kctl)) < 0)
3060 goto __out;
3061 kctl->put(kctl, uctl);
3062
3063 kctl = snd_ctl_new1(&snd_trident_spdif_default, trident);
3064 if (kctl == NULL) {
3065 err = -ENOMEM;
3066 goto __out;
3067 }
3068 kctl->id.index = idx;
3069 kctl->id.device = pcm_spdif_device;
3070 if ((err = snd_ctl_add(card, kctl)) < 0)
3071 goto __out;
3072
3073 kctl = snd_ctl_new1(&snd_trident_spdif_mask, trident);
3074 if (kctl == NULL) {
3075 err = -ENOMEM;
3076 goto __out;
3077 }
3078 kctl->id.index = idx;
3079 kctl->id.device = pcm_spdif_device;
3080 if ((err = snd_ctl_add(card, kctl)) < 0)
3081 goto __out;
3082
3083 kctl = snd_ctl_new1(&snd_trident_spdif_stream, trident);
3084 if (kctl == NULL) {
3085 err = -ENOMEM;
3086 goto __out;
3087 }
3088 kctl->id.index = idx;
3089 kctl->id.device = pcm_spdif_device;
3090 if ((err = snd_ctl_add(card, kctl)) < 0)
3091 goto __out;
3092 trident->spdif_pcm_ctl = kctl;
3093 }
3094
3095 err = 0;
3096 goto __out;
3097
3098 __nomem:
3099 err = -ENOMEM;
3100
3101 __out:
3102 kfree(uctl);
3103
3104 return err;
3105}
3106
3107/*
3108 * gameport interface
3109 */
3110
3111#if defined(CONFIG_GAMEPORT) || (defined(MODULE) && defined(CONFIG_GAMEPORT_MODULE))
3112
3113static unsigned char snd_trident_gameport_read(struct gameport *gameport)
3114{
3115 trident_t *chip = gameport_get_port_data(gameport);
3116
3117 snd_assert(chip, return 0);
3118 return inb(TRID_REG(chip, GAMEPORT_LEGACY));
3119}
3120
3121static void snd_trident_gameport_trigger(struct gameport *gameport)
3122{
3123 trident_t *chip = gameport_get_port_data(gameport);
3124
3125 snd_assert(chip, return);
3126 outb(0xff, TRID_REG(chip, GAMEPORT_LEGACY));
3127}
3128
3129static int snd_trident_gameport_cooked_read(struct gameport *gameport, int *axes, int *buttons)
3130{
3131 trident_t *chip = gameport_get_port_data(gameport);
3132 int i;
3133
3134 snd_assert(chip, return 0);
3135
3136 *buttons = (~inb(TRID_REG(chip, GAMEPORT_LEGACY)) >> 4) & 0xf;
3137
3138 for (i = 0; i < 4; i++) {
3139 axes[i] = inw(TRID_REG(chip, GAMEPORT_AXES + i * 2));
3140 if (axes[i] == 0xffff) axes[i] = -1;
3141 }
3142
3143 return 0;
3144}
3145
3146static int snd_trident_gameport_open(struct gameport *gameport, int mode)
3147{
3148 trident_t *chip = gameport_get_port_data(gameport);
3149
3150 snd_assert(chip, return 0);
3151
3152 switch (mode) {
3153 case GAMEPORT_MODE_COOKED:
3154 outb(GAMEPORT_MODE_ADC, TRID_REG(chip, GAMEPORT_GCR));
3155 set_current_state(TASK_UNINTERRUPTIBLE);
3156 schedule_timeout(1 + 20 * HZ / 1000); /* 20msec */
3157 return 0;
3158 case GAMEPORT_MODE_RAW:
3159 outb(0, TRID_REG(chip, GAMEPORT_GCR));
3160 return 0;
3161 default:
3162 return -1;
3163 }
3164}
3165
3166int __devinit snd_trident_create_gameport(trident_t *chip)
3167{
3168 struct gameport *gp;
3169
3170 chip->gameport = gp = gameport_allocate_port();
3171 if (!gp) {
3172 printk(KERN_ERR "trident: cannot allocate memory for gameport\n");
3173 return -ENOMEM;
3174 }
3175
3176 gameport_set_name(gp, "Trident 4DWave");
3177 gameport_set_phys(gp, "pci%s/gameport0", pci_name(chip->pci));
3178 gameport_set_dev_parent(gp, &chip->pci->dev);
3179
3180 gameport_set_port_data(gp, chip);
3181 gp->fuzz = 64;
3182 gp->read = snd_trident_gameport_read;
3183 gp->trigger = snd_trident_gameport_trigger;
3184 gp->cooked_read = snd_trident_gameport_cooked_read;
3185 gp->open = snd_trident_gameport_open;
3186
3187 gameport_register_port(gp);
3188
3189 return 0;
3190}
3191
3192static inline void snd_trident_free_gameport(trident_t *chip)
3193{
3194 if (chip->gameport) {
3195 gameport_unregister_port(chip->gameport);
3196 chip->gameport = NULL;
3197 }
3198}
3199#else
3200int __devinit snd_trident_create_gameport(trident_t *chip) { return -ENOSYS; }
3201static inline void snd_trident_free_gameport(trident_t *chip) { }
3202#endif /* CONFIG_GAMEPORT */
3203
3204/*
3205 * delay for 1 tick
3206 */
3207inline static void do_delay(trident_t *chip)
3208{
3209 set_current_state(TASK_UNINTERRUPTIBLE);
3210 schedule_timeout(1);
3211}
3212
3213/*
3214 * SiS reset routine
3215 */
3216
3217static int snd_trident_sis_reset(trident_t *trident)
3218{
3219 unsigned long end_time;
3220 unsigned int i;
3221 int r;
3222
3223 r = trident->in_suspend ? 0 : 2; /* count of retries */
3224 __si7018_retry:
3225 pci_write_config_byte(trident->pci, 0x46, 0x04); /* SOFTWARE RESET */
3226 udelay(100);
3227 pci_write_config_byte(trident->pci, 0x46, 0x00);
3228 udelay(100);
3229 /* disable AC97 GPIO interrupt */
3230 outb(0x00, TRID_REG(trident, SI_AC97_GPIO));
3231 /* initialize serial interface, force cold reset */
3232 i = PCMOUT|SURROUT|CENTEROUT|LFEOUT|SECONDARY_ID|COLD_RESET;
3233 outl(i, TRID_REG(trident, SI_SERIAL_INTF_CTRL));
3234 udelay(1000);
3235 /* remove cold reset */
3236 i &= ~COLD_RESET;
3237 outl(i, TRID_REG(trident, SI_SERIAL_INTF_CTRL));
3238 udelay(2000);
3239 /* wait, until the codec is ready */
3240 end_time = (jiffies + (HZ * 3) / 4) + 1;
3241 do {
3242 if ((inl(TRID_REG(trident, SI_SERIAL_INTF_CTRL)) & SI_AC97_PRIMARY_READY) != 0)
3243 goto __si7018_ok;
3244 do_delay(trident);
3245 } while (time_after_eq(end_time, jiffies));
3246 snd_printk("AC'97 codec ready error [0x%x]\n", inl(TRID_REG(trident, SI_SERIAL_INTF_CTRL)));
3247 if (r-- > 0) {
3248 end_time = jiffies + HZ;
3249 do {
3250 do_delay(trident);
3251 } while (time_after_eq(end_time, jiffies));
3252 goto __si7018_retry;
3253 }
3254 __si7018_ok:
3255 /* wait for the second codec */
3256 do {
3257 if ((inl(TRID_REG(trident, SI_SERIAL_INTF_CTRL)) & SI_AC97_SECONDARY_READY) != 0)
3258 break;
3259 do_delay(trident);
3260 } while (time_after_eq(end_time, jiffies));
3261 /* enable 64 channel mode */
3262 outl(BANK_B_EN, TRID_REG(trident, T4D_LFO_GC_CIR));
3263 return 0;
3264}
3265
3266/*
3267 * /proc interface
3268 */
3269
3270static void snd_trident_proc_read(snd_info_entry_t *entry,
3271 snd_info_buffer_t * buffer)
3272{
3273 trident_t *trident = entry->private_data;
3274 char *s;
3275
3276 switch (trident->device) {
3277 case TRIDENT_DEVICE_ID_SI7018:
3278 s = "SiS 7018 Audio";
3279 break;
3280 case TRIDENT_DEVICE_ID_DX:
3281 s = "Trident 4DWave PCI DX";
3282 break;
3283 case TRIDENT_DEVICE_ID_NX:
3284 s = "Trident 4DWave PCI NX";
3285 break;
3286 default:
3287 s = "???";
3288 }
3289 snd_iprintf(buffer, "%s\n\n", s);
3290 snd_iprintf(buffer, "Spurious IRQs : %d\n", trident->spurious_irq_count);
3291 snd_iprintf(buffer, "Spurious IRQ dlta: %d\n", trident->spurious_irq_max_delta);
3292 if (trident->device == TRIDENT_DEVICE_ID_NX || trident->device == TRIDENT_DEVICE_ID_SI7018)
3293 snd_iprintf(buffer, "IEC958 Mixer Out : %s\n", trident->spdif_ctrl == 0x28 ? "on" : "off");
3294 if (trident->device == TRIDENT_DEVICE_ID_NX) {
3295 snd_iprintf(buffer, "Rear Speakers : %s\n", trident->ac97_ctrl & 0x00000010 ? "on" : "off");
3296 if (trident->tlb.entries) {
3297 snd_iprintf(buffer,"\nVirtual Memory\n");
3298 snd_iprintf(buffer, "Memory Maximum : %d\n", trident->tlb.memhdr->size);
3299 snd_iprintf(buffer, "Memory Used : %d\n", trident->tlb.memhdr->used);
3300 snd_iprintf(buffer, "Memory Free : %d\n", snd_util_mem_avail(trident->tlb.memhdr));
3301 }
3302 }
3303#if defined(CONFIG_SND_SEQUENCER) || (defined(MODULE) && defined(CONFIG_SND_SEQUENCER_MODULE))
3304 snd_iprintf(buffer,"\nWavetable Synth\n");
3305 snd_iprintf(buffer, "Memory Maximum : %d\n", trident->synth.max_size);
3306 snd_iprintf(buffer, "Memory Used : %d\n", trident->synth.current_size);
3307 snd_iprintf(buffer, "Memory Free : %d\n", (trident->synth.max_size-trident->synth.current_size));
3308#endif
3309}
3310
3311static void __devinit snd_trident_proc_init(trident_t * trident)
3312{
3313 snd_info_entry_t *entry;
3314 const char *s = "trident";
3315
3316 if (trident->device == TRIDENT_DEVICE_ID_SI7018)
3317 s = "sis7018";
3318 if (! snd_card_proc_new(trident->card, s, &entry))
3319 snd_info_set_text_ops(entry, trident, 1024, snd_trident_proc_read);
3320}
3321
3322static int snd_trident_dev_free(snd_device_t *device)
3323{
3324 trident_t *trident = device->device_data;
3325 return snd_trident_free(trident);
3326}
3327
3328/*---------------------------------------------------------------------------
3329 snd_trident_tlb_alloc
3330
3331 Description: Allocate and set up the TLB page table on 4D NX.
3332 Each entry has 4 bytes (physical PCI address).
3333
3334 Paramters: trident - pointer to target device class for 4DWave.
3335
3336 Returns: 0 or negative error code
3337
3338 ---------------------------------------------------------------------------*/
3339
3340static int __devinit snd_trident_tlb_alloc(trident_t *trident)
3341{
3342 int i;
3343
3344 /* TLB array must be aligned to 16kB !!! so we allocate
3345 32kB region and correct offset when necessary */
3346
3347 if (snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, snd_dma_pci_data(trident->pci),
3348 2 * SNDRV_TRIDENT_MAX_PAGES * 4, &trident->tlb.buffer) < 0) {
3349 snd_printk(KERN_ERR "trident: unable to allocate TLB buffer\n");
3350 return -ENOMEM;
3351 }
3352 trident->tlb.entries = (unsigned int*)(((unsigned long)trident->tlb.buffer.area + SNDRV_TRIDENT_MAX_PAGES * 4 - 1) & ~(SNDRV_TRIDENT_MAX_PAGES * 4 - 1));
3353 trident->tlb.entries_dmaaddr = (trident->tlb.buffer.addr + SNDRV_TRIDENT_MAX_PAGES * 4 - 1) & ~(SNDRV_TRIDENT_MAX_PAGES * 4 - 1);
3354 /* allocate shadow TLB page table (virtual addresses) */
3355 trident->tlb.shadow_entries = (unsigned long *)vmalloc(SNDRV_TRIDENT_MAX_PAGES*sizeof(unsigned long));
3356 if (trident->tlb.shadow_entries == NULL) {
3357 snd_printk(KERN_ERR "trident: unable to allocate shadow TLB entries\n");
3358 return -ENOMEM;
3359 }
3360 /* allocate and setup silent page and initialise TLB entries */
3361 if (snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, snd_dma_pci_data(trident->pci),
3362 SNDRV_TRIDENT_PAGE_SIZE, &trident->tlb.silent_page) < 0) {
3363 snd_printk(KERN_ERR "trident: unable to allocate silent page\n");
3364 return -ENOMEM;
3365 }
3366 memset(trident->tlb.silent_page.area, 0, SNDRV_TRIDENT_PAGE_SIZE);
3367 for (i = 0; i < SNDRV_TRIDENT_MAX_PAGES; i++) {
3368 trident->tlb.entries[i] = cpu_to_le32(trident->tlb.silent_page.addr & ~(SNDRV_TRIDENT_PAGE_SIZE-1));
3369 trident->tlb.shadow_entries[i] = (unsigned long)trident->tlb.silent_page.area;
3370 }
3371
3372 /* use emu memory block manager code to manage tlb page allocation */
3373 trident->tlb.memhdr = snd_util_memhdr_new(SNDRV_TRIDENT_PAGE_SIZE * SNDRV_TRIDENT_MAX_PAGES);
3374 if (trident->tlb.memhdr == NULL)
3375 return -ENOMEM;
3376
3377 trident->tlb.memhdr->block_extra_size = sizeof(snd_trident_memblk_arg_t);
3378 return 0;
3379}
3380
3381/*
3382 * initialize 4D DX chip
3383 */
3384
3385static void snd_trident_stop_all_voices(trident_t *trident)
3386{
3387 outl(0xffffffff, TRID_REG(trident, T4D_STOP_A));
3388 outl(0xffffffff, TRID_REG(trident, T4D_STOP_B));
3389 outl(0, TRID_REG(trident, T4D_AINTEN_A));
3390 outl(0, TRID_REG(trident, T4D_AINTEN_B));
3391}
3392
3393static int snd_trident_4d_dx_init(trident_t *trident)
3394{
3395 struct pci_dev *pci = trident->pci;
3396 unsigned long end_time;
3397
3398 /* reset the legacy configuration and whole audio/wavetable block */
3399 pci_write_config_dword(pci, 0x40, 0); /* DDMA */
3400 pci_write_config_byte(pci, 0x44, 0); /* ports */
3401 pci_write_config_byte(pci, 0x45, 0); /* Legacy DMA */
3402 pci_write_config_byte(pci, 0x46, 4); /* reset */
3403 udelay(100);
3404 pci_write_config_byte(pci, 0x46, 0); /* release reset */
3405 udelay(100);
3406
3407 /* warm reset of the AC'97 codec */
3408 outl(0x00000001, TRID_REG(trident, DX_ACR2_AC97_COM_STAT));
3409 udelay(100);
3410 outl(0x00000000, TRID_REG(trident, DX_ACR2_AC97_COM_STAT));
3411 /* DAC on, disable SB IRQ and try to force ADC valid signal */
3412 trident->ac97_ctrl = 0x0000004a;
3413 outl(trident->ac97_ctrl, TRID_REG(trident, DX_ACR2_AC97_COM_STAT));
3414 /* wait, until the codec is ready */
3415 end_time = (jiffies + (HZ * 3) / 4) + 1;
3416 do {
3417 if ((inl(TRID_REG(trident, DX_ACR2_AC97_COM_STAT)) & 0x0010) != 0)
3418 goto __dx_ok;
3419 do_delay(trident);
3420 } while (time_after_eq(end_time, jiffies));
3421 snd_printk(KERN_ERR "AC'97 codec ready error\n");
3422 return -EIO;
3423
3424 __dx_ok:
3425 snd_trident_stop_all_voices(trident);
3426
3427 return 0;
3428}
3429
3430/*
3431 * initialize 4D NX chip
3432 */
3433static int snd_trident_4d_nx_init(trident_t *trident)
3434{
3435 struct pci_dev *pci = trident->pci;
3436 unsigned long end_time;
3437
3438 /* reset the legacy configuration and whole audio/wavetable block */
3439 pci_write_config_dword(pci, 0x40, 0); /* DDMA */
3440 pci_write_config_byte(pci, 0x44, 0); /* ports */
3441 pci_write_config_byte(pci, 0x45, 0); /* Legacy DMA */
3442
3443 pci_write_config_byte(pci, 0x46, 1); /* reset */
3444 udelay(100);
3445 pci_write_config_byte(pci, 0x46, 0); /* release reset */
3446 udelay(100);
3447
3448 /* warm reset of the AC'97 codec */
3449 outl(0x00000001, TRID_REG(trident, NX_ACR0_AC97_COM_STAT));
3450 udelay(100);
3451 outl(0x00000000, TRID_REG(trident, NX_ACR0_AC97_COM_STAT));
3452 /* wait, until the codec is ready */
3453 end_time = (jiffies + (HZ * 3) / 4) + 1;
3454 do {
3455 if ((inl(TRID_REG(trident, NX_ACR0_AC97_COM_STAT)) & 0x0008) != 0)
3456 goto __nx_ok;
3457 do_delay(trident);
3458 } while (time_after_eq(end_time, jiffies));
3459 snd_printk(KERN_ERR "AC'97 codec ready error [0x%x]\n", inl(TRID_REG(trident, NX_ACR0_AC97_COM_STAT)));
3460 return -EIO;
3461
3462 __nx_ok:
3463 /* DAC on */
3464 trident->ac97_ctrl = 0x00000002;
3465 outl(trident->ac97_ctrl, TRID_REG(trident, NX_ACR0_AC97_COM_STAT));
3466 /* disable SB IRQ */
3467 outl(NX_SB_IRQ_DISABLE, TRID_REG(trident, T4D_MISCINT));
3468
3469 snd_trident_stop_all_voices(trident);
3470
3471 if (trident->tlb.entries != NULL) {
3472 unsigned int i;
3473 /* enable virtual addressing via TLB */
3474 i = trident->tlb.entries_dmaaddr;
3475 i |= 0x00000001;
3476 outl(i, TRID_REG(trident, NX_TLBC));
3477 } else {
3478 outl(0, TRID_REG(trident, NX_TLBC));
3479 }
3480 /* initialize S/PDIF */
3481 outl(trident->spdif_bits, TRID_REG(trident, NX_SPCSTATUS));
3482 outb(trident->spdif_ctrl, TRID_REG(trident, NX_SPCTRL_SPCSO + 3));
3483
3484 return 0;
3485}
3486
3487/*
3488 * initialize sis7018 chip
3489 */
3490static int snd_trident_sis_init(trident_t *trident)
3491{
3492 int err;
3493
3494 if ((err = snd_trident_sis_reset(trident)) < 0)
3495 return err;
3496
3497 snd_trident_stop_all_voices(trident);
3498
3499 /* initialize S/PDIF */
3500 outl(trident->spdif_bits, TRID_REG(trident, SI_SPDIF_CS));
3501
3502 return 0;
3503}
3504
3505/*---------------------------------------------------------------------------
3506 snd_trident_create
3507
3508 Description: This routine will create the device specific class for
3509 the 4DWave card. It will also perform basic initialization.
3510
3511 Paramters: card - which card to create
3512 pci - interface to PCI bus resource info
3513 dma1ptr - playback dma buffer
3514 dma2ptr - capture dma buffer
3515 irqptr - interrupt resource info
3516
3517 Returns: 4DWave device class private data
3518
3519 ---------------------------------------------------------------------------*/
3520
3521int __devinit snd_trident_create(snd_card_t * card,
3522 struct pci_dev *pci,
3523 int pcm_streams,
3524 int pcm_spdif_device,
3525 int max_wavetable_size,
3526 trident_t ** rtrident)
3527{
3528 trident_t *trident;
3529 int i, err;
3530 snd_trident_voice_t *voice;
3531 snd_trident_pcm_mixer_t *tmix;
3532 static snd_device_ops_t ops = {
3533 .dev_free = snd_trident_dev_free,
3534 };
3535
3536 *rtrident = NULL;
3537
3538 /* enable PCI device */
3539 if ((err = pci_enable_device(pci)) < 0)
3540 return err;
3541 /* check, if we can restrict PCI DMA transfers to 30 bits */
3542 if (pci_set_dma_mask(pci, 0x3fffffff) < 0 ||
3543 pci_set_consistent_dma_mask(pci, 0x3fffffff) < 0) {
3544 snd_printk("architecture does not support 30bit PCI busmaster DMA\n");
3545 pci_disable_device(pci);
3546 return -ENXIO;
3547 }
3548
3549 trident = kcalloc(1, sizeof(*trident), GFP_KERNEL);
3550 if (trident == NULL) {
3551 pci_disable_device(pci);
3552 return -ENOMEM;
3553 }
3554 trident->device = (pci->vendor << 16) | pci->device;
3555 trident->card = card;
3556 trident->pci = pci;
3557 spin_lock_init(&trident->reg_lock);
3558 spin_lock_init(&trident->event_lock);
3559 spin_lock_init(&trident->voice_alloc);
3560 if (pcm_streams < 1)
3561 pcm_streams = 1;
3562 if (pcm_streams > 32)
3563 pcm_streams = 32;
3564 trident->ChanPCM = pcm_streams;
3565 if (max_wavetable_size < 0 )
3566 max_wavetable_size = 0;
3567 trident->synth.max_size = max_wavetable_size * 1024;
3568 trident->irq = -1;
3569
3570 trident->midi_port = TRID_REG(trident, T4D_MPU401_BASE);
3571 pci_set_master(pci);
3572
3573 if ((err = pci_request_regions(pci, "Trident Audio")) < 0) {
3574 kfree(trident);
3575 pci_disable_device(pci);
3576 return err;
3577 }
3578 trident->port = pci_resource_start(pci, 0);
3579
3580 if (request_irq(pci->irq, snd_trident_interrupt, SA_INTERRUPT|SA_SHIRQ, "Trident Audio", (void *) trident)) {
3581 snd_printk("unable to grab IRQ %d\n", pci->irq);
3582 snd_trident_free(trident);
3583 return -EBUSY;
3584 }
3585 trident->irq = pci->irq;
3586
3587 /* allocate 16k-aligned TLB for NX cards */
3588 trident->tlb.entries = NULL;
3589 trident->tlb.buffer.area = NULL;
3590 if (trident->device == TRIDENT_DEVICE_ID_NX) {
3591 if ((err = snd_trident_tlb_alloc(trident)) < 0) {
3592 snd_trident_free(trident);
3593 return err;
3594 }
3595 }
3596
3597 trident->spdif_bits = trident->spdif_pcm_bits = SNDRV_PCM_DEFAULT_CON_SPDIF;
3598
3599 /* initialize chip */
3600 switch (trident->device) {
3601 case TRIDENT_DEVICE_ID_DX:
3602 err = snd_trident_4d_dx_init(trident);
3603 break;
3604 case TRIDENT_DEVICE_ID_NX:
3605 err = snd_trident_4d_nx_init(trident);
3606 break;
3607 case TRIDENT_DEVICE_ID_SI7018:
3608 err = snd_trident_sis_init(trident);
3609 break;
3610 default:
3611 snd_BUG();
3612 break;
3613 }
3614 if (err < 0) {
3615 snd_trident_free(trident);
3616 return err;
3617 }
3618
3619 if ((err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, trident, &ops)) < 0) {
3620 snd_trident_free(trident);
3621 return err;
3622 }
3623
3624 if ((err = snd_trident_mixer(trident, pcm_spdif_device)) < 0)
3625 return err;
3626
3627 /* initialise synth voices */
3628 for (i = 0; i < 64; i++) {
3629 voice = &trident->synth.voices[i];
3630 voice->number = i;
3631 voice->trident = trident;
3632 }
3633 /* initialize pcm mixer entries */
3634 for (i = 0; i < 32; i++) {
3635 tmix = &trident->pcm_mixer[i];
3636 tmix->vol = T4D_DEFAULT_PCM_VOL;
3637 tmix->pan = T4D_DEFAULT_PCM_PAN;
3638 tmix->rvol = T4D_DEFAULT_PCM_RVOL;
3639 tmix->cvol = T4D_DEFAULT_PCM_CVOL;
3640 }
3641
3642 snd_trident_enable_eso(trident);
3643
3644
3645 snd_card_set_pm_callback(card, snd_trident_suspend, snd_trident_resume, trident);
3646 snd_trident_proc_init(trident);
3647 snd_card_set_dev(card, &pci->dev);
3648 *rtrident = trident;
3649 return 0;
3650}
3651
3652/*---------------------------------------------------------------------------
3653 snd_trident_free
3654
3655 Description: This routine will free the device specific class for
3656 the 4DWave card.
3657
3658 Paramters: trident - device specific private data for 4DWave card
3659
3660 Returns: None.
3661
3662 ---------------------------------------------------------------------------*/
3663
3664static int snd_trident_free(trident_t *trident)
3665{
3666 snd_trident_free_gameport(trident);
3667 snd_trident_disable_eso(trident);
3668 // Disable S/PDIF out
3669 if (trident->device == TRIDENT_DEVICE_ID_NX)
3670 outb(0x00, TRID_REG(trident, NX_SPCTRL_SPCSO + 3));
3671 else if (trident->device == TRIDENT_DEVICE_ID_SI7018) {
3672 outl(0, TRID_REG(trident, SI_SERIAL_INTF_CTRL));
3673 }
3674 if (trident->tlb.buffer.area) {
3675 outl(0, TRID_REG(trident, NX_TLBC));
3676 if (trident->tlb.memhdr)
3677 snd_util_memhdr_free(trident->tlb.memhdr);
3678 if (trident->tlb.silent_page.area)
3679 snd_dma_free_pages(&trident->tlb.silent_page);
3680 vfree(trident->tlb.shadow_entries);
3681 snd_dma_free_pages(&trident->tlb.buffer);
3682 }
3683 if (trident->irq >= 0)
3684 free_irq(trident->irq, (void *)trident);
3685 pci_release_regions(trident->pci);
3686 pci_disable_device(trident->pci);
3687 kfree(trident);
3688 return 0;
3689}
3690
3691/*---------------------------------------------------------------------------
3692 snd_trident_interrupt
3693
3694 Description: ISR for Trident 4DWave device
3695
3696 Paramters: trident - device specific private data for 4DWave card
3697
3698 Problems: It seems that Trident chips generates interrupts more than
3699 one time in special cases. The spurious interrupts are
3700 detected via sample timer (T4D_STIMER) and computing
3701 corresponding delta value. The limits are detected with
3702 the method try & fail so it is possible that it won't
3703 work on all computers. [jaroslav]
3704
3705 Returns: None.
3706
3707 ---------------------------------------------------------------------------*/
3708
3709static irqreturn_t snd_trident_interrupt(int irq, void *dev_id, struct pt_regs *regs)
3710{
3711 trident_t *trident = dev_id;
3712 unsigned int audio_int, chn_int, stimer, channel, mask, tmp;
3713 int delta;
3714 snd_trident_voice_t *voice;
3715
3716 audio_int = inl(TRID_REG(trident, T4D_MISCINT));
3717 if ((audio_int & (ADDRESS_IRQ|MPU401_IRQ)) == 0)
3718 return IRQ_NONE;
3719 if (audio_int & ADDRESS_IRQ) {
3720 // get interrupt status for all channels
3721 spin_lock(&trident->reg_lock);
3722 stimer = inl(TRID_REG(trident, T4D_STIMER)) & 0x00ffffff;
3723 chn_int = inl(TRID_REG(trident, T4D_AINT_A));
3724 if (chn_int == 0)
3725 goto __skip1;
3726 outl(chn_int, TRID_REG(trident, T4D_AINT_A)); /* ack */
3727 __skip1:
3728 chn_int = inl(TRID_REG(trident, T4D_AINT_B));
3729 if (chn_int == 0)
3730 goto __skip2;
3731 for (channel = 63; channel >= 32; channel--) {
3732 mask = 1 << (channel&0x1f);
3733 if ((chn_int & mask) == 0)
3734 continue;
3735 voice = &trident->synth.voices[channel];
3736 if (!voice->pcm || voice->substream == NULL) {
3737 outl(mask, TRID_REG(trident, T4D_STOP_B));
3738 continue;
3739 }
3740 delta = (int)stimer - (int)voice->stimer;
3741 if (delta < 0)
3742 delta = -delta;
3743 if ((unsigned int)delta < voice->spurious_threshold) {
3744 /* do some statistics here */
3745 trident->spurious_irq_count++;
3746 if (trident->spurious_irq_max_delta < (unsigned int)delta)
3747 trident->spurious_irq_max_delta = delta;
3748 continue;
3749 }
3750 voice->stimer = stimer;
3751 if (voice->isync) {
3752 if (!voice->isync3) {
3753 tmp = inw(TRID_REG(trident, T4D_SBBL_SBCL));
3754 if (trident->bDMAStart & 0x40)
3755 tmp >>= 1;
3756 if (tmp > 0)
3757 tmp = voice->isync_max - tmp;
3758 } else {
3759 tmp = inl(TRID_REG(trident, NX_SPCTRL_SPCSO)) & 0x00ffffff;
3760 }
3761 if (tmp < voice->isync_mark) {
3762 if (tmp > 0x10)
3763 tmp = voice->isync_ESO - 7;
3764 else
3765 tmp = voice->isync_ESO + 2;
3766 /* update ESO for IRQ voice to preserve sync */
3767 snd_trident_stop_voice(trident, voice->number);
3768 snd_trident_write_eso_reg(trident, voice, tmp);
3769 snd_trident_start_voice(trident, voice->number);
3770 }
3771 } else if (voice->isync2) {
3772 voice->isync2 = 0;
3773 /* write original ESO and update CSO for IRQ voice to preserve sync */
3774 snd_trident_stop_voice(trident, voice->number);
3775 snd_trident_write_cso_reg(trident, voice, voice->isync_mark);
3776 snd_trident_write_eso_reg(trident, voice, voice->ESO);
3777 snd_trident_start_voice(trident, voice->number);
3778 }
3779#if 0
3780 if (voice->extra) {
3781 /* update CSO for extra voice to preserve sync */
3782 snd_trident_stop_voice(trident, voice->extra->number);
3783 snd_trident_write_cso_reg(trident, voice->extra, 0);
3784 snd_trident_start_voice(trident, voice->extra->number);
3785 }
3786#endif
3787 spin_unlock(&trident->reg_lock);
3788 snd_pcm_period_elapsed(voice->substream);
3789 spin_lock(&trident->reg_lock);
3790 }
3791 outl(chn_int, TRID_REG(trident, T4D_AINT_B)); /* ack */
3792 __skip2:
3793 spin_unlock(&trident->reg_lock);
3794 }
3795 if (audio_int & MPU401_IRQ) {
3796 if (trident->rmidi) {
3797 snd_mpu401_uart_interrupt(irq, trident->rmidi->private_data, regs);
3798 } else {
3799 inb(TRID_REG(trident, T4D_MPUR0));
3800 }
3801 }
3802 // outl((ST_TARGET_REACHED | MIXER_OVERFLOW | MIXER_UNDERFLOW), TRID_REG(trident, T4D_MISCINT));
3803 return IRQ_HANDLED;
3804}
3805
3806/*---------------------------------------------------------------------------
3807 snd_trident_attach_synthesizer
3808
3809 Description: Attach synthesizer hooks
3810
3811 Paramters: trident - device specific private data for 4DWave card
3812
3813 Returns: None.
3814
3815 ---------------------------------------------------------------------------*/
3816int snd_trident_attach_synthesizer(trident_t *trident)
3817{
3818#if defined(CONFIG_SND_SEQUENCER) || (defined(MODULE) && defined(CONFIG_SND_SEQUENCER_MODULE))
3819 if (snd_seq_device_new(trident->card, 1, SNDRV_SEQ_DEV_ID_TRIDENT,
3820 sizeof(trident_t*), &trident->seq_dev) >= 0) {
3821 strcpy(trident->seq_dev->name, "4DWave");
3822 *(trident_t**)SNDRV_SEQ_DEVICE_ARGPTR(trident->seq_dev) = trident;
3823 }
3824#endif
3825 return 0;
3826}
3827
3828snd_trident_voice_t *snd_trident_alloc_voice(trident_t * trident, int type, int client, int port)
3829{
3830 snd_trident_voice_t *pvoice;
3831 unsigned long flags;
3832 int idx;
3833
3834 spin_lock_irqsave(&trident->voice_alloc, flags);
3835 if (type == SNDRV_TRIDENT_VOICE_TYPE_PCM) {
3836 idx = snd_trident_allocate_pcm_channel(trident);
3837 if(idx < 0) {
3838 spin_unlock_irqrestore(&trident->voice_alloc, flags);
3839 return NULL;
3840 }
3841 pvoice = &trident->synth.voices[idx];
3842 pvoice->use = 1;
3843 pvoice->pcm = 1;
3844 pvoice->capture = 0;
3845 pvoice->spdif = 0;
3846 pvoice->memblk = NULL;
3847 pvoice->substream = NULL;
3848 spin_unlock_irqrestore(&trident->voice_alloc, flags);
3849 return pvoice;
3850 }
3851 if (type == SNDRV_TRIDENT_VOICE_TYPE_SYNTH) {
3852 idx = snd_trident_allocate_synth_channel(trident);
3853 if(idx < 0) {
3854 spin_unlock_irqrestore(&trident->voice_alloc, flags);
3855 return NULL;
3856 }
3857 pvoice = &trident->synth.voices[idx];
3858 pvoice->use = 1;
3859 pvoice->synth = 1;
3860 pvoice->client = client;
3861 pvoice->port = port;
3862 pvoice->memblk = NULL;
3863 spin_unlock_irqrestore(&trident->voice_alloc, flags);
3864 return pvoice;
3865 }
3866 if (type == SNDRV_TRIDENT_VOICE_TYPE_MIDI) {
3867 }
3868 spin_unlock_irqrestore(&trident->voice_alloc, flags);
3869 return NULL;
3870}
3871
3872void snd_trident_free_voice(trident_t * trident, snd_trident_voice_t *voice)
3873{
3874 unsigned long flags;
3875 void (*private_free)(snd_trident_voice_t *);
3876 void *private_data;
3877
3878 if (voice == NULL || !voice->use)
3879 return;
3880 snd_trident_clear_voices(trident, voice->number, voice->number);
3881 spin_lock_irqsave(&trident->voice_alloc, flags);
3882 private_free = voice->private_free;
3883 private_data = voice->private_data;
3884 voice->private_free = NULL;
3885 voice->private_data = NULL;
3886 if (voice->pcm)
3887 snd_trident_free_pcm_channel(trident, voice->number);
3888 if (voice->synth)
3889 snd_trident_free_synth_channel(trident, voice->number);
3890 voice->use = voice->pcm = voice->synth = voice->midi = 0;
3891 voice->capture = voice->spdif = 0;
3892 voice->sample_ops = NULL;
3893 voice->substream = NULL;
3894 voice->extra = NULL;
3895 spin_unlock_irqrestore(&trident->voice_alloc, flags);
3896 if (private_free)
3897 private_free(voice);
3898}
3899
3900static void snd_trident_clear_voices(trident_t * trident, unsigned short v_min, unsigned short v_max)
3901{
3902 unsigned int i, val, mask[2] = { 0, 0 };
3903
3904 snd_assert(v_min <= 63, return);
3905 snd_assert(v_max <= 63, return);
3906 for (i = v_min; i <= v_max; i++)
3907 mask[i >> 5] |= 1 << (i & 0x1f);
3908 if (mask[0]) {
3909 outl(mask[0], TRID_REG(trident, T4D_STOP_A));
3910 val = inl(TRID_REG(trident, T4D_AINTEN_A));
3911 outl(val & ~mask[0], TRID_REG(trident, T4D_AINTEN_A));
3912 }
3913 if (mask[1]) {
3914 outl(mask[1], TRID_REG(trident, T4D_STOP_B));
3915 val = inl(TRID_REG(trident, T4D_AINTEN_B));
3916 outl(val & ~mask[1], TRID_REG(trident, T4D_AINTEN_B));
3917 }
3918}
3919
3920#ifdef CONFIG_PM
3921static int snd_trident_suspend(snd_card_t *card, pm_message_t state)
3922{
3923 trident_t *trident = card->pm_private_data;
3924
3925 trident->in_suspend = 1;
3926 snd_pcm_suspend_all(trident->pcm);
3927 if (trident->foldback)
3928 snd_pcm_suspend_all(trident->foldback);
3929 if (trident->spdif)
3930 snd_pcm_suspend_all(trident->spdif);
3931
3932 snd_ac97_suspend(trident->ac97);
3933 if (trident->ac97_sec)
3934 snd_ac97_suspend(trident->ac97_sec);
3935
3936 switch (trident->device) {
3937 case TRIDENT_DEVICE_ID_DX:
3938 case TRIDENT_DEVICE_ID_NX:
3939 break; /* TODO */
3940 case TRIDENT_DEVICE_ID_SI7018:
3941 break;
3942 }
3943 pci_disable_device(trident->pci);
3944 return 0;
3945}
3946
3947static int snd_trident_resume(snd_card_t *card)
3948{
3949 trident_t *trident = card->pm_private_data;
3950
3951 pci_enable_device(trident->pci);
3952 if (pci_set_dma_mask(trident->pci, 0x3fffffff) < 0 ||
3953 pci_set_consistent_dma_mask(trident->pci, 0x3fffffff) < 0)
3954 snd_printk(KERN_WARNING "trident: can't set the proper DMA mask\n");
3955 pci_set_master(trident->pci); /* to be sure */
3956
3957 switch (trident->device) {
3958 case TRIDENT_DEVICE_ID_DX:
3959 snd_trident_4d_dx_init(trident);
3960 break;
3961 case TRIDENT_DEVICE_ID_NX:
3962 snd_trident_4d_nx_init(trident);
3963 break;
3964 case TRIDENT_DEVICE_ID_SI7018:
3965 snd_trident_sis_init(trident);
3966 break;
3967 }
3968
3969 snd_ac97_resume(trident->ac97);
3970 if (trident->ac97_sec)
3971 snd_ac97_resume(trident->ac97_sec);
3972
3973 /* restore some registers */
3974 outl(trident->musicvol_wavevol, TRID_REG(trident, T4D_MUSICVOL_WAVEVOL));
3975
3976 snd_trident_enable_eso(trident);
3977
3978 trident->in_suspend = 0;
3979 return 0;
3980}
3981#endif /* CONFIG_PM */
3982
3983EXPORT_SYMBOL(snd_trident_alloc_voice);
3984EXPORT_SYMBOL(snd_trident_free_voice);
3985EXPORT_SYMBOL(snd_trident_start_voice);
3986EXPORT_SYMBOL(snd_trident_stop_voice);
3987EXPORT_SYMBOL(snd_trident_write_voice_regs);
3988/* trident_memory.c symbols */
3989EXPORT_SYMBOL(snd_trident_synth_alloc);
3990EXPORT_SYMBOL(snd_trident_synth_free);
3991EXPORT_SYMBOL(snd_trident_synth_copy_from_user);
diff --git a/sound/pci/trident/trident_memory.c b/sound/pci/trident/trident_memory.c
new file mode 100644
index 000000000000..6cc282681e09
--- /dev/null
+++ b/sound/pci/trident/trident_memory.c
@@ -0,0 +1,476 @@
1/*
2 * Copyright (c) by Jaroslav Kysela <perex@suse.cz>
3 * Copyright (c) by Takashi Iwai <tiwai@suse.de>
4 * Copyright (c) by Scott McNab <sdm@fractalgraphics.com.au>
5 *
6 * Trident 4DWave-NX memory page allocation (TLB area)
7 * Trident chip can handle only 16MByte of the memory at the same time.
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 */
25
26#include <sound/driver.h>
27#include <asm/io.h>
28#include <linux/pci.h>
29#include <linux/time.h>
30#include <sound/core.h>
31#include <sound/trident.h>
32
33/* page arguments of these two macros are Trident page (4096 bytes), not like
34 * aligned pages in others
35 */
36#define __set_tlb_bus(trident,page,ptr,addr) \
37 do { (trident)->tlb.entries[page] = cpu_to_le32((addr) & ~(SNDRV_TRIDENT_PAGE_SIZE-1)); \
38 (trident)->tlb.shadow_entries[page] = (ptr); } while (0)
39#define __tlb_to_ptr(trident,page) \
40 (void*)((trident)->tlb.shadow_entries[page])
41#define __tlb_to_addr(trident,page) \
42 (dma_addr_t)le32_to_cpu((trident->tlb.entries[page]) & ~(SNDRV_TRIDENT_PAGE_SIZE - 1))
43
44#if PAGE_SIZE == 4096
45/* page size == SNDRV_TRIDENT_PAGE_SIZE */
46#define ALIGN_PAGE_SIZE PAGE_SIZE /* minimum page size for allocation */
47#define MAX_ALIGN_PAGES SNDRV_TRIDENT_MAX_PAGES /* maxmium aligned pages */
48/* fill TLB entrie(s) corresponding to page with ptr */
49#define set_tlb_bus(trident,page,ptr,addr) __set_tlb_bus(trident,page,ptr,addr)
50/* fill TLB entrie(s) corresponding to page with silence pointer */
51#define set_silent_tlb(trident,page) __set_tlb_bus(trident, page, (unsigned long)trident->tlb.silent_page.area, trident->tlb.silent_page.addr)
52/* get aligned page from offset address */
53#define get_aligned_page(offset) ((offset) >> 12)
54/* get offset address from aligned page */
55#define aligned_page_offset(page) ((page) << 12)
56/* get buffer address from aligned page */
57#define page_to_ptr(trident,page) __tlb_to_ptr(trident, page)
58/* get PCI physical address from aligned page */
59#define page_to_addr(trident,page) __tlb_to_addr(trident, page)
60
61#elif PAGE_SIZE == 8192
62/* page size == SNDRV_TRIDENT_PAGE_SIZE x 2*/
63#define ALIGN_PAGE_SIZE PAGE_SIZE
64#define MAX_ALIGN_PAGES (SNDRV_TRIDENT_MAX_PAGES / 2)
65#define get_aligned_page(offset) ((offset) >> 13)
66#define aligned_page_offset(page) ((page) << 13)
67#define page_to_ptr(trident,page) __tlb_to_ptr(trident, (page) << 1)
68#define page_to_addr(trident,page) __tlb_to_addr(trident, (page) << 1)
69
70/* fill TLB entries -- we need to fill two entries */
71static inline void set_tlb_bus(trident_t *trident, int page, unsigned long ptr, dma_addr_t addr)
72{
73 page <<= 1;
74 __set_tlb_bus(trident, page, ptr, addr);
75 __set_tlb_bus(trident, page+1, ptr + SNDRV_TRIDENT_PAGE_SIZE, addr + SNDRV_TRIDENT_PAGE_SIZE);
76}
77static inline void set_silent_tlb(trident_t *trident, int page)
78{
79 page <<= 1;
80 __set_tlb_bus(trident, page, (unsigned long)trident->tlb.silent_page.area, trident->tlb.silent_page.addr);
81 __set_tlb_bus(trident, page+1, (unsigned long)trident->tlb.silent_page.area, trident->tlb.silent_page.addr);
82}
83
84#else
85/* arbitrary size */
86#define UNIT_PAGES (PAGE_SIZE / SNDRV_TRIDENT_PAGE_SIZE)
87#define ALIGN_PAGE_SIZE (SNDRV_TRIDENT_PAGE_SIZE * UNIT_PAGES)
88#define MAX_ALIGN_PAGES (SNDRV_TRIDENT_MAX_PAGES / UNIT_PAGES)
89/* Note: if alignment doesn't match to the maximum size, the last few blocks
90 * become unusable. To use such blocks, you'll need to check the validity
91 * of accessing page in set_tlb_bus and set_silent_tlb. search_empty()
92 * should also check it, too.
93 */
94#define get_aligned_page(offset) ((offset) / ALIGN_PAGE_SIZE)
95#define aligned_page_offset(page) ((page) * ALIGN_PAGE_SIZE)
96#define page_to_ptr(trident,page) __tlb_to_ptr(trident, (page) * UNIT_PAGES)
97#define page_to_addr(trident,page) __tlb_to_addr(trident, (page) * UNIT_PAGES)
98
99/* fill TLB entries -- UNIT_PAGES entries must be filled */
100static inline void set_tlb_bus(trident_t *trident, int page, unsigned long ptr, dma_addr_t addr)
101{
102 int i;
103 page *= UNIT_PAGES;
104 for (i = 0; i < UNIT_PAGES; i++, page++) {
105 __set_tlb_bus(trident, page, ptr, addr);
106 ptr += SNDRV_TRIDENT_PAGE_SIZE;
107 addr += SNDRV_TRIDENT_PAGE_SIZE;
108 }
109}
110static inline void set_silent_tlb(trident_t *trident, int page)
111{
112 int i;
113 page *= UNIT_PAGES;
114 for (i = 0; i < UNIT_PAGES; i++, page++)
115 __set_tlb_bus(trident, page, (unsigned long)trident->tlb.silent_page.area, trident->tlb.silent_page.addr);
116}
117
118#endif /* PAGE_SIZE */
119
120/* calculate buffer pointer from offset address */
121inline static void *offset_ptr(trident_t *trident, int offset)
122{
123 char *ptr;
124 ptr = page_to_ptr(trident, get_aligned_page(offset));
125 ptr += offset % ALIGN_PAGE_SIZE;
126 return (void*)ptr;
127}
128
129/* first and last (aligned) pages of memory block */
130#define firstpg(blk) (((snd_trident_memblk_arg_t*)snd_util_memblk_argptr(blk))->first_page)
131#define lastpg(blk) (((snd_trident_memblk_arg_t*)snd_util_memblk_argptr(blk))->last_page)
132
133/*
134 * search empty pages which may contain given size
135 */
136static snd_util_memblk_t *
137search_empty(snd_util_memhdr_t *hdr, int size)
138{
139 snd_util_memblk_t *blk, *prev;
140 int page, psize;
141 struct list_head *p;
142
143 psize = get_aligned_page(size + ALIGN_PAGE_SIZE -1);
144 prev = NULL;
145 page = 0;
146 list_for_each(p, &hdr->block) {
147 blk = list_entry(p, snd_util_memblk_t, list);
148 if (page + psize <= firstpg(blk))
149 goto __found_pages;
150 page = lastpg(blk) + 1;
151 }
152 if (page + psize > MAX_ALIGN_PAGES)
153 return NULL;
154
155__found_pages:
156 /* create a new memory block */
157 blk = __snd_util_memblk_new(hdr, psize * ALIGN_PAGE_SIZE, p->prev);
158 if (blk == NULL)
159 return NULL;
160 blk->offset = aligned_page_offset(page); /* set aligned offset */
161 firstpg(blk) = page;
162 lastpg(blk) = page + psize - 1;
163 return blk;
164}
165
166
167/*
168 * check if the given pointer is valid for pages
169 */
170static int is_valid_page(unsigned long ptr)
171{
172 if (ptr & ~0x3fffffffUL) {
173 snd_printk("max memory size is 1GB!!\n");
174 return 0;
175 }
176 if (ptr & (SNDRV_TRIDENT_PAGE_SIZE-1)) {
177 snd_printk("page is not aligned\n");
178 return 0;
179 }
180 return 1;
181}
182
183/*
184 * page allocation for DMA (Scatter-Gather version)
185 */
186static snd_util_memblk_t *
187snd_trident_alloc_sg_pages(trident_t *trident, snd_pcm_substream_t *substream)
188{
189 snd_util_memhdr_t *hdr;
190 snd_util_memblk_t *blk;
191 snd_pcm_runtime_t *runtime = substream->runtime;
192 int idx, page;
193 struct snd_sg_buf *sgbuf = snd_pcm_substream_sgbuf(substream);
194
195 snd_assert(runtime->dma_bytes > 0 && runtime->dma_bytes <= SNDRV_TRIDENT_MAX_PAGES * SNDRV_TRIDENT_PAGE_SIZE, return NULL);
196 hdr = trident->tlb.memhdr;
197 snd_assert(hdr != NULL, return NULL);
198
199
200
201 down(&hdr->block_mutex);
202 blk = search_empty(hdr, runtime->dma_bytes);
203 if (blk == NULL) {
204 up(&hdr->block_mutex);
205 return NULL;
206 }
207 if (lastpg(blk) - firstpg(blk) >= sgbuf->pages) {
208 snd_printk(KERN_ERR "page calculation doesn't match: allocated pages = %d, trident = %d/%d\n", sgbuf->pages, firstpg(blk), lastpg(blk));
209 __snd_util_mem_free(hdr, blk);
210 up(&hdr->block_mutex);
211 return NULL;
212 }
213
214 /* set TLB entries */
215 idx = 0;
216 for (page = firstpg(blk); page <= lastpg(blk); page++, idx++) {
217 dma_addr_t addr = sgbuf->table[idx].addr;
218 unsigned long ptr = (unsigned long)sgbuf->table[idx].buf;
219 if (! is_valid_page(addr)) {
220 __snd_util_mem_free(hdr, blk);
221 up(&hdr->block_mutex);
222 return NULL;
223 }
224 set_tlb_bus(trident, page, ptr, addr);
225 }
226 up(&hdr->block_mutex);
227 return blk;
228}
229
230/*
231 * page allocation for DMA (contiguous version)
232 */
233static snd_util_memblk_t *
234snd_trident_alloc_cont_pages(trident_t *trident, snd_pcm_substream_t *substream)
235{
236 snd_util_memhdr_t *hdr;
237 snd_util_memblk_t *blk;
238 int page;
239 snd_pcm_runtime_t *runtime = substream->runtime;
240 dma_addr_t addr;
241 unsigned long ptr;
242
243 snd_assert(runtime->dma_bytes> 0 && runtime->dma_bytes <= SNDRV_TRIDENT_MAX_PAGES * SNDRV_TRIDENT_PAGE_SIZE, return NULL);
244 hdr = trident->tlb.memhdr;
245 snd_assert(hdr != NULL, return NULL);
246
247 down(&hdr->block_mutex);
248 blk = search_empty(hdr, runtime->dma_bytes);
249 if (blk == NULL) {
250 up(&hdr->block_mutex);
251 return NULL;
252 }
253
254 /* set TLB entries */
255 addr = runtime->dma_addr;
256 ptr = (unsigned long)runtime->dma_area;
257 for (page = firstpg(blk); page <= lastpg(blk); page++,
258 ptr += SNDRV_TRIDENT_PAGE_SIZE, addr += SNDRV_TRIDENT_PAGE_SIZE) {
259 if (! is_valid_page(addr)) {
260 __snd_util_mem_free(hdr, blk);
261 up(&hdr->block_mutex);
262 return NULL;
263 }
264 set_tlb_bus(trident, page, ptr, addr);
265 }
266 up(&hdr->block_mutex);
267 return blk;
268}
269
270/*
271 * page allocation for DMA
272 */
273snd_util_memblk_t *
274snd_trident_alloc_pages(trident_t *trident, snd_pcm_substream_t *substream)
275{
276 snd_assert(trident != NULL, return NULL);
277 snd_assert(substream != NULL, return NULL);
278 if (substream->dma_buffer.dev.type == SNDRV_DMA_TYPE_DEV_SG)
279 return snd_trident_alloc_sg_pages(trident, substream);
280 else
281 return snd_trident_alloc_cont_pages(trident, substream);
282}
283
284
285/*
286 * release DMA buffer from page table
287 */
288int snd_trident_free_pages(trident_t *trident, snd_util_memblk_t *blk)
289{
290 snd_util_memhdr_t *hdr;
291 int page;
292
293 snd_assert(trident != NULL, return -EINVAL);
294 snd_assert(blk != NULL, return -EINVAL);
295
296 hdr = trident->tlb.memhdr;
297 down(&hdr->block_mutex);
298 /* reset TLB entries */
299 for (page = firstpg(blk); page <= lastpg(blk); page++)
300 set_silent_tlb(trident, page);
301 /* free memory block */
302 __snd_util_mem_free(hdr, blk);
303 up(&hdr->block_mutex);
304 return 0;
305}
306
307
308/*----------------------------------------------------------------
309 * memory allocation using multiple pages (for synth)
310 *----------------------------------------------------------------
311 * Unlike the DMA allocation above, non-contiguous pages are
312 * assigned to TLB.
313 *----------------------------------------------------------------*/
314
315/*
316 */
317static int synth_alloc_pages(trident_t *hw, snd_util_memblk_t *blk);
318static int synth_free_pages(trident_t *hw, snd_util_memblk_t *blk);
319
320/*
321 * allocate a synth sample area
322 */
323snd_util_memblk_t *
324snd_trident_synth_alloc(trident_t *hw, unsigned int size)
325{
326 snd_util_memblk_t *blk;
327 snd_util_memhdr_t *hdr = hw->tlb.memhdr;
328
329 down(&hdr->block_mutex);
330 blk = __snd_util_mem_alloc(hdr, size);
331 if (blk == NULL) {
332 up(&hdr->block_mutex);
333 return NULL;
334 }
335 if (synth_alloc_pages(hw, blk)) {
336 __snd_util_mem_free(hdr, blk);
337 up(&hdr->block_mutex);
338 return NULL;
339 }
340 up(&hdr->block_mutex);
341 return blk;
342}
343
344
345/*
346 * free a synth sample area
347 */
348int
349snd_trident_synth_free(trident_t *hw, snd_util_memblk_t *blk)
350{
351 snd_util_memhdr_t *hdr = hw->tlb.memhdr;
352
353 down(&hdr->block_mutex);
354 synth_free_pages(hw, blk);
355 __snd_util_mem_free(hdr, blk);
356 up(&hdr->block_mutex);
357 return 0;
358}
359
360
361/*
362 * reset TLB entry and free kernel page
363 */
364static void clear_tlb(trident_t *trident, int page)
365{
366 void *ptr = page_to_ptr(trident, page);
367 dma_addr_t addr = page_to_addr(trident, page);
368 set_silent_tlb(trident, page);
369 if (ptr) {
370 struct snd_dma_buffer dmab;
371 dmab.dev.type = SNDRV_DMA_TYPE_DEV;
372 dmab.dev.dev = snd_dma_pci_data(trident->pci);
373 dmab.area = ptr;
374 dmab.addr = addr;
375 dmab.bytes = ALIGN_PAGE_SIZE;
376 snd_dma_free_pages(&dmab);
377 }
378}
379
380/* check new allocation range */
381static void get_single_page_range(snd_util_memhdr_t *hdr, snd_util_memblk_t *blk, int *first_page_ret, int *last_page_ret)
382{
383 struct list_head *p;
384 snd_util_memblk_t *q;
385 int first_page, last_page;
386 first_page = firstpg(blk);
387 if ((p = blk->list.prev) != &hdr->block) {
388 q = list_entry(p, snd_util_memblk_t, list);
389 if (lastpg(q) == first_page)
390 first_page++; /* first page was already allocated */
391 }
392 last_page = lastpg(blk);
393 if ((p = blk->list.next) != &hdr->block) {
394 q = list_entry(p, snd_util_memblk_t, list);
395 if (firstpg(q) == last_page)
396 last_page--; /* last page was already allocated */
397 }
398 *first_page_ret = first_page;
399 *last_page_ret = last_page;
400}
401
402/*
403 * allocate kernel pages and assign them to TLB
404 */
405static int synth_alloc_pages(trident_t *hw, snd_util_memblk_t *blk)
406{
407 int page, first_page, last_page;
408 struct snd_dma_buffer dmab;
409
410 firstpg(blk) = get_aligned_page(blk->offset);
411 lastpg(blk) = get_aligned_page(blk->offset + blk->size - 1);
412 get_single_page_range(hw->tlb.memhdr, blk, &first_page, &last_page);
413
414 /* allocate a kernel page for each Trident page -
415 * fortunately Trident page size and kernel PAGE_SIZE is identical!
416 */
417 for (page = first_page; page <= last_page; page++) {
418 if (snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, snd_dma_pci_data(hw->pci),
419 ALIGN_PAGE_SIZE, &dmab) < 0)
420 goto __fail;
421 if (! is_valid_page(dmab.addr)) {
422 snd_dma_free_pages(&dmab);
423 goto __fail;
424 }
425 set_tlb_bus(hw, page, (unsigned long)dmab.area, dmab.addr);
426 }
427 return 0;
428
429__fail:
430 /* release allocated pages */
431 last_page = page - 1;
432 for (page = first_page; page <= last_page; page++)
433 clear_tlb(hw, page);
434
435 return -ENOMEM;
436}
437
438/*
439 * free pages
440 */
441static int synth_free_pages(trident_t *trident, snd_util_memblk_t *blk)
442{
443 int page, first_page, last_page;
444
445 get_single_page_range(trident->tlb.memhdr, blk, &first_page, &last_page);
446 for (page = first_page; page <= last_page; page++)
447 clear_tlb(trident, page);
448
449 return 0;
450}
451
452/*
453 * copy_from_user(blk + offset, data, size)
454 */
455int snd_trident_synth_copy_from_user(trident_t *trident, snd_util_memblk_t *blk, int offset, const char __user *data, int size)
456{
457 int page, nextofs, end_offset, temp, temp1;
458
459 offset += blk->offset;
460 end_offset = offset + size;
461 page = get_aligned_page(offset) + 1;
462 do {
463 nextofs = aligned_page_offset(page);
464 temp = nextofs - offset;
465 temp1 = end_offset - offset;
466 if (temp1 < temp)
467 temp = temp1;
468 if (copy_from_user(offset_ptr(trident, offset), data, temp))
469 return -EFAULT;
470 offset = nextofs;
471 data += temp;
472 page++;
473 } while (offset < end_offset);
474 return 0;
475}
476
diff --git a/sound/pci/trident/trident_synth.c b/sound/pci/trident/trident_synth.c
new file mode 100644
index 000000000000..5d5a719b0585
--- /dev/null
+++ b/sound/pci/trident/trident_synth.c
@@ -0,0 +1,1031 @@
1/*
2 * Routines for Trident 4DWave NX/DX soundcards - Synthesizer
3 * Copyright (c) by Scott McNab <jedi@tartarus.uwa.edu.au>
4 *
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 *
20 */
21
22#include <sound/driver.h>
23#include <asm/io.h>
24#include <linux/init.h>
25#include <linux/slab.h>
26#include <linux/pci.h>
27#include <sound/core.h>
28#include <sound/trident.h>
29#include <sound/seq_device.h>
30
31MODULE_AUTHOR("Scott McNab <jedi@tartarus.uwa.edu.au>");
32MODULE_DESCRIPTION("Routines for Trident 4DWave NX/DX soundcards - Synthesizer");
33MODULE_LICENSE("GPL");
34
35/* linear to log pan conversion table (4.2 channel attenuation format) */
36static unsigned int pan_table[63] = {
37 7959, 7733, 7514, 7301, 7093, 6892, 6697, 6507,
38 6322, 6143, 5968, 5799, 5634, 5475, 5319, 5168,
39 5022, 4879, 4741, 4606, 4475, 4349, 4225, 4105,
40 3989, 3876, 3766, 3659, 3555, 3454, 3356, 3261,
41 3168, 3078, 2991, 2906, 2824, 2744, 2666, 2590,
42 2517, 2445, 2376, 2308, 2243, 2179, 2117, 2057,
43 1999, 1942, 1887, 1833, 1781, 1731, 1682, 1634,
44 1588, 1543, 1499, 1456, 1415, 1375, 1336
45};
46
47#define LOG_TABLE_SIZE 386
48
49/* Linear half-attenuation to log conversion table in the format:
50 * {linear volume, logarithmic attenuation equivalent}, ...
51 *
52 * Provides conversion from a linear half-volume value in the range
53 * [0,8192] to a logarithmic attenuation value in the range 0 to 6.02dB.
54 * Halving the linear volume is equivalent to an additional 6dB of
55 * logarithmic attenuation. The algorithm used in log_from_linear()
56 * therefore uses this table as follows:
57 *
58 * - loop and for every time the volume is less than half the maximum
59 * volume (16384), add another 6dB and halve the maximum value used
60 * for this comparison.
61 * - when the volume is greater than half the maximum volume, take
62 * the difference of the volume to half volume (in the range [0,8192])
63 * and look up the log_table[] to find the nearest entry.
64 * - take the logarithic component of this entry and add it to the
65 * resulting attenuation.
66 *
67 * Thus this routine provides a linear->log conversion for a range of
68 * [0,16384] using only 386 table entries
69 *
70 * Note: although this table stores log attenuation in 8.8 format, values
71 * were only calculated for 6 bits fractional precision, since that is
72 * the most precision offered by the trident hardware.
73 */
74
75static unsigned short log_table[LOG_TABLE_SIZE*2] =
76{
77 4, 0x0604, 19, 0x0600, 34, 0x05fc,
78 49, 0x05f8, 63, 0x05f4, 78, 0x05f0, 93, 0x05ec, 108, 0x05e8,
79 123, 0x05e4, 138, 0x05e0, 153, 0x05dc, 168, 0x05d8, 183, 0x05d4,
80 198, 0x05d0, 213, 0x05cc, 228, 0x05c8, 244, 0x05c4, 259, 0x05c0,
81 274, 0x05bc, 289, 0x05b8, 304, 0x05b4, 320, 0x05b0, 335, 0x05ac,
82 350, 0x05a8, 366, 0x05a4, 381, 0x05a0, 397, 0x059c, 412, 0x0598,
83 428, 0x0594, 443, 0x0590, 459, 0x058c, 474, 0x0588, 490, 0x0584,
84 506, 0x0580, 521, 0x057c, 537, 0x0578, 553, 0x0574, 568, 0x0570,
85 584, 0x056c, 600, 0x0568, 616, 0x0564, 632, 0x0560, 647, 0x055c,
86 663, 0x0558, 679, 0x0554, 695, 0x0550, 711, 0x054c, 727, 0x0548,
87 743, 0x0544, 759, 0x0540, 776, 0x053c, 792, 0x0538, 808, 0x0534,
88 824, 0x0530, 840, 0x052c, 857, 0x0528, 873, 0x0524, 889, 0x0520,
89 906, 0x051c, 922, 0x0518, 938, 0x0514, 955, 0x0510, 971, 0x050c,
90 988, 0x0508, 1004, 0x0504, 1021, 0x0500, 1037, 0x04fc, 1054, 0x04f8,
91 1071, 0x04f4, 1087, 0x04f0, 1104, 0x04ec, 1121, 0x04e8, 1138, 0x04e4,
92 1154, 0x04e0, 1171, 0x04dc, 1188, 0x04d8, 1205, 0x04d4, 1222, 0x04d0,
93 1239, 0x04cc, 1256, 0x04c8, 1273, 0x04c4, 1290, 0x04c0, 1307, 0x04bc,
94 1324, 0x04b8, 1341, 0x04b4, 1358, 0x04b0, 1376, 0x04ac, 1393, 0x04a8,
95 1410, 0x04a4, 1427, 0x04a0, 1445, 0x049c, 1462, 0x0498, 1479, 0x0494,
96 1497, 0x0490, 1514, 0x048c, 1532, 0x0488, 1549, 0x0484, 1567, 0x0480,
97 1584, 0x047c, 1602, 0x0478, 1620, 0x0474, 1637, 0x0470, 1655, 0x046c,
98 1673, 0x0468, 1690, 0x0464, 1708, 0x0460, 1726, 0x045c, 1744, 0x0458,
99 1762, 0x0454, 1780, 0x0450, 1798, 0x044c, 1816, 0x0448, 1834, 0x0444,
100 1852, 0x0440, 1870, 0x043c, 1888, 0x0438, 1906, 0x0434, 1924, 0x0430,
101 1943, 0x042c, 1961, 0x0428, 1979, 0x0424, 1997, 0x0420, 2016, 0x041c,
102 2034, 0x0418, 2053, 0x0414, 2071, 0x0410, 2089, 0x040c, 2108, 0x0408,
103 2127, 0x0404, 2145, 0x0400, 2164, 0x03fc, 2182, 0x03f8, 2201, 0x03f4,
104 2220, 0x03f0, 2239, 0x03ec, 2257, 0x03e8, 2276, 0x03e4, 2295, 0x03e0,
105 2314, 0x03dc, 2333, 0x03d8, 2352, 0x03d4, 2371, 0x03d0, 2390, 0x03cc,
106 2409, 0x03c8, 2428, 0x03c4, 2447, 0x03c0, 2466, 0x03bc, 2485, 0x03b8,
107 2505, 0x03b4, 2524, 0x03b0, 2543, 0x03ac, 2562, 0x03a8, 2582, 0x03a4,
108 2601, 0x03a0, 2621, 0x039c, 2640, 0x0398, 2660, 0x0394, 2679, 0x0390,
109 2699, 0x038c, 2718, 0x0388, 2738, 0x0384, 2758, 0x0380, 2777, 0x037c,
110 2797, 0x0378, 2817, 0x0374, 2837, 0x0370, 2857, 0x036c, 2876, 0x0368,
111 2896, 0x0364, 2916, 0x0360, 2936, 0x035c, 2956, 0x0358, 2976, 0x0354,
112 2997, 0x0350, 3017, 0x034c, 3037, 0x0348, 3057, 0x0344, 3077, 0x0340,
113 3098, 0x033c, 3118, 0x0338, 3138, 0x0334, 3159, 0x0330, 3179, 0x032c,
114 3200, 0x0328, 3220, 0x0324, 3241, 0x0320, 3261, 0x031c, 3282, 0x0318,
115 3303, 0x0314, 3323, 0x0310, 3344, 0x030c, 3365, 0x0308, 3386, 0x0304,
116 3406, 0x0300, 3427, 0x02fc, 3448, 0x02f8, 3469, 0x02f4, 3490, 0x02f0,
117 3511, 0x02ec, 3532, 0x02e8, 3553, 0x02e4, 3575, 0x02e0, 3596, 0x02dc,
118 3617, 0x02d8, 3638, 0x02d4, 3660, 0x02d0, 3681, 0x02cc, 3702, 0x02c8,
119 3724, 0x02c4, 3745, 0x02c0, 3767, 0x02bc, 3788, 0x02b8, 3810, 0x02b4,
120 3831, 0x02b0, 3853, 0x02ac, 3875, 0x02a8, 3896, 0x02a4, 3918, 0x02a0,
121 3940, 0x029c, 3962, 0x0298, 3984, 0x0294, 4006, 0x0290, 4028, 0x028c,
122 4050, 0x0288, 4072, 0x0284, 4094, 0x0280, 4116, 0x027c, 4138, 0x0278,
123 4160, 0x0274, 4182, 0x0270, 4205, 0x026c, 4227, 0x0268, 4249, 0x0264,
124 4272, 0x0260, 4294, 0x025c, 4317, 0x0258, 4339, 0x0254, 4362, 0x0250,
125 4384, 0x024c, 4407, 0x0248, 4430, 0x0244, 4453, 0x0240, 4475, 0x023c,
126 4498, 0x0238, 4521, 0x0234, 4544, 0x0230, 4567, 0x022c, 4590, 0x0228,
127 4613, 0x0224, 4636, 0x0220, 4659, 0x021c, 4682, 0x0218, 4705, 0x0214,
128 4728, 0x0210, 4752, 0x020c, 4775, 0x0208, 4798, 0x0204, 4822, 0x0200,
129 4845, 0x01fc, 4869, 0x01f8, 4892, 0x01f4, 4916, 0x01f0, 4939, 0x01ec,
130 4963, 0x01e8, 4987, 0x01e4, 5010, 0x01e0, 5034, 0x01dc, 5058, 0x01d8,
131 5082, 0x01d4, 5106, 0x01d0, 5130, 0x01cc, 5154, 0x01c8, 5178, 0x01c4,
132 5202, 0x01c0, 5226, 0x01bc, 5250, 0x01b8, 5274, 0x01b4, 5299, 0x01b0,
133 5323, 0x01ac, 5347, 0x01a8, 5372, 0x01a4, 5396, 0x01a0, 5420, 0x019c,
134 5445, 0x0198, 5469, 0x0194, 5494, 0x0190, 5519, 0x018c, 5543, 0x0188,
135 5568, 0x0184, 5593, 0x0180, 5618, 0x017c, 5643, 0x0178, 5668, 0x0174,
136 5692, 0x0170, 5717, 0x016c, 5743, 0x0168, 5768, 0x0164, 5793, 0x0160,
137 5818, 0x015c, 5843, 0x0158, 5868, 0x0154, 5894, 0x0150, 5919, 0x014c,
138 5945, 0x0148, 5970, 0x0144, 5995, 0x0140, 6021, 0x013c, 6047, 0x0138,
139 6072, 0x0134, 6098, 0x0130, 6124, 0x012c, 6149, 0x0128, 6175, 0x0124,
140 6201, 0x0120, 6227, 0x011c, 6253, 0x0118, 6279, 0x0114, 6305, 0x0110,
141 6331, 0x010c, 6357, 0x0108, 6384, 0x0104, 6410, 0x0100, 6436, 0x00fc,
142 6462, 0x00f8, 6489, 0x00f4, 6515, 0x00f0, 6542, 0x00ec, 6568, 0x00e8,
143 6595, 0x00e4, 6621, 0x00e0, 6648, 0x00dc, 6675, 0x00d8, 6702, 0x00d4,
144 6728, 0x00d0, 6755, 0x00cc, 6782, 0x00c8, 6809, 0x00c4, 6836, 0x00c0,
145 6863, 0x00bc, 6890, 0x00b8, 6917, 0x00b4, 6945, 0x00b0, 6972, 0x00ac,
146 6999, 0x00a8, 7027, 0x00a4, 7054, 0x00a0, 7081, 0x009c, 7109, 0x0098,
147 7136, 0x0094, 7164, 0x0090, 7192, 0x008c, 7219, 0x0088, 7247, 0x0084,
148 7275, 0x0080, 7303, 0x007c, 7331, 0x0078, 7359, 0x0074, 7387, 0x0070,
149 7415, 0x006c, 7443, 0x0068, 7471, 0x0064, 7499, 0x0060, 7527, 0x005c,
150 7556, 0x0058, 7584, 0x0054, 7613, 0x0050, 7641, 0x004c, 7669, 0x0048,
151 7698, 0x0044, 7727, 0x0040, 7755, 0x003c, 7784, 0x0038, 7813, 0x0034,
152 7842, 0x0030, 7870, 0x002c, 7899, 0x0028, 7928, 0x0024, 7957, 0x0020,
153 7986, 0x001c, 8016, 0x0018, 8045, 0x0014, 8074, 0x0010, 8103, 0x000c,
154 8133, 0x0008, 8162, 0x0004, 8192, 0x0000
155};
156
157static unsigned short lookup_volume_table( unsigned short value )
158{
159 /* This code is an optimised version of:
160 * int i = 0;
161 * while( volume_table[i*2] < value )
162 * i++;
163 * return volume_table[i*2+1];
164 */
165 unsigned short *ptr = log_table;
166 while( *ptr < value )
167 ptr += 2;
168 return *(ptr+1);
169}
170
171/* this function calculates a 8.8 fixed point logarithmic attenuation
172 * value from a linear volume value in the range 0 to 16384 */
173static unsigned short log_from_linear( unsigned short value )
174{
175 if (value >= 16384)
176 return 0x0000;
177 if (value) {
178 unsigned short result = 0;
179 int v, c;
180 for( c = 0, v = 8192; c < 14; c++, v >>= 1 ) {
181 if( value >= v ) {
182 result += lookup_volume_table( (value - v) << c );
183 return result;
184 }
185 result += 0x0605; /* 6.0205 (result of -20*log10(0.5)) */
186 }
187 }
188 return 0xffff;
189}
190
191/*
192 * Sample handling operations
193 */
194
195static void sample_start(trident_t * trident, snd_trident_voice_t * voice, snd_seq_position_t position);
196static void sample_stop(trident_t * trident, snd_trident_voice_t * voice, snd_seq_stop_mode_t mode);
197static void sample_freq(trident_t * trident, snd_trident_voice_t * voice, snd_seq_frequency_t freq);
198static void sample_volume(trident_t * trident, snd_trident_voice_t * voice, snd_seq_ev_volume_t * volume);
199static void sample_loop(trident_t * trident, snd_trident_voice_t * voice, snd_seq_ev_loop_t * loop);
200static void sample_pos(trident_t * trident, snd_trident_voice_t * voice, snd_seq_position_t position);
201static void sample_private1(trident_t * trident, snd_trident_voice_t * voice, unsigned char *data);
202
203static snd_trident_sample_ops_t sample_ops =
204{
205 sample_start,
206 sample_stop,
207 sample_freq,
208 sample_volume,
209 sample_loop,
210 sample_pos,
211 sample_private1
212};
213
214static void snd_trident_simple_init(snd_trident_voice_t * voice)
215{
216 //voice->handler_wave = interrupt_wave;
217 //voice->handler_volume = interrupt_volume;
218 //voice->handler_effect = interrupt_effect;
219 //voice->volume_change = NULL;
220 voice->sample_ops = &sample_ops;
221}
222
223static void sample_start(trident_t * trident, snd_trident_voice_t * voice, snd_seq_position_t position)
224{
225 simple_instrument_t *simple;
226 snd_seq_kinstr_t *instr;
227 unsigned long flags;
228 unsigned int loop_start, loop_end, sample_start, sample_end, start_offset;
229 unsigned int value;
230 unsigned int shift = 0;
231
232 instr = snd_seq_instr_find(trident->synth.ilist, &voice->instr, 0, 1);
233 if (instr == NULL)
234 return;
235 voice->instr = instr->instr; /* copy ID to speedup aliases */
236 simple = KINSTR_DATA(instr);
237
238 spin_lock_irqsave(&trident->reg_lock, flags);
239
240 if (trident->device == TRIDENT_DEVICE_ID_SI7018)
241 voice->GVSel = 1; /* route to Wave volume */
242
243 voice->CTRL = 0;
244 voice->Alpha = 0;
245 voice->FMS = 0;
246
247 loop_start = simple->loop_start >> 4;
248 loop_end = simple->loop_end >> 4;
249 sample_start = (simple->start + position) >> 4;
250 if( sample_start >= simple->size )
251 sample_start = simple->start >> 4;
252 sample_end = simple->size;
253 start_offset = position >> 4;
254
255 if (simple->format & SIMPLE_WAVE_16BIT) {
256 voice->CTRL |= 8;
257 shift++;
258 }
259 if (simple->format & SIMPLE_WAVE_STEREO) {
260 voice->CTRL |= 4;
261 shift++;
262 }
263 if (!(simple->format & SIMPLE_WAVE_UNSIGNED))
264 voice->CTRL |= 2;
265
266 voice->LBA = simple->address.memory;
267
268 if (simple->format & SIMPLE_WAVE_LOOP) {
269 voice->CTRL |= 1;
270 voice->LBA += loop_start << shift;
271 if( start_offset >= loop_start ) {
272 voice->CSO = start_offset - loop_start;
273 voice->negCSO = 0;
274 } else {
275 voice->CSO = loop_start - start_offset;
276 voice->negCSO = 1;
277 }
278 voice->ESO = loop_end - loop_start - 1;
279 } else {
280 voice->LBA += start_offset << shift;
281 voice->CSO = sample_start;
282 voice->ESO = sample_end - 1;
283 voice->negCSO = 0;
284 }
285
286 if (voice->flags & SNDRV_TRIDENT_VFLG_RUNNING) {
287 snd_trident_stop_voice(trident, voice->number);
288 voice->flags &= ~SNDRV_TRIDENT_VFLG_RUNNING;
289 }
290
291 /* set CSO sign */
292 value = inl(TRID_REG(trident, T4D_SIGN_CSO_A));
293 if( voice->negCSO ) {
294 value |= 1 << (voice->number&31);
295 } else {
296 value &= ~(1 << (voice->number&31));
297 }
298 outl(value,TRID_REG(trident, T4D_SIGN_CSO_A));
299
300 voice->Attribute = 0;
301 snd_trident_write_voice_regs(trident, voice);
302 snd_trident_start_voice(trident, voice->number);
303 voice->flags |= SNDRV_TRIDENT_VFLG_RUNNING;
304 spin_unlock_irqrestore(&trident->reg_lock, flags);
305 snd_seq_instr_free_use(trident->synth.ilist, instr);
306}
307
308static void sample_stop(trident_t * trident, snd_trident_voice_t * voice, snd_seq_stop_mode_t mode)
309{
310 unsigned long flags;
311
312 if (!(voice->flags & SNDRV_TRIDENT_VFLG_RUNNING))
313 return;
314
315 switch (mode) {
316 default:
317 spin_lock_irqsave(&trident->reg_lock, flags);
318 snd_trident_stop_voice(trident, voice->number);
319 voice->flags &= ~SNDRV_TRIDENT_VFLG_RUNNING;
320 spin_unlock_irqrestore(&trident->reg_lock, flags);
321 break;
322 case SAMPLE_STOP_LOOP: /* disable loop only */
323 voice->CTRL &= ~1;
324 spin_lock_irqsave(&trident->reg_lock, flags);
325 outb((unsigned char) voice->number, TRID_REG(trident, T4D_LFO_GC_CIR));
326 outw((((voice->CTRL << 12) | (voice->EC & 0x0fff)) & 0xffff), CH_GVSEL_PAN_VOL_CTRL_EC);
327 spin_unlock_irqrestore(&trident->reg_lock, flags);
328 break;
329 }
330}
331
332static void sample_freq(trident_t * trident, snd_trident_voice_t * voice, snd_seq_frequency_t freq)
333{
334 unsigned long flags;
335 freq >>= 4;
336
337 spin_lock_irqsave(&trident->reg_lock, flags);
338 if (freq == 44100)
339 voice->Delta = 0xeb3;
340 else if (freq == 8000)
341 voice->Delta = 0x2ab;
342 else if (freq == 48000)
343 voice->Delta = 0x1000;
344 else
345 voice->Delta = (((freq << 12) + freq) / 48000) & 0x0000ffff;
346
347 outb((unsigned char) voice->number, TRID_REG(trident, T4D_LFO_GC_CIR));
348 if (trident->device == TRIDENT_DEVICE_ID_NX) {
349 outb((unsigned char) voice->Delta, TRID_REG(trident, CH_NX_DELTA_CSO + 3));
350 outb((unsigned char) (voice->Delta >> 8), TRID_REG(trident, CH_NX_DELTA_ESO + 3));
351 } else {
352 outw((unsigned short) voice->Delta, TRID_REG(trident, CH_DX_ESO_DELTA));
353 }
354
355 spin_unlock_irqrestore(&trident->reg_lock, flags);
356}
357
358static void sample_volume(trident_t * trident, snd_trident_voice_t * voice, snd_seq_ev_volume_t * volume)
359{
360 unsigned long flags;
361 unsigned short value;
362
363 spin_lock_irqsave(&trident->reg_lock, flags);
364 voice->GVSel = 0; /* use global music volume */
365 voice->FMC = 0x03; /* fixme: can we do something useful with FMC? */
366 if (volume->volume >= 0) {
367 volume->volume &= 0x3fff;
368 /* linear volume -> logarithmic attenuation conversion
369 * uses EC register for greater resolution (6.6 bits) than Vol register (5.3 bits)
370 * Vol register used when additional attenuation is required */
371 voice->RVol = 0;
372 voice->CVol = 0;
373 value = log_from_linear( volume->volume );
374 voice->Vol = 0;
375 voice->EC = (value & 0x3fff) >> 2;
376 if (value > 0x3fff) {
377 voice->EC |= 0xfc0;
378 if (value < 0x5f00 )
379 voice->Vol = ((value >> 8) - 0x3f) << 5;
380 else {
381 voice->Vol = 0x3ff;
382 voice->EC = 0xfff;
383 }
384 }
385 }
386 if (volume->lr >= 0) {
387 volume->lr &= 0x3fff;
388 /* approximate linear pan by attenuating channels */
389 if (volume->lr >= 0x2000) { /* attenuate left (pan right) */
390 value = 0x3fff - volume->lr;
391 for (voice->Pan = 0; voice->Pan < 63; voice->Pan++ )
392 if (value >= pan_table[voice->Pan] )
393 break;
394 } else { /* attenuate right (pan left) */
395 for (voice->Pan = 0; voice->Pan < 63; voice->Pan++ )
396 if ((unsigned int)volume->lr >= pan_table[voice->Pan] )
397 break;
398 voice->Pan |= 0x40;
399 }
400 }
401 outb((unsigned char) voice->number, TRID_REG(trident, T4D_LFO_GC_CIR));
402 outl((voice->GVSel << 31) | ((voice->Pan & 0x0000007f) << 24) |
403 ((voice->Vol & 0x000000ff) << 16) | ((voice->CTRL & 0x0000000f) << 12) |
404 (voice->EC & 0x00000fff), TRID_REG(trident, CH_GVSEL_PAN_VOL_CTRL_EC));
405 value = ((voice->FMC & 0x03) << 14) | ((voice->RVol & 0x7f) << 7) | (voice->CVol & 0x7f);
406 outw(value, TRID_REG(trident, CH_DX_FMC_RVOL_CVOL));
407 spin_unlock_irqrestore(&trident->reg_lock, flags);
408}
409
410static void sample_loop(trident_t * trident, snd_trident_voice_t * voice, snd_seq_ev_loop_t * loop)
411{
412 unsigned long flags;
413 simple_instrument_t *simple;
414 snd_seq_kinstr_t *instr;
415 unsigned int loop_start, loop_end;
416
417 instr = snd_seq_instr_find(trident->synth.ilist, &voice->instr, 0, 1);
418 if (instr == NULL)
419 return;
420 voice->instr = instr->instr; /* copy ID to speedup aliases */
421 simple = KINSTR_DATA(instr);
422
423 loop_start = loop->start >> 4;
424 loop_end = loop->end >> 4;
425
426 spin_lock_irqsave(&trident->reg_lock, flags);
427
428 voice->LBA = simple->address.memory + loop_start;
429 voice->CSO = 0;
430 voice->ESO = loop_end - loop_start - 1;
431
432 outb((unsigned char) voice->number, TRID_REG(trident, T4D_LFO_GC_CIR));
433 outb((voice->LBA >> 16), TRID_REG(trident, CH_LBA + 2));
434 outw((voice->LBA & 0xffff), TRID_REG(trident, CH_LBA));
435 if (trident->device == TRIDENT_DEVICE_ID_NX) {
436 outb((voice->ESO >> 16), TRID_REG(trident, CH_NX_DELTA_ESO + 2));
437 outw((voice->ESO & 0xffff), TRID_REG(trident, CH_NX_DELTA_ESO));
438 outb((voice->CSO >> 16), TRID_REG(trident, CH_NX_DELTA_CSO + 2));
439 outw((voice->CSO & 0xffff), TRID_REG(trident, CH_NX_DELTA_CSO));
440 } else {
441 outw((voice->ESO & 0xffff), TRID_REG(trident, CH_DX_ESO_DELTA + 2));
442 outw((voice->CSO & 0xffff), TRID_REG(trident, CH_DX_CSO_ALPHA_FMS + 2));
443 }
444
445 spin_unlock_irqrestore(&trident->reg_lock, flags);
446 snd_seq_instr_free_use(trident->synth.ilist, instr);
447}
448
449static void sample_pos(trident_t * trident, snd_trident_voice_t * voice, snd_seq_position_t position)
450{
451 unsigned long flags;
452 simple_instrument_t *simple;
453 snd_seq_kinstr_t *instr;
454 unsigned int value;
455
456 instr = snd_seq_instr_find(trident->synth.ilist, &voice->instr, 0, 1);
457 if (instr == NULL)
458 return;
459 voice->instr = instr->instr; /* copy ID to speedup aliases */
460 simple = KINSTR_DATA(instr);
461
462 spin_lock_irqsave(&trident->reg_lock, flags);
463
464 if (simple->format & SIMPLE_WAVE_LOOP) {
465 if( position >= simple->loop_start ) {
466 voice->CSO = (position - simple->loop_start) >> 4;
467 voice->negCSO = 0;
468 } else {
469 voice->CSO = (simple->loop_start - position) >> 4;
470 voice->negCSO = 1;
471 }
472 } else {
473 voice->CSO = position >> 4;
474 voice->negCSO = 0;
475 }
476
477 /* set CSO sign */
478 value = inl(TRID_REG(trident, T4D_SIGN_CSO_A));
479 if( voice->negCSO ) {
480 value |= 1 << (voice->number&31);
481 } else {
482 value &= ~(1 << (voice->number&31));
483 }
484 outl(value,TRID_REG(trident, T4D_SIGN_CSO_A));
485
486
487 outb((unsigned char) voice->number, TRID_REG(trident, T4D_LFO_GC_CIR));
488 if (trident->device == TRIDENT_DEVICE_ID_NX) {
489 outw((voice->CSO & 0xffff), TRID_REG(trident, CH_NX_DELTA_CSO));
490 outb((voice->CSO >> 16), TRID_REG(trident, CH_NX_DELTA_CSO + 2));
491 } else {
492 outw((voice->CSO & 0xffff), TRID_REG(trident, CH_DX_CSO_ALPHA_FMS) + 2);
493 }
494
495 spin_unlock_irqrestore(&trident->reg_lock, flags);
496 snd_seq_instr_free_use(trident->synth.ilist, instr);
497}
498
499static void sample_private1(trident_t * trident, snd_trident_voice_t * voice, unsigned char *data)
500{
501}
502
503/*
504 * Memory management / sample loading
505 */
506
507static int snd_trident_simple_put_sample(void *private_data, simple_instrument_t * instr,
508 char __user *data, long len, int atomic)
509{
510 trident_t *trident = private_data;
511 int size = instr->size;
512 int shift = 0;
513
514 if (instr->format & SIMPLE_WAVE_BACKWARD ||
515 instr->format & SIMPLE_WAVE_BIDIR ||
516 instr->format & SIMPLE_WAVE_ULAW)
517 return -EINVAL; /* not supported */
518
519 if (instr->format & SIMPLE_WAVE_16BIT)
520 shift++;
521 if (instr->format & SIMPLE_WAVE_STEREO)
522 shift++;
523 size <<= shift;
524
525 if (trident->synth.current_size + size > trident->synth.max_size)
526 return -ENOMEM;
527
528 if (!access_ok(VERIFY_READ, data, size))
529 return -EFAULT;
530
531 if (trident->tlb.entries) {
532 snd_util_memblk_t *memblk;
533 memblk = snd_trident_synth_alloc(trident, size);
534 if (memblk == NULL)
535 return -ENOMEM;
536 if (snd_trident_synth_copy_from_user(trident, memblk, 0, data, size) ) {
537 snd_trident_synth_free(trident, memblk);
538 return -EFAULT;
539 }
540 instr->address.ptr = (unsigned char*)memblk;
541 instr->address.memory = memblk->offset;
542 } else {
543 struct snd_dma_buffer dmab;
544 if (snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, snd_dma_pci_data(trident->pci),
545 size, &dmab) < 0)
546 return -ENOMEM;
547
548 if (copy_from_user(dmab.area, data, size)) {
549 snd_dma_free_pages(&dmab);
550 return -EFAULT;
551 }
552 instr->address.ptr = dmab.area;
553 instr->address.memory = dmab.addr;
554 }
555
556 trident->synth.current_size += size;
557 return 0;
558}
559
560static int snd_trident_simple_get_sample(void *private_data, simple_instrument_t * instr,
561 char __user *data, long len, int atomic)
562{
563 //trident_t *trident = private_data;
564 int size = instr->size;
565 int shift = 0;
566
567 if (instr->format & SIMPLE_WAVE_16BIT)
568 shift++;
569 if (instr->format & SIMPLE_WAVE_STEREO)
570 shift++;
571 size <<= shift;
572
573 if (!access_ok(VERIFY_WRITE, data, size))
574 return -EFAULT;
575
576 /* FIXME: not implemented yet */
577
578 return -EBUSY;
579}
580
581static int snd_trident_simple_remove_sample(void *private_data, simple_instrument_t * instr,
582 int atomic)
583{
584 trident_t *trident = private_data;
585 int size = instr->size;
586
587 if (instr->format & SIMPLE_WAVE_16BIT)
588 size <<= 1;
589 if (instr->format & SIMPLE_WAVE_STEREO)
590 size <<= 1;
591
592 if (trident->tlb.entries) {
593 snd_util_memblk_t *memblk = (snd_util_memblk_t*)instr->address.ptr;
594 if (memblk)
595 snd_trident_synth_free(trident, memblk);
596 else
597 return -EFAULT;
598 } else {
599 struct snd_dma_buffer dmab;
600 dmab.dev.type = SNDRV_DMA_TYPE_DEV;
601 dmab.dev.dev = snd_dma_pci_data(trident->pci);
602 dmab.area = instr->address.ptr;
603 dmab.addr = instr->address.memory;
604 dmab.bytes = size;
605 snd_dma_free_pages(&dmab);
606 }
607
608 trident->synth.current_size -= size;
609 if (trident->synth.current_size < 0) /* shouldn't need this check... */
610 trident->synth.current_size = 0;
611
612 return 0;
613}
614
615static void select_instrument(trident_t * trident, snd_trident_voice_t * v)
616{
617 snd_seq_kinstr_t *instr;
618 instr = snd_seq_instr_find(trident->synth.ilist, &v->instr, 0, 1);
619 if (instr != NULL) {
620 if (instr->ops) {
621 if (!strcmp(instr->ops->instr_type, SNDRV_SEQ_INSTR_ID_SIMPLE))
622 snd_trident_simple_init(v);
623 }
624 snd_seq_instr_free_use(trident->synth.ilist, instr);
625 }
626}
627
628/*
629
630 */
631
632static void event_sample(snd_seq_event_t * ev, snd_trident_port_t * p, snd_trident_voice_t * v)
633{
634 if (v->sample_ops && v->sample_ops->sample_stop)
635 v->sample_ops->sample_stop(p->trident, v, SAMPLE_STOP_IMMEDIATELY);
636 v->instr.std = ev->data.sample.param.sample.std;
637 if (v->instr.std & 0xff000000) { /* private instrument */
638 v->instr.std &= 0x00ffffff;
639 v->instr.std |= (unsigned int)ev->source.client << 24;
640 }
641 v->instr.bank = ev->data.sample.param.sample.bank;
642 v->instr.prg = ev->data.sample.param.sample.prg;
643 select_instrument(p->trident, v);
644}
645
646static void event_cluster(snd_seq_event_t * ev, snd_trident_port_t * p, snd_trident_voice_t * v)
647{
648 if (v->sample_ops && v->sample_ops->sample_stop)
649 v->sample_ops->sample_stop(p->trident, v, SAMPLE_STOP_IMMEDIATELY);
650 v->instr.cluster = ev->data.sample.param.cluster.cluster;
651 select_instrument(p->trident, v);
652}
653
654static void event_start(snd_seq_event_t * ev, snd_trident_port_t * p, snd_trident_voice_t * v)
655{
656 if (v->sample_ops && v->sample_ops->sample_start)
657 v->sample_ops->sample_start(p->trident, v, ev->data.sample.param.position);
658}
659
660static void event_stop(snd_seq_event_t * ev, snd_trident_port_t * p, snd_trident_voice_t * v)
661{
662 if (v->sample_ops && v->sample_ops->sample_stop)
663 v->sample_ops->sample_stop(p->trident, v, ev->data.sample.param.stop_mode);
664}
665
666static void event_freq(snd_seq_event_t * ev, snd_trident_port_t * p, snd_trident_voice_t * v)
667{
668 if (v->sample_ops && v->sample_ops->sample_freq)
669 v->sample_ops->sample_freq(p->trident, v, ev->data.sample.param.frequency);
670}
671
672static void event_volume(snd_seq_event_t * ev, snd_trident_port_t * p, snd_trident_voice_t * v)
673{
674 if (v->sample_ops && v->sample_ops->sample_volume)
675 v->sample_ops->sample_volume(p->trident, v, &ev->data.sample.param.volume);
676}
677
678static void event_loop(snd_seq_event_t * ev, snd_trident_port_t * p, snd_trident_voice_t * v)
679{
680 if (v->sample_ops && v->sample_ops->sample_loop)
681 v->sample_ops->sample_loop(p->trident, v, &ev->data.sample.param.loop);
682}
683
684static void event_position(snd_seq_event_t * ev, snd_trident_port_t * p, snd_trident_voice_t * v)
685{
686 if (v->sample_ops && v->sample_ops->sample_pos)
687 v->sample_ops->sample_pos(p->trident, v, ev->data.sample.param.position);
688}
689
690static void event_private1(snd_seq_event_t * ev, snd_trident_port_t * p, snd_trident_voice_t * v)
691{
692 if (v->sample_ops && v->sample_ops->sample_private1)
693 v->sample_ops->sample_private1(p->trident, v, (unsigned char *) &ev->data.sample.param.raw8);
694}
695
696typedef void (trident_sample_event_handler_t) (snd_seq_event_t * ev, snd_trident_port_t * p, snd_trident_voice_t * v);
697
698static trident_sample_event_handler_t *trident_sample_event_handlers[9] =
699{
700 event_sample,
701 event_cluster,
702 event_start,
703 event_stop,
704 event_freq,
705 event_volume,
706 event_loop,
707 event_position,
708 event_private1
709};
710
711static void snd_trident_sample_event(snd_seq_event_t * ev, snd_trident_port_t * p)
712{
713 int idx, voice;
714 trident_t *trident = p->trident;
715 snd_trident_voice_t *v;
716 unsigned long flags;
717
718 idx = ev->type - SNDRV_SEQ_EVENT_SAMPLE;
719 if (idx < 0 || idx > 8)
720 return;
721 for (voice = 0; voice < 64; voice++) {
722 v = &trident->synth.voices[voice];
723 if (v->use && v->client == ev->source.client &&
724 v->port == ev->source.port &&
725 v->index == ev->data.sample.channel) {
726 spin_lock_irqsave(&trident->event_lock, flags);
727 trident_sample_event_handlers[idx] (ev, p, v);
728 spin_unlock_irqrestore(&trident->event_lock, flags);
729 return;
730 }
731 }
732}
733
734/*
735
736 */
737
738static void snd_trident_synth_free_voices(trident_t * trident, int client, int port)
739{
740 int idx;
741 snd_trident_voice_t *voice;
742
743 for (idx = 0; idx < 32; idx++) {
744 voice = &trident->synth.voices[idx];
745 if (voice->use && voice->client == client && voice->port == port)
746 snd_trident_free_voice(trident, voice);
747 }
748}
749
750static int snd_trident_synth_use(void *private_data, snd_seq_port_subscribe_t * info)
751{
752 snd_trident_port_t *port = (snd_trident_port_t *) private_data;
753 trident_t *trident = port->trident;
754 snd_trident_voice_t *voice;
755 unsigned int idx;
756 unsigned long flags;
757
758 if (info->voices > 32)
759 return -EINVAL;
760 spin_lock_irqsave(&trident->reg_lock, flags);
761 for (idx = 0; idx < info->voices; idx++) {
762 voice = snd_trident_alloc_voice(trident, SNDRV_TRIDENT_VOICE_TYPE_SYNTH, info->sender.client, info->sender.port);
763 if (voice == NULL) {
764 snd_trident_synth_free_voices(trident, info->sender.client, info->sender.port);
765 spin_unlock_irqrestore(&trident->reg_lock, flags);
766 return -EBUSY;
767 }
768 voice->index = idx;
769 voice->Vol = 0x3ff;
770 voice->EC = 0x0fff;
771 }
772#if 0
773 for (idx = 0; idx < info->midi_voices; idx++) {
774 port->midi_has_voices = 1;
775 voice = snd_trident_alloc_voice(trident, SNDRV_TRIDENT_VOICE_TYPE_MIDI, info->sender.client, info->sender.port);
776 if (voice == NULL) {
777 snd_trident_synth_free_voices(trident, info->sender.client, info->sender.port);
778 spin_unlock_irqrestore(&trident->reg_lock, flags);
779 return -EBUSY;
780 }
781 voice->Vol = 0x3ff;
782 voice->EC = 0x0fff;
783 }
784#endif
785 spin_unlock_irqrestore(&trident->reg_lock, flags);
786 return 0;
787}
788
789static int snd_trident_synth_unuse(void *private_data, snd_seq_port_subscribe_t * info)
790{
791 snd_trident_port_t *port = (snd_trident_port_t *) private_data;
792 trident_t *trident = port->trident;
793 unsigned long flags;
794
795 spin_lock_irqsave(&trident->reg_lock, flags);
796 snd_trident_synth_free_voices(trident, info->sender.client, info->sender.port);
797 spin_unlock_irqrestore(&trident->reg_lock, flags);
798 return 0;
799}
800
801/*
802
803 */
804
805static void snd_trident_synth_free_private_instruments(snd_trident_port_t * p, int client)
806{
807 snd_seq_instr_header_t ifree;
808
809 memset(&ifree, 0, sizeof(ifree));
810 ifree.cmd = SNDRV_SEQ_INSTR_FREE_CMD_PRIVATE;
811 snd_seq_instr_list_free_cond(p->trident->synth.ilist, &ifree, client, 0);
812}
813
814static int snd_trident_synth_event_input(snd_seq_event_t * ev, int direct, void *private_data, int atomic, int hop)
815{
816 snd_trident_port_t *p = (snd_trident_port_t *) private_data;
817
818 if (p == NULL)
819 return -EINVAL;
820 if (ev->type >= SNDRV_SEQ_EVENT_SAMPLE &&
821 ev->type <= SNDRV_SEQ_EVENT_SAMPLE_PRIVATE1) {
822 snd_trident_sample_event(ev, p);
823 return 0;
824 }
825 if (ev->source.client == SNDRV_SEQ_CLIENT_SYSTEM &&
826 ev->source.port == SNDRV_SEQ_PORT_SYSTEM_ANNOUNCE) {
827 if (ev->type == SNDRV_SEQ_EVENT_CLIENT_EXIT) {
828 snd_trident_synth_free_private_instruments(p, ev->data.addr.client);
829 return 0;
830 }
831 }
832 if (direct) {
833 if (ev->type >= SNDRV_SEQ_EVENT_INSTR_BEGIN) {
834 snd_seq_instr_event(&p->trident->synth.simple_ops.kops,
835 p->trident->synth.ilist, ev,
836 p->trident->synth.seq_client, atomic, hop);
837 return 0;
838 }
839 }
840 return 0;
841}
842
843static void snd_trident_synth_instr_notify(void *private_data,
844 snd_seq_kinstr_t * instr,
845 int what)
846{
847 int idx;
848 trident_t *trident = private_data;
849 snd_trident_voice_t *pvoice;
850 unsigned long flags;
851
852 spin_lock_irqsave(&trident->event_lock, flags);
853 for (idx = 0; idx < 64; idx++) {
854 pvoice = &trident->synth.voices[idx];
855 if (pvoice->use && !memcmp(&pvoice->instr, &instr->instr, sizeof(pvoice->instr))) {
856 if (pvoice->sample_ops && pvoice->sample_ops->sample_stop) {
857 pvoice->sample_ops->sample_stop(trident, pvoice, SAMPLE_STOP_IMMEDIATELY);
858 } else {
859 snd_trident_stop_voice(trident, pvoice->number);
860 pvoice->flags &= ~SNDRV_TRIDENT_VFLG_RUNNING;
861 }
862 }
863 }
864 spin_unlock_irqrestore(&trident->event_lock, flags);
865}
866
867/*
868
869 */
870
871static void snd_trident_synth_free_port(void *private_data)
872{
873 snd_trident_port_t *p = (snd_trident_port_t *) private_data;
874
875 if (p)
876 snd_midi_channel_free_set(p->chset);
877}
878
879static int snd_trident_synth_create_port(trident_t * trident, int idx)
880{
881 snd_trident_port_t *p;
882 snd_seq_port_callback_t callbacks;
883 char name[32];
884 char *str;
885 int result;
886
887 p = &trident->synth.seq_ports[idx];
888 p->chset = snd_midi_channel_alloc_set(16);
889 if (p->chset == NULL)
890 return -ENOMEM;
891 p->chset->private_data = p;
892 p->trident = trident;
893 p->client = trident->synth.seq_client;
894
895 memset(&callbacks, 0, sizeof(callbacks));
896 callbacks.owner = THIS_MODULE;
897 callbacks.use = snd_trident_synth_use;
898 callbacks.unuse = snd_trident_synth_unuse;
899 callbacks.event_input = snd_trident_synth_event_input;
900 callbacks.private_free = snd_trident_synth_free_port;
901 callbacks.private_data = p;
902
903 str = "???";
904 switch (trident->device) {
905 case TRIDENT_DEVICE_ID_DX: str = "Trident 4DWave-DX"; break;
906 case TRIDENT_DEVICE_ID_NX: str = "Trident 4DWave-NX"; break;
907 case TRIDENT_DEVICE_ID_SI7018: str = "SiS 7018"; break;
908 }
909 sprintf(name, "%s port %i", str, idx);
910 p->chset->port = snd_seq_event_port_attach(trident->synth.seq_client,
911 &callbacks,
912 SNDRV_SEQ_PORT_CAP_WRITE | SNDRV_SEQ_PORT_CAP_SUBS_WRITE,
913 SNDRV_SEQ_PORT_TYPE_DIRECT_SAMPLE |
914 SNDRV_SEQ_PORT_TYPE_SYNTH,
915 16, 0,
916 name);
917 if (p->chset->port < 0) {
918 result = p->chset->port;
919 snd_trident_synth_free_port(p);
920 return result;
921 }
922 p->port = p->chset->port;
923 return 0;
924}
925
926/*
927
928 */
929
930static int snd_trident_synth_new_device(snd_seq_device_t *dev)
931{
932 trident_t *trident;
933 int client, i;
934 snd_seq_client_callback_t callbacks;
935 snd_seq_client_info_t cinfo;
936 snd_seq_port_subscribe_t sub;
937 snd_simple_ops_t *simpleops;
938 char *str;
939
940 trident = *(trident_t **)SNDRV_SEQ_DEVICE_ARGPTR(dev);
941 if (trident == NULL)
942 return -EINVAL;
943
944 trident->synth.seq_client = -1;
945
946 /* allocate new client */
947 memset(&callbacks, 0, sizeof(callbacks));
948 callbacks.private_data = trident;
949 callbacks.allow_output = callbacks.allow_input = 1;
950 client = trident->synth.seq_client =
951 snd_seq_create_kernel_client(trident->card, 1, &callbacks);
952 if (client < 0)
953 return client;
954
955 /* change name of client */
956 memset(&cinfo, 0, sizeof(cinfo));
957 cinfo.client = client;
958 cinfo.type = KERNEL_CLIENT;
959 str = "???";
960 switch (trident->device) {
961 case TRIDENT_DEVICE_ID_DX: str = "Trident 4DWave-DX"; break;
962 case TRIDENT_DEVICE_ID_NX: str = "Trident 4DWave-NX"; break;
963 case TRIDENT_DEVICE_ID_SI7018: str = "SiS 7018"; break;
964 }
965 sprintf(cinfo.name, str);
966 snd_seq_kernel_client_ctl(client, SNDRV_SEQ_IOCTL_SET_CLIENT_INFO, &cinfo);
967
968 for (i = 0; i < 4; i++)
969 snd_trident_synth_create_port(trident, i);
970
971 trident->synth.ilist = snd_seq_instr_list_new();
972 if (trident->synth.ilist == NULL) {
973 snd_seq_delete_kernel_client(client);
974 trident->synth.seq_client = -1;
975 return -ENOMEM;
976 }
977 trident->synth.ilist->flags = SNDRV_SEQ_INSTR_FLG_DIRECT;
978
979 simpleops = &trident->synth.simple_ops;
980 snd_seq_simple_init(simpleops, trident, NULL);
981 simpleops->put_sample = snd_trident_simple_put_sample;
982 simpleops->get_sample = snd_trident_simple_get_sample;
983 simpleops->remove_sample = snd_trident_simple_remove_sample;
984 simpleops->notify = snd_trident_synth_instr_notify;
985
986 memset(&sub, 0, sizeof(sub));
987 sub.sender.client = SNDRV_SEQ_CLIENT_SYSTEM;
988 sub.sender.port = SNDRV_SEQ_PORT_SYSTEM_ANNOUNCE;
989 sub.dest.client = client;
990 sub.dest.port = 0;
991 snd_seq_kernel_client_ctl(client, SNDRV_SEQ_IOCTL_SUBSCRIBE_PORT, &sub);
992
993 return 0;
994}
995
996static int snd_trident_synth_delete_device(snd_seq_device_t *dev)
997{
998 trident_t *trident;
999
1000 trident = *(trident_t **)SNDRV_SEQ_DEVICE_ARGPTR(dev);
1001 if (trident == NULL)
1002 return -EINVAL;
1003
1004 if (trident->synth.seq_client >= 0) {
1005 snd_seq_delete_kernel_client(trident->synth.seq_client);
1006 trident->synth.seq_client = -1;
1007 }
1008 if (trident->synth.ilist)
1009 snd_seq_instr_list_free(&trident->synth.ilist);
1010 return 0;
1011}
1012
1013static int __init alsa_trident_synth_init(void)
1014{
1015 static snd_seq_dev_ops_t ops =
1016 {
1017 snd_trident_synth_new_device,
1018 snd_trident_synth_delete_device
1019 };
1020
1021 return snd_seq_device_register_driver(SNDRV_SEQ_DEV_ID_TRIDENT, &ops,
1022 sizeof(trident_t*));
1023}
1024
1025static void __exit alsa_trident_synth_exit(void)
1026{
1027 snd_seq_device_unregister_driver(SNDRV_SEQ_DEV_ID_TRIDENT);
1028}
1029
1030module_init(alsa_trident_synth_init)
1031module_exit(alsa_trident_synth_exit)