~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/sound/pci/trident/trident_main.c

Version: ~ [ linux-5.2-rc1 ] ~ [ linux-5.1.2 ] ~ [ linux-5.0.16 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.43 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.119 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.176 ] ~ [ linux-4.8.17 ] ~ [ linux-4.7.10 ] ~ [ linux-4.6.7 ] ~ [ linux-4.5.7 ] ~ [ linux-4.4.179 ] ~ [ linux-4.3.6 ] ~ [ linux-4.2.8 ] ~ [ linux-4.1.52 ] ~ [ linux-4.0.9 ] ~ [ linux-3.19.8 ] ~ [ linux-3.18.139 ] ~ [ linux-3.17.8 ] ~ [ linux-3.16.67 ] ~ [ linux-3.15.10 ] ~ [ linux-3.14.79 ] ~ [ linux-3.13.11 ] ~ [ linux-3.12.74 ] ~ [ linux-3.11.10 ] ~ [ linux-3.10.108 ] ~ [ linux-3.9.11 ] ~ [ linux-3.8.13 ] ~ [ linux-3.7.10 ] ~ [ linux-3.6.11 ] ~ [ linux-3.5.7 ] ~ [ linux-3.4.113 ] ~ [ linux-3.3.8 ] ~ [ linux-3.2.102 ] ~ [ linux-3.1.10 ] ~ [ linux-3.0.101 ] ~ [ linux-2.6.39.4 ] ~ [ linux-2.6.38.8 ] ~ [ linux-2.6.37.6 ] ~ [ linux-2.6.36.4 ] ~ [ linux-2.6.35.14 ] ~ [ linux-2.6.34.15 ] ~ [ linux-2.6.33.20 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.5 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  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 
 47 #define chip_t trident_t
 48 
 49 static int snd_trident_pcm_mixer_build(trident_t *trident, snd_trident_voice_t * voice, snd_pcm_substream_t *substream);
 50 static int snd_trident_pcm_mixer_free(trident_t *trident, snd_trident_voice_t * voice, snd_pcm_substream_t *substream);
 51 static irqreturn_t snd_trident_interrupt(int irq, void *dev_id, struct pt_regs *regs);
 52 #ifdef CONFIG_PM
 53 static int snd_trident_set_power_state(snd_card_t *card, unsigned int power_state);
 54 #endif
 55 static int snd_trident_sis_reset(trident_t *trident);
 56 
 57 /*
 58  *  common I/O routines
 59  */
 60 
 61 
 62 #if 0
 63 static void snd_trident_print_voice_regs(trident_t *trident, int voice)
 64 {
 65         unsigned int val, tmp;
 66 
 67         printk("Trident voice %i:\n", voice);
 68         outb(voice, TRID_REG(trident, T4D_LFO_GC_CIR));
 69         val = inl(TRID_REG(trident, CH_LBA));
 70         printk("LBA: 0x%x\n", val);
 71         val = inl(TRID_REG(trident, CH_GVSEL_PAN_VOL_CTRL_EC));
 72         printk("GVSel: %i\n", val >> 31);
 73         printk("Pan: 0x%x\n", (val >> 24) & 0x7f);
 74         printk("Vol: 0x%x\n", (val >> 16) & 0xff);
 75         printk("CTRL: 0x%x\n", (val >> 12) & 0x0f);
 76         printk("EC: 0x%x\n", val & 0x0fff);
 77         if (trident->device != TRIDENT_DEVICE_ID_NX) {
 78                 val = inl(TRID_REG(trident, CH_DX_CSO_ALPHA_FMS));
 79                 printk("CSO: 0x%x\n", val >> 16);
 80                 printk("Alpha: 0x%x\n", (val >> 4) & 0x0fff);
 81                 printk("FMS: 0x%x\n", val & 0x0f);
 82                 val = inl(TRID_REG(trident, CH_DX_ESO_DELTA));
 83                 printk("ESO: 0x%x\n", val >> 16);
 84                 printk("Delta: 0x%x\n", val & 0xffff);
 85                 val = inl(TRID_REG(trident, CH_DX_FMC_RVOL_CVOL));
 86         } else {                // TRIDENT_DEVICE_ID_NX
 87                 val = inl(TRID_REG(trident, CH_NX_DELTA_CSO));
 88                 tmp = (val >> 24) & 0xff;
 89                 printk("CSO: 0x%x\n", val & 0x00ffffff);
 90                 val = inl(TRID_REG(trident, CH_NX_DELTA_ESO));
 91                 tmp |= (val >> 16) & 0xff00;
 92                 printk("Delta: 0x%x\n", tmp);
 93                 printk("ESO: 0x%x\n", val & 0x00ffffff);
 94                 val = inl(TRID_REG(trident, CH_NX_ALPHA_FMS_FMC_RVOL_CVOL));
 95                 printk("Alpha: 0x%x\n", val >> 20);
 96                 printk("FMS: 0x%x\n", (val >> 16) & 0x0f);
 97         }
 98         printk("FMC: 0x%x\n", (val >> 14) & 3);
 99         printk("RVol: 0x%x\n", (val >> 7) & 0x7f);
100         printk("CVol: 0x%x\n", val & 0x7f);
101 }
102 #endif
103 
104 /*---------------------------------------------------------------------------
105    unsigned short snd_trident_codec_read(ac97_t *ac97, unsigned short reg)
106   
107    Description: This routine will do all of the reading from the external
108                 CODEC (AC97).
109   
110    Parameters:  ac97 - ac97 codec structure
111                 reg - CODEC register index, from AC97 Hal.
112  
113    returns:     16 bit value read from the AC97.
114   
115   ---------------------------------------------------------------------------*/
116 static unsigned short snd_trident_codec_read(ac97_t *ac97, unsigned short reg)
117 {
118         unsigned int data = 0, treg;
119         unsigned short count = 0xffff;
120         unsigned long flags;
121         trident_t *trident = snd_magic_cast(trident_t, ac97->private_data, return -ENXIO);
122 
123         spin_lock_irqsave(&trident->reg_lock, flags);
124         if (trident->device == TRIDENT_DEVICE_ID_DX) {
125                 data = (DX_AC97_BUSY_READ | (reg & 0x000000ff));
126                 outl(data, TRID_REG(trident, DX_ACR1_AC97_R));
127                 do {
128                         data = inl(TRID_REG(trident, DX_ACR1_AC97_R));
129                         if ((data & DX_AC97_BUSY_READ) == 0)
130                                 break;
131                 } while (--count);
132         } else if (trident->device == TRIDENT_DEVICE_ID_NX) {
133                 data = (NX_AC97_BUSY_READ | (reg & 0x000000ff));
134                 treg = ac97->num == 0 ? NX_ACR2_AC97_R_PRIMARY : NX_ACR3_AC97_R_SECONDARY;
135                 outl(data, TRID_REG(trident, treg));
136                 do {
137                         data = inl(TRID_REG(trident, treg));
138                         if ((data & 0x00000C00) == 0)
139                                 break;
140                 } while (--count);
141         } else if (trident->device == TRIDENT_DEVICE_ID_SI7018) {
142                 data = SI_AC97_BUSY_READ | SI_AC97_AUDIO_BUSY | (reg & 0x000000ff);
143                 if (ac97->num == 1)
144                         data |= SI_AC97_SECONDARY;
145                 outl(data, TRID_REG(trident, SI_AC97_READ));
146                 do {
147                         data = inl(TRID_REG(trident, SI_AC97_READ));
148                         if ((data & (SI_AC97_BUSY_READ)) == 0)
149                                 break;
150                 } while (--count);
151         }
152 
153         if (count == 0 && !trident->ac97_detect) {
154                 snd_printk("ac97 codec read TIMEOUT [0x%x/0x%x]!!!\n", reg, data);
155                 data = 0;
156         }
157 
158         spin_unlock_irqrestore(&trident->reg_lock, flags);
159         return ((unsigned short) (data >> 16));
160 }
161 
162 /*---------------------------------------------------------------------------
163    void snd_trident_codec_write(ac97_t *ac97, unsigned short reg, unsigned short wdata)
164   
165    Description: This routine will do all of the writing to the external
166                 CODEC (AC97).
167   
168    Parameters:  ac97 - ac97 codec structure
169                 reg - CODEC register index, from AC97 Hal.
170                 data  - Lower 16 bits are the data to write to CODEC.
171   
172    returns:     TRUE if everything went ok, else FALSE.
173   
174   ---------------------------------------------------------------------------*/
175 static void snd_trident_codec_write(ac97_t *ac97, unsigned short reg, unsigned short wdata)
176 {
177         unsigned int address, data;
178         unsigned short count = 0xffff;
179         unsigned long flags;
180         trident_t *trident = snd_magic_cast(trident_t, ac97->private_data, return);
181 
182         data = ((unsigned long) wdata) << 16;
183 
184         spin_lock_irqsave(&trident->reg_lock, flags);
185         if (trident->device == TRIDENT_DEVICE_ID_DX) {
186                 address = DX_ACR0_AC97_W;
187 
188                 /* read AC-97 write register status */
189                 do {
190                         if ((inw(TRID_REG(trident, address)) & DX_AC97_BUSY_WRITE) == 0)
191                                 break;
192                 } while (--count);
193 
194                 data |= (DX_AC97_BUSY_WRITE | (reg & 0x000000ff));
195         } else if (trident->device == TRIDENT_DEVICE_ID_NX) {
196                 address = NX_ACR1_AC97_W;
197 
198                 /* read AC-97 write register status */
199                 do {
200                         if ((inw(TRID_REG(trident, address)) & NX_AC97_BUSY_WRITE) == 0)
201                                 break;
202                 } while (--count);
203 
204                 data |= (NX_AC97_BUSY_WRITE | (ac97->num << 8) | (reg & 0x000000ff));
205         } else if (trident->device == TRIDENT_DEVICE_ID_SI7018) {
206                 address = SI_AC97_WRITE;
207 
208                 /* read AC-97 write register status */
209                 do {
210                         if ((inw(TRID_REG(trident, address)) & (SI_AC97_BUSY_WRITE)) == 0)
211                                 break;
212                 } while (--count);
213 
214                 data |= SI_AC97_BUSY_WRITE | SI_AC97_AUDIO_BUSY | (reg & 0x000000ff);
215                 if (ac97->num == 1)
216                         data |= SI_AC97_SECONDARY;
217         } else {
218                 address = 0;    /* keep GCC happy */
219                 count = 0;      /* return */
220         }
221 
222         if (count == 0) {
223                 spin_unlock_irqrestore(&trident->reg_lock, flags);
224                 return;
225         }
226         outl(data, TRID_REG(trident, address));
227         spin_unlock_irqrestore(&trident->reg_lock, flags);
228 }
229 
230 /*---------------------------------------------------------------------------
231    void snd_trident_enable_eso(trident_t *trident)
232   
233    Description: This routine will enable end of loop interrupts.
234                 End of loop interrupts will occur when a running
235                 channel reaches ESO.
236                 Also enables middle of loop interrupts.
237   
238    Parameters:  trident - pointer to target device class for 4DWave.
239   
240   ---------------------------------------------------------------------------*/
241 
242 static void snd_trident_enable_eso(trident_t * trident)
243 {
244         unsigned int val;
245 
246         val = inl(TRID_REG(trident, T4D_LFO_GC_CIR));
247         val |= ENDLP_IE;
248         val |= MIDLP_IE;
249         if (trident->device == TRIDENT_DEVICE_ID_SI7018)
250                 val |= BANK_B_EN;
251         outl(val, TRID_REG(trident, T4D_LFO_GC_CIR));
252 }
253 
254 /*---------------------------------------------------------------------------
255    void snd_trident_disable_eso(trident_t *trident)
256   
257    Description: This routine will disable end of loop interrupts.
258                 End of loop interrupts will occur when a running
259                 channel reaches ESO.
260                 Also disables middle of loop interrupts.
261   
262    Parameters:  
263                 trident - pointer to target device class for 4DWave.
264   
265    returns:     TRUE if everything went ok, else FALSE.
266   
267   ---------------------------------------------------------------------------*/
268 
269 static void snd_trident_disable_eso(trident_t * trident)
270 {
271         unsigned int tmp;
272 
273         tmp = inl(TRID_REG(trident, T4D_LFO_GC_CIR));
274         tmp &= ~ENDLP_IE;
275         tmp &= ~MIDLP_IE;
276         outl(tmp, TRID_REG(trident, T4D_LFO_GC_CIR));
277 }
278 
279 /*---------------------------------------------------------------------------
280    void snd_trident_start_voice(trident_t * trident, unsigned int voice)
281 
282     Description: Start a voice, any channel 0 thru 63.
283                  This routine automatically handles the fact that there are
284                  more than 32 channels available.
285 
286     Parameters : voice - Voice number 0 thru n.
287                  trident - pointer to target device class for 4DWave.
288 
289     Return Value: None.
290 
291   ---------------------------------------------------------------------------*/
292 
293 void snd_trident_start_voice(trident_t * trident, unsigned int voice)
294 {
295         unsigned int mask = 1 << (voice & 0x1f);
296         unsigned int reg = (voice & 0x20) ? T4D_START_B : T4D_START_A;
297 
298         outl(mask, TRID_REG(trident, reg));
299 }
300 
301 /*---------------------------------------------------------------------------
302    void snd_trident_stop_voice(trident_t * trident, unsigned int voice)
303 
304     Description: Stop a voice, any channel 0 thru 63.
305                  This routine automatically handles the fact that there are
306                  more than 32 channels available.
307 
308     Parameters : voice - Voice number 0 thru n.
309                  trident - pointer to target device class for 4DWave.
310 
311     Return Value: None.
312 
313   ---------------------------------------------------------------------------*/
314 
315 void snd_trident_stop_voice(trident_t * trident, unsigned int voice)
316 {
317         unsigned int mask = 1 << (voice & 0x1f);
318         unsigned int reg = (voice & 0x20) ? T4D_STOP_B : T4D_STOP_A;
319 
320         outl(mask, TRID_REG(trident, reg));
321 }
322 
323 /*---------------------------------------------------------------------------
324     int snd_trident_allocate_pcm_channel(trident_t *trident)
325   
326     Description: Allocate hardware channel in Bank B (32-63).
327   
328     Parameters :  trident - pointer to target device class for 4DWave.
329   
330     Return Value: hardware channel - 32-63 or -1 when no channel is available
331   
332   ---------------------------------------------------------------------------*/
333 
334 static int snd_trident_allocate_pcm_channel(trident_t * trident)
335 {
336         int idx;
337 
338         if (trident->ChanPCMcnt >= trident->ChanPCM)
339                 return -1;
340         for (idx = 31; idx >= 0; idx--) {
341                 if (!(trident->ChanMap[T4D_BANK_B] & (1 << idx))) {
342                         trident->ChanMap[T4D_BANK_B] |= 1 << idx;
343                         trident->ChanPCMcnt++;
344                         return idx + 32;
345                 }
346         }
347         return -1;
348 }
349 
350 /*---------------------------------------------------------------------------
351     void snd_trident_free_pcm_channel(int channel)
352   
353     Description: Free hardware channel in Bank B (32-63)
354   
355     Parameters :  trident - pointer to target device class for 4DWave.
356                   channel - hardware channel number 0-63
357   
358     Return Value: none
359   
360   ---------------------------------------------------------------------------*/
361 
362 static void snd_trident_free_pcm_channel(trident_t *trident, int channel)
363 {
364         if (channel < 32 || channel > 63)
365                 return;
366         channel &= 0x1f;
367         if (trident->ChanMap[T4D_BANK_B] & (1 << channel)) {
368                 trident->ChanMap[T4D_BANK_B] &= ~(1 << channel);
369                 trident->ChanPCMcnt--;
370         }
371 }
372 
373 /*---------------------------------------------------------------------------
374     unsigned int snd_trident_allocate_synth_channel(void)
375   
376     Description: Allocate hardware channel in Bank A (0-31).
377   
378     Parameters :  trident - pointer to target device class for 4DWave.
379   
380     Return Value: hardware channel - 0-31 or -1 when no channel is available
381   
382   ---------------------------------------------------------------------------*/
383 
384 static int snd_trident_allocate_synth_channel(trident_t * trident)
385 {
386         int idx;
387 
388         for (idx = 31; idx >= 0; idx--) {
389                 if (!(trident->ChanMap[T4D_BANK_A] & (1 << idx))) {
390                         trident->ChanMap[T4D_BANK_A] |= 1 << idx;
391                         trident->synth.ChanSynthCount++;
392                         return idx;
393                 }
394         }
395         return -1;
396 }
397 
398 /*---------------------------------------------------------------------------
399     void snd_trident_free_synth_channel( int channel )
400   
401     Description: Free hardware channel in Bank B (0-31).
402   
403     Parameters :  trident - pointer to target device class for 4DWave.
404                   channel - hardware channel number 0-63
405   
406     Return Value: none
407   
408   ---------------------------------------------------------------------------*/
409 
410 static void snd_trident_free_synth_channel(trident_t *trident, int channel)
411 {
412         if (channel < 0 || channel > 31)
413                 return;
414         channel &= 0x1f;
415         if (trident->ChanMap[T4D_BANK_A] & (1 << channel)) {
416                 trident->ChanMap[T4D_BANK_A] &= ~(1 << channel);
417                 trident->synth.ChanSynthCount--;
418         }
419 }
420 
421 /*---------------------------------------------------------------------------
422    snd_trident_write_voice_regs
423   
424    Description: This routine will complete and write the 5 hardware channel
425                 registers to hardware.
426   
427    Paramters:   trident - pointer to target device class for 4DWave.
428                 voice - synthesizer voice structure
429                 Each register field.
430   
431   ---------------------------------------------------------------------------*/
432 
433 void snd_trident_write_voice_regs(trident_t * trident,
434                                   snd_trident_voice_t * voice)
435 {
436         unsigned int FmcRvolCvol;
437         unsigned int regs[5];
438 
439         regs[1] = voice->LBA;
440         regs[4] = (voice->GVSel << 31) |
441                   ((voice->Pan & 0x0000007f) << 24) |
442                   ((voice->CTRL & 0x0000000f) << 12);
443         FmcRvolCvol = ((voice->FMC & 3) << 14) |
444                       ((voice->RVol & 0x7f) << 7) |
445                       (voice->CVol & 0x7f);
446 
447         switch (trident->device) {
448         case TRIDENT_DEVICE_ID_SI7018:
449                 regs[4] |= voice->number > 31 ?
450                                 (voice->Vol & 0x000003ff) :
451                                 ((voice->Vol & 0x00003fc) << (16-2)) |
452                                 (voice->EC & 0x00000fff);
453                 regs[0] = (voice->CSO << 16) | ((voice->Alpha & 0x00000fff) << 4) | (voice->FMS & 0x0000000f);
454                 regs[2] = (voice->ESO << 16) | (voice->Delta & 0x0ffff);
455                 regs[3] = (voice->Attribute << 16) | FmcRvolCvol;
456                 break;
457         case TRIDENT_DEVICE_ID_DX:
458                 regs[4] |= ((voice->Vol & 0x000003fc) << (16-2)) |
459                            (voice->EC & 0x00000fff);
460                 regs[0] = (voice->CSO << 16) | ((voice->Alpha & 0x00000fff) << 4) | (voice->FMS & 0x0000000f);
461                 regs[2] = (voice->ESO << 16) | (voice->Delta & 0x0ffff);
462                 regs[3] = FmcRvolCvol;
463                 break;
464         case TRIDENT_DEVICE_ID_NX:
465                 regs[4] |= ((voice->Vol & 0x000003fc) << (16-2)) |
466                            (voice->EC & 0x00000fff);
467                 regs[0] = (voice->Delta << 24) | (voice->CSO & 0x00ffffff);
468                 regs[2] = ((voice->Delta << 16) & 0xff000000) | (voice->ESO & 0x00ffffff);
469                 regs[3] = (voice->Alpha << 20) | ((voice->FMS & 0x0000000f) << 16) | FmcRvolCvol;
470                 break;
471         default:
472                 snd_BUG();
473         }
474 
475         outb(voice->number, TRID_REG(trident, T4D_LFO_GC_CIR));
476         outl(regs[0], TRID_REG(trident, CH_START + 0));
477         outl(regs[1], TRID_REG(trident, CH_START + 4));
478         outl(regs[2], TRID_REG(trident, CH_START + 8));
479         outl(regs[3], TRID_REG(trident, CH_START + 12));
480         outl(regs[4], TRID_REG(trident, CH_START + 16));
481 
482 #if 0
483         printk("written %i channel:\n", voice->number);
484         printk("  regs[0] = 0x%x/0x%x\n", regs[0], inl(TRID_REG(trident, CH_START + 0)));
485         printk("  regs[1] = 0x%x/0x%x\n", regs[1], inl(TRID_REG(trident, CH_START + 4)));
486         printk("  regs[2] = 0x%x/0x%x\n", regs[2], inl(TRID_REG(trident, CH_START + 8)));
487         printk("  regs[3] = 0x%x/0x%x\n", regs[3], inl(TRID_REG(trident, CH_START + 12)));
488         printk("  regs[4] = 0x%x/0x%x\n", regs[4], inl(TRID_REG(trident, CH_START + 16)));
489 #endif
490 }
491 
492 /*---------------------------------------------------------------------------
493    snd_trident_write_cso_reg
494   
495    Description: This routine will write the new CSO offset
496                 register to hardware.
497   
498    Paramters:   trident - pointer to target device class for 4DWave.
499                 voice - synthesizer voice structure
500                 CSO - new CSO value
501   
502   ---------------------------------------------------------------------------*/
503 
504 static void snd_trident_write_cso_reg(trident_t * trident, snd_trident_voice_t * voice, unsigned int CSO)
505 {
506         voice->CSO = CSO;
507         outb(voice->number, TRID_REG(trident, T4D_LFO_GC_CIR));
508         if (trident->device != TRIDENT_DEVICE_ID_NX) {
509                 outw(voice->CSO, TRID_REG(trident, CH_DX_CSO_ALPHA_FMS) + 2);
510         } else {
511                 outl((voice->Delta << 24) | (voice->CSO & 0x00ffffff), TRID_REG(trident, CH_NX_DELTA_CSO));
512         }
513 }
514 
515 /*---------------------------------------------------------------------------
516    snd_trident_write_eso_reg
517   
518    Description: This routine will write the new ESO offset
519                 register to hardware.
520   
521    Paramters:   trident - pointer to target device class for 4DWave.
522                 voice - synthesizer voice structure
523                 ESO - new ESO value
524   
525   ---------------------------------------------------------------------------*/
526 
527 static void snd_trident_write_eso_reg(trident_t * trident, snd_trident_voice_t * voice, unsigned int ESO)
528 {
529         voice->ESO = ESO;
530         outb(voice->number, TRID_REG(trident, T4D_LFO_GC_CIR));
531         if (trident->device != TRIDENT_DEVICE_ID_NX) {
532                 outw(voice->ESO, TRID_REG(trident, CH_DX_ESO_DELTA) + 2);
533         } else {
534                 outl(((voice->Delta << 16) & 0xff000000) | (voice->ESO & 0x00ffffff), TRID_REG(trident, CH_NX_DELTA_ESO));
535         }
536 }
537 
538 /*---------------------------------------------------------------------------
539    snd_trident_write_vol_reg
540   
541    Description: This routine will write the new voice volume
542                 register to hardware.
543   
544    Paramters:   trident - pointer to target device class for 4DWave.
545                 voice - synthesizer voice structure
546                 Vol - new voice volume
547   
548   ---------------------------------------------------------------------------*/
549 
550 static void snd_trident_write_vol_reg(trident_t * trident, snd_trident_voice_t * voice, unsigned int Vol)
551 {
552         voice->Vol = Vol;
553         outb(voice->number, TRID_REG(trident, T4D_LFO_GC_CIR));
554         switch (trident->device) {
555         case TRIDENT_DEVICE_ID_DX:
556         case TRIDENT_DEVICE_ID_NX:
557                 outb(voice->Vol >> 2, TRID_REG(trident, CH_GVSEL_PAN_VOL_CTRL_EC + 2));
558                 break;
559         case TRIDENT_DEVICE_ID_SI7018:
560                 // printk("voice->Vol = 0x%x\n", voice->Vol);
561                 outw((voice->CTRL << 12) | voice->Vol, TRID_REG(trident, CH_GVSEL_PAN_VOL_CTRL_EC));
562                 break;
563         }
564 }
565 
566 /*---------------------------------------------------------------------------
567    snd_trident_write_pan_reg
568   
569    Description: This routine will write the new voice pan
570                 register to hardware.
571   
572    Paramters:   trident - pointer to target device class for 4DWave.
573                 voice - synthesizer voice structure
574                 Pan - new pan value
575   
576   ---------------------------------------------------------------------------*/
577 
578 static void snd_trident_write_pan_reg(trident_t * trident, snd_trident_voice_t * voice, unsigned int Pan)
579 {
580         voice->Pan = Pan;
581         outb(voice->number, TRID_REG(trident, T4D_LFO_GC_CIR));
582         outb(((voice->GVSel & 0x01) << 7) | (voice->Pan & 0x7f), TRID_REG(trident, CH_GVSEL_PAN_VOL_CTRL_EC + 3));
583 }
584 
585 /*---------------------------------------------------------------------------
586    snd_trident_write_rvol_reg
587   
588    Description: This routine will write the new reverb volume
589                 register to hardware.
590   
591    Paramters:   trident - pointer to target device class for 4DWave.
592                 voice - synthesizer voice structure
593                 RVol - new reverb volume
594   
595   ---------------------------------------------------------------------------*/
596 
597 static void snd_trident_write_rvol_reg(trident_t * trident, snd_trident_voice_t * voice, unsigned int RVol)
598 {
599         voice->RVol = RVol;
600         outb(voice->number, TRID_REG(trident, T4D_LFO_GC_CIR));
601         outw(((voice->FMC & 0x0003) << 14) | ((voice->RVol & 0x007f) << 7) | (voice->CVol & 0x007f),
602              TRID_REG(trident, trident->device == TRIDENT_DEVICE_ID_NX ? CH_NX_ALPHA_FMS_FMC_RVOL_CVOL : CH_DX_FMC_RVOL_CVOL));
603 }
604 
605 /*---------------------------------------------------------------------------
606    snd_trident_write_cvol_reg
607   
608    Description: This routine will write the new chorus volume
609                 register to hardware.
610   
611    Paramters:   trident - pointer to target device class for 4DWave.
612                 voice - synthesizer voice structure
613                 CVol - new chorus volume
614   
615   ---------------------------------------------------------------------------*/
616 
617 static void snd_trident_write_cvol_reg(trident_t * trident, snd_trident_voice_t * voice, unsigned int CVol)
618 {
619         voice->CVol = CVol;
620         outb(voice->number, TRID_REG(trident, T4D_LFO_GC_CIR));
621         outw(((voice->FMC & 0x0003) << 14) | ((voice->RVol & 0x007f) << 7) | (voice->CVol & 0x007f),
622              TRID_REG(trident, trident->device == TRIDENT_DEVICE_ID_NX ? CH_NX_ALPHA_FMS_FMC_RVOL_CVOL : CH_DX_FMC_RVOL_CVOL));
623 }
624 
625 /*---------------------------------------------------------------------------
626    snd_trident_convert_rate
627 
628    Description: This routine converts rate in HZ to hardware delta value.
629   
630    Paramters:   trident - pointer to target device class for 4DWave.
631                 rate - Real or Virtual channel number.
632   
633    Returns:     Delta value.
634   
635   ---------------------------------------------------------------------------*/
636 unsigned int snd_trident_convert_rate(unsigned int rate)
637 {
638         unsigned int delta;
639 
640         // We special case 44100 and 8000 since rounding with the equation
641         // does not give us an accurate enough value. For 11025 and 22050
642         // the equation gives us the best answer. All other frequencies will
643         // also use the equation. JDW
644         if (rate == 44100)
645                 delta = 0xeb3;
646         else if (rate == 8000)
647                 delta = 0x2ab;
648         else if (rate == 48000)
649                 delta = 0x1000;
650         else
651                 delta = (((rate << 12) + 24000) / 48000) & 0x0000ffff;
652         return delta;
653 }
654 
655 /*---------------------------------------------------------------------------
656    snd_trident_convert_adc_rate
657 
658    Description: This routine converts rate in HZ to hardware delta value.
659   
660    Paramters:   trident - pointer to target device class for 4DWave.
661                 rate - Real or Virtual channel number.
662   
663    Returns:     Delta value.
664   
665   ---------------------------------------------------------------------------*/
666 static unsigned int snd_trident_convert_adc_rate(unsigned int rate)
667 {
668         unsigned int delta;
669 
670         // We special case 44100 and 8000 since rounding with the equation
671         // does not give us an accurate enough value. For 11025 and 22050
672         // the equation gives us the best answer. All other frequencies will
673         // also use the equation. JDW
674         if (rate == 44100)
675                 delta = 0x116a;
676         else if (rate == 8000)
677                 delta = 0x6000;
678         else if (rate == 48000)
679                 delta = 0x1000;
680         else
681                 delta = ((48000 << 12) / rate) & 0x0000ffff;
682         return delta;
683 }
684 
685 /*---------------------------------------------------------------------------
686    snd_trident_spurious_threshold
687 
688    Description: This routine converts rate in HZ to spurious threshold.
689   
690    Paramters:   trident - pointer to target device class for 4DWave.
691                 rate - Real or Virtual channel number.
692   
693    Returns:     Delta value.
694   
695   ---------------------------------------------------------------------------*/
696 unsigned int snd_trident_spurious_threshold(unsigned int rate, unsigned int period_size)
697 {
698         unsigned int res = (rate * period_size) / 48000;
699         if (res < 64)
700                 res = res / 2;
701         else
702                 res -= 32;
703         return res;
704 }
705 
706 /*---------------------------------------------------------------------------
707    snd_trident_control_mode
708 
709    Description: This routine returns a control mode for a PCM channel.
710   
711    Paramters:   trident - pointer to target device class for 4DWave.
712                 substream  - PCM substream
713   
714    Returns:     Control value.
715   
716   ---------------------------------------------------------------------------*/
717 unsigned int snd_trident_control_mode(snd_pcm_substream_t *substream)
718 {
719         unsigned int CTRL;
720         snd_pcm_runtime_t *runtime = substream->runtime;
721 
722         /* set ctrl mode
723            CTRL default: 8-bit (unsigned) mono, loop mode enabled
724          */
725         CTRL = 0x00000001;
726         if (snd_pcm_format_width(runtime->format) == 16)
727                 CTRL |= 0x00000008;     // 16-bit data
728         if (snd_pcm_format_signed(runtime->format))
729                 CTRL |= 0x00000002;     // signed data
730         if (runtime->channels > 1)
731                 CTRL |= 0x00000004;     // stereo data
732         return CTRL;
733 }
734 
735 /*
736  *  PCM part
737  */
738 
739 /*---------------------------------------------------------------------------
740    snd_trident_ioctl
741   
742    Description: Device I/O control handler for playback/capture parameters.
743   
744    Paramters:   substream  - PCM substream class
745                 cmd     - what ioctl message to process
746                 arg     - additional message infoarg     
747   
748    Returns:     Error status
749   
750   ---------------------------------------------------------------------------*/
751 
752 static int snd_trident_ioctl(snd_pcm_substream_t * substream,
753                              unsigned int cmd,
754                              void *arg)
755 {
756         /* FIXME: it seems that with small periods the behaviour of
757                   trident hardware is unpredictable and interrupt generator
758                   is broken */
759         return snd_pcm_lib_ioctl(substream, cmd, arg);
760 }
761 
762 /*---------------------------------------------------------------------------
763    snd_trident_allocate_pcm_mem
764   
765    Description: Allocate PCM ring buffer for given substream
766   
767    Parameters:  substream  - PCM substream class
768                 hw_params  - hardware parameters
769   
770    Returns:     Error status
771   
772   ---------------------------------------------------------------------------*/
773 
774 int snd_trident_allocate_pcm_mem(snd_pcm_substream_t * substream,
775                                  snd_pcm_hw_params_t * hw_params)
776 {
777         trident_t *trident = snd_pcm_substream_chip(substream);
778         snd_pcm_runtime_t *runtime = substream->runtime;
779         snd_trident_voice_t *voice = (snd_trident_voice_t *) runtime->private_data;
780         int err;
781 
782         if ((err = snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(hw_params))) < 0)
783                 return err;
784         if (trident->tlb.entries) {
785                 if (err > 0) { /* change */
786                         if (voice->memblk)
787                                 snd_trident_free_pages(trident, voice->memblk);
788                         voice->memblk = snd_trident_alloc_pages(trident, substream);
789                         if (voice->memblk == NULL)
790                                 return -ENOMEM;
791                 }
792         }
793         return 0;
794 }
795 
796 /*---------------------------------------------------------------------------
797    snd_trident_allocate_evoice
798   
799    Description: Allocate extra voice as interrupt generator
800   
801    Parameters:  substream  - PCM substream class
802                 hw_params  - hardware parameters
803   
804    Returns:     Error status
805   
806   ---------------------------------------------------------------------------*/
807 
808 int snd_trident_allocate_evoice(snd_pcm_substream_t * substream,
809                                 snd_pcm_hw_params_t * hw_params)
810 {
811         trident_t *trident = snd_pcm_substream_chip(substream);
812         snd_pcm_runtime_t *runtime = substream->runtime;
813         snd_trident_voice_t *voice = (snd_trident_voice_t *) runtime->private_data;
814         snd_trident_voice_t *evoice = voice->extra;
815 
816         /* voice management */
817 
818         if (params_buffer_size(hw_params) / 2 != params_period_size(hw_params)) {
819                 if (evoice == NULL) {
820                         evoice = snd_trident_alloc_voice(trident, SNDRV_TRIDENT_VOICE_TYPE_PCM, 0, 0);
821                         if (evoice == NULL)
822                                 return -ENOMEM;
823                         voice->extra = evoice;
824                         evoice->substream = substream;
825                 }
826         } else {
827                 if (evoice != NULL) {
828                         snd_trident_free_voice(trident, evoice);
829                         voice->extra = evoice = NULL;
830                 }
831         }
832 
833         return 0;
834 }
835 
836 /*---------------------------------------------------------------------------
837    snd_trident_hw_params
838   
839    Description: Set the hardware parameters for the playback device.
840   
841    Parameters:  substream  - PCM substream class
842                 hw_params  - hardware parameters
843   
844    Returns:     Error status
845   
846   ---------------------------------------------------------------------------*/
847 
848 static int snd_trident_hw_params(snd_pcm_substream_t * substream,
849                                  snd_pcm_hw_params_t * hw_params)
850 {
851         int err;
852 
853         err = snd_trident_allocate_pcm_mem(substream, hw_params);
854         if (err >= 0)
855                 err = snd_trident_allocate_evoice(substream, hw_params);
856         return err;
857 }
858 
859 /*---------------------------------------------------------------------------
860    snd_trident_playback_hw_free
861   
862    Description: Release the hardware resources for the playback device.
863   
864    Parameters:  substream  - PCM substream class
865   
866    Returns:     Error status
867   
868   ---------------------------------------------------------------------------*/
869 
870 static int snd_trident_hw_free(snd_pcm_substream_t * substream)
871 {
872         trident_t *trident = snd_pcm_substream_chip(substream);
873         snd_pcm_runtime_t *runtime = substream->runtime;
874         snd_trident_voice_t *voice = (snd_trident_voice_t *) runtime->private_data;
875         snd_trident_voice_t *evoice = voice ? voice->extra : NULL;
876 
877         if (trident->tlb.entries) {
878                 if (voice && voice->memblk) {
879                         snd_trident_free_pages(trident, voice->memblk);
880                         voice->memblk = NULL;
881                 }
882         }
883         snd_pcm_lib_free_pages(substream);
884         if (evoice != NULL) {
885                 snd_trident_free_voice(trident, evoice);
886                 voice->extra = NULL;
887         }
888         return 0;
889 }
890 
891 /*---------------------------------------------------------------------------
892    snd_trident_playback_prepare
893   
894    Description: Prepare playback device for playback.
895   
896    Parameters:  substream  - PCM substream class
897   
898    Returns:     Error status
899   
900   ---------------------------------------------------------------------------*/
901 
902 static int snd_trident_playback_prepare(snd_pcm_substream_t * substream)
903 {
904         trident_t *trident = snd_pcm_substream_chip(substream);
905         snd_pcm_runtime_t *runtime = substream->runtime;
906         snd_trident_voice_t *voice = (snd_trident_voice_t *) runtime->private_data;
907         snd_trident_voice_t *evoice = voice->extra;
908         snd_trident_pcm_mixer_t *mix = &trident->pcm_mixer[substream->number];
909 
910         spin_lock(&trident->reg_lock);  
911 
912         /* set delta (rate) value */
913         voice->Delta = snd_trident_convert_rate(runtime->rate);
914         voice->spurious_threshold = snd_trident_spurious_threshold(runtime->rate, runtime->period_size);
915 
916         /* set Loop Begin Address */
917         if (voice->memblk)
918                 voice->LBA = voice->memblk->offset;
919         else
920                 voice->LBA = runtime->dma_addr;
921  
922         voice->CSO = 0;
923         voice->ESO = runtime->buffer_size - 1;  /* in samples */
924         voice->CTRL = snd_trident_control_mode(substream);
925         voice->FMC = 3;
926         voice->GVSel = 1;
927         voice->EC = 0;
928         voice->Alpha = 0;
929         voice->FMS = 0;
930         voice->Vol = mix->vol;
931         voice->RVol = mix->rvol;
932         voice->CVol = mix->cvol;
933         voice->Pan = mix->pan;
934         voice->Attribute = 0;
935 #if 0
936         voice->Attribute = (1<<(30-16))|(2<<(26-16))|
937                            (0<<(24-16))|(0x1f<<(19-16));
938 #else
939         voice->Attribute = 0;
940 #endif
941 
942         snd_trident_write_voice_regs(trident, voice);
943 
944         if (evoice != NULL) {
945                 evoice->Delta = voice->Delta;
946                 evoice->spurious_threshold = voice->spurious_threshold;
947                 evoice->LBA = voice->LBA;
948                 evoice->CSO = 0;
949                 evoice->ESO = (runtime->period_size * 2) + 4 - 1; /* in samples */
950                 evoice->CTRL = voice->CTRL;
951                 evoice->FMC = 3;
952                 evoice->GVSel = trident->device == TRIDENT_DEVICE_ID_SI7018 ? 0 : 1;
953                 evoice->EC = 0;
954                 evoice->Alpha = 0;
955                 evoice->FMS = 0;
956                 evoice->Vol = 0x3ff;                    /* mute */
957                 evoice->RVol = evoice->CVol = 0x7f;     /* mute */
958                 evoice->Pan = 0x7f;                     /* mute */
959 #if 0
960                 evoice->Attribute = (1<<(30-16))|(2<<(26-16))|
961                                     (0<<(24-16))|(0x1f<<(19-16));
962 #else
963                 evoice->Attribute = 0;
964 #endif
965                 snd_trident_write_voice_regs(trident, evoice);
966                 evoice->isync2 = 1;
967                 evoice->isync_mark = runtime->period_size;
968                 evoice->ESO = (runtime->period_size * 2) - 1;
969         }
970 
971         spin_unlock(&trident->reg_lock);
972 
973         return 0;
974 }
975 
976 /*---------------------------------------------------------------------------
977    snd_trident_capture_hw_params
978   
979    Description: Set the hardware parameters for the capture device.
980   
981    Parameters:  substream  - PCM substream class
982                 hw_params  - hardware parameters
983   
984    Returns:     Error status
985   
986   ---------------------------------------------------------------------------*/
987 
988 static int snd_trident_capture_hw_params(snd_pcm_substream_t * substream,
989                                          snd_pcm_hw_params_t * hw_params)
990 {
991         return snd_trident_allocate_pcm_mem(substream, hw_params);
992 }
993 
994 /*---------------------------------------------------------------------------
995    snd_trident_capture_prepare
996   
997    Description: Prepare capture device for playback.
998   
999    Parameters:  substream  - PCM substream class
1000   
1001    Returns:     Error status
1002   
1003   ---------------------------------------------------------------------------*/
1004 
1005 static int snd_trident_capture_prepare(snd_pcm_substream_t * substream)
1006 {
1007         trident_t *trident = snd_pcm_substream_chip(substream);
1008         snd_pcm_runtime_t *runtime = substream->runtime;
1009         snd_trident_voice_t *voice = (snd_trident_voice_t *) runtime->private_data;
1010         unsigned int val, ESO_bytes;
1011 
1012         snd_assert(substream->dma_device.type == SNDRV_DMA_TYPE_PCI, return -EIO);
1013 
1014         spin_lock(&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(&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 
1099 static 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 
1121 static 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 
1147 static 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(&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(&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 
1218 static 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(&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(&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 
1296 static 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 
1361 static 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(&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(&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 
1500 static 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_chip(s->pcm) == 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 
1598 static 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 
1637 static 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 
1667 static 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 
1686 static 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 
1711 static 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 
1736 static 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 
1760 static 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 
1781 static 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 
1801 static 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 
1812 static 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   ---------------------------------------------------------------------------*/
1840 static 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 
1861 static 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 
1902 static 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 
1940 static 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   ---------------------------------------------------------------------------*/
1968 static 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 
1984 static 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   ---------------------------------------------------------------------------*/
2011 static 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 
2029 static 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 
2040 static 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 
2052 static 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 
2063 static 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 
2074 static 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 
2085 static 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 
2097 static 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 
2108 static 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   ---------------------------------------------------------------------------*/
2129 static void snd_trident_pcm_free(snd_pcm_t *pcm)
2130 {
2131         trident_t *trident = snd_magic_cast(trident_t, pcm->private_data, return);
2132         trident->pcm = NULL;
2133         snd_pcm_lib_preallocate_free_for_all(pcm);
2134 }
2135 
2136 static void snd_trident_foldback_pcm_free(snd_pcm_t *pcm)
2137 {
2138         trident_t *trident = snd_magic_cast(trident_t, pcm->private_data, return);
2139         trident->foldback = NULL;
2140         snd_pcm_lib_preallocate_free_for_all(pcm);
2141 }
2142 
2143 static void snd_trident_spdif_pcm_free(snd_pcm_t *pcm)
2144 {
2145         trident_t *trident = snd_magic_cast(trident_t, pcm->private_data, return);
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 
2161 int __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_sg_pages(trident->pci, substream, 64*1024, 128*1024);
2193                 snd_pcm_lib_preallocate_pci_pages(trident->pci, pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream, 64*1024, 128*1024);
2194         } else {
2195                 snd_pcm_lib_preallocate_pci_pages_for_all(trident->pci, pcm, 64*1024, 128*1024);
2196         }
2197 
2198         if (rpcm)
2199                 *rpcm = pcm;
2200         return 0;
2201 }
2202 
2203 /*---------------------------------------------------------------------------
2204    snd_trident_foldback_pcm
2205   
2206    Description: This routine registers the 4DWave device for foldback PCM support.
2207                 
2208    Paramters:   trident - pointer to target device class for 4DWave.
2209 
2210    Returns:     None
2211   
2212   ---------------------------------------------------------------------------*/
2213 
2214 int __devinit snd_trident_foldback_pcm(trident_t * trident, int device, snd_pcm_t ** rpcm)
2215 {
2216         snd_pcm_t *foldback;
2217         int err;
2218         int num_chan = 3;
2219         snd_pcm_substream_t *substream;
2220 
2221         if (rpcm)
2222                 *rpcm = NULL;
2223         if (trident->device == TRIDENT_DEVICE_ID_NX)
2224                 num_chan = 4;
2225         if ((err = snd_pcm_new(trident->card, "trident_dx_nx", device, 0, num_chan, &foldback)) < 0)
2226                 return err;
2227 
2228         foldback->private_data = trident;
2229         foldback->private_free = snd_trident_foldback_pcm_free;
2230         if (trident->tlb.entries)
2231                 snd_pcm_set_ops(foldback, SNDRV_PCM_STREAM_CAPTURE, &snd_trident_nx_foldback_ops);
2232         else
2233                 snd_pcm_set_ops(foldback, SNDRV_PCM_STREAM_CAPTURE, &snd_trident_foldback_ops);
2234         foldback->info_flags = 0;
2235         strcpy(foldback->name, "Trident 4DWave");
2236         substream = foldback->streams[SNDRV_PCM_STREAM_CAPTURE].substream;
2237         strcpy(substream->name, "Front Mixer");
2238         substream = substream->next;
2239         strcpy(substream->name, "Reverb Mixer");
2240         substream = substream->next;
2241         strcpy(substream->name, "Chorus Mixer");
2242         if (num_chan == 4) {
2243                 substream = substream->next;
2244                 strcpy(substream->name, "Second AC'97 ADC");
2245         }
2246         trident->foldback = foldback;
2247 
2248         if (trident->tlb.entries)
2249                 snd_pcm_lib_preallocate_sg_pages_for_all(trident->pci, foldback, 0, 128*1024);
2250         else
2251                 snd_pcm_lib_preallocate_pci_pages_for_all(trident->pci, foldback, 64*1024, 128*1024);
2252 
2253         if (rpcm)
2254                 *rpcm = foldback;
2255         return 0;
2256 }
2257 
2258 /*---------------------------------------------------------------------------
2259    snd_trident_spdif
2260   
2261    Description: This routine registers the 4DWave-NX device for SPDIF support.
2262                 
2263    Paramters:   trident - pointer to target device class for 4DWave-NX.
2264 
2265    Returns:     None
2266   
2267   ---------------------------------------------------------------------------*/
2268 
2269 int __devinit snd_trident_spdif_pcm(trident_t * trident, int device, snd_pcm_t ** rpcm)
2270 {
2271         snd_pcm_t *spdif;
2272         int err;
2273 
2274         if (rpcm)
2275                 *rpcm = NULL;
2276         if ((err = snd_pcm_new(trident->card, "trident_dx_nx IEC958", device, 1, 0, &spdif)) < 0)
2277                 return err;
2278 
2279         spdif->private_data = trident;
2280         spdif->private_free = snd_trident_spdif_pcm_free;
2281         if (trident->device != TRIDENT_DEVICE_ID_SI7018) {
2282                 snd_pcm_set_ops(spdif, SNDRV_PCM_STREAM_PLAYBACK, &snd_trident_spdif_ops);
2283         } else {
2284                 snd_pcm_set_ops(spdif, SNDRV_PCM_STREAM_PLAYBACK, &snd_trident_spdif_7018_ops);
2285         }
2286         spdif->info_flags = 0;
2287         strcpy(spdif->name, "Trident 4DWave IEC958");
2288         trident->spdif = spdif;
2289 
2290         snd_pcm_lib_preallocate_pci_pages_for_all(trident->pci, spdif, 64*1024, 128*1024);
2291 
2292         if (rpcm)
2293                 *rpcm = spdif;
2294         return 0;
2295 }
2296 
2297 /*
2298  *  Mixer part
2299  */
2300 
2301 
2302 /*---------------------------------------------------------------------------
2303     snd_trident_spdif_control
2304 
2305     Description: enable/disable S/PDIF out from ac97 mixer
2306   ---------------------------------------------------------------------------*/
2307 
2308 static int snd_trident_spdif_control_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
2309 {
2310         uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
2311         uinfo->count = 1;
2312         uinfo->value.integer.min = 0;
2313         uinfo->value.integer.max = 1;
2314         return 0;
2315 }
2316 
2317 static int snd_trident_spdif_control_get(snd_kcontrol_t * kcontrol,
2318                                          snd_ctl_elem_value_t * ucontrol)
2319 {
2320         trident_t *trident = snd_kcontrol_chip(kcontrol);
2321         unsigned long flags;
2322         unsigned char val;
2323 
2324         spin_lock_irqsave(&trident->reg_lock, flags);
2325         val = trident->spdif_ctrl;
2326         ucontrol->value.integer.value[0] = val == kcontrol->private_value;
2327         spin_unlock_irqrestore(&trident->reg_lock, flags);
2328         return 0;
2329 }
2330 
2331 static int snd_trident_spdif_control_put(snd_kcontrol_t * kcontrol,
2332                                          snd_ctl_elem_value_t * ucontrol)
2333 {
2334         trident_t *trident = snd_kcontrol_chip(kcontrol);
2335         unsigned long flags;
2336         unsigned char val;
2337         int change;
2338 
2339         val = ucontrol->value.integer.value[0] ? (unsigned char) kcontrol->private_value : 0x00;
2340         spin_lock_irqsave(&trident->reg_lock, flags);
2341         /* S/PDIF C Channel bits 0-31 : 48khz, SCMS disabled */
2342         change = trident->spdif_ctrl != val;
2343         trident->spdif_ctrl = val;
2344         if (trident->device != TRIDENT_DEVICE_ID_SI7018) {
2345                 if ((inb(TRID_REG(trident, NX_SPCTRL_SPCSO + 3)) & 0x10) == 0) {
2346                         outl(trident->spdif_bits, TRID_REG(trident, NX_SPCSTATUS));
2347                         outb(trident->spdif_ctrl, TRID_REG(trident, NX_SPCTRL_SPCSO + 3));
2348                 }
2349         } else {
2350                 if (trident->spdif == NULL) {
2351                         unsigned int temp;
2352                         outl(trident->spdif_bits, TRID_REG(trident, SI_SPDIF_CS));
2353                         temp = inl(TRID_REG(trident, SI_SERIAL_INTF_CTRL)) & ~SPDIF_EN;
2354                         if (val)
2355                                 temp |= SPDIF_EN;
2356                         outl(temp, TRID_REG(trident, SI_SERIAL_INTF_CTRL));
2357                 }
2358         }
2359         spin_unlock_irqrestore(&trident->reg_lock, flags);
2360         return change;
2361 }
2362 
2363 static snd_kcontrol_new_t snd_trident_spdif_control __devinitdata =
2364 {
2365         .iface =        SNDRV_CTL_ELEM_IFACE_MIXER,
2366         .name =         SNDRV_CTL_NAME_IEC958("",PLAYBACK,SWITCH),
2367         .info =         snd_trident_spdif_control_info,
2368         .get =          snd_trident_spdif_control_get,
2369         .put =          snd_trident_spdif_control_put,
2370         .private_value = 0x28,
2371 };
2372 
2373 /*---------------------------------------------------------------------------
2374     snd_trident_spdif_default
2375 
2376     Description: put/get the S/PDIF default settings
2377   ---------------------------------------------------------------------------*/
2378 
2379 static int snd_trident_spdif_default_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
2380 {
2381         uinfo->type = SNDRV_CTL_ELEM_TYPE_IEC958;
2382         uinfo->count = 1;
2383         return 0;
2384 }
2385 
2386 static int snd_trident_spdif_default_get(snd_kcontrol_t * kcontrol,
2387                                          snd_ctl_elem_value_t * ucontrol)
2388 {
2389         trident_t *trident = snd_kcontrol_chip(kcontrol);
2390         unsigned long flags;
2391 
2392         spin_lock_irqsave(&trident->reg_lock, flags);
2393         ucontrol->value.iec958.status[0] = (trident->spdif_bits >> 0) & 0xff;
2394         ucontrol->value.iec958.status[1] = (trident->spdif_bits >> 8) & 0xff;
2395         ucontrol->value.iec958.status[2] = (trident->spdif_bits >> 16) & 0xff;
2396         ucontrol->value.iec958.status[3] = (trident->spdif_bits >> 24) & 0xff;
2397         spin_unlock_irqrestore(&trident->reg_lock, flags);
2398         return 0;
2399 }
2400 
2401 static int snd_trident_spdif_default_put(snd_kcontrol_t * kcontrol,
2402                                          snd_ctl_elem_value_t * ucontrol)
2403 {
2404         trident_t *trident = snd_kcontrol_chip(kcontrol);
2405         unsigned long flags;
2406         unsigned int val;
2407         int change;
2408 
2409         val = (ucontrol->value.iec958.status[0] << 0) |
2410               (ucontrol->value.iec958.status[1] << 8) |
2411               (ucontrol->value.iec958.status[2] << 16) |
2412               (ucontrol->value.iec958.status[3] << 24);
2413         spin_lock_irqsave(&trident->reg_lock, flags);
2414         change = trident->spdif_bits != val;
2415         trident->spdif_bits = val;
2416         if (trident->device != TRIDENT_DEVICE_ID_SI7018) {
2417                 if ((inb(TRID_REG(trident, NX_SPCTRL_SPCSO + 3)) & 0x10) == 0)
2418                         outl(trident->spdif_bits, TRID_REG(trident, NX_SPCSTATUS));
2419         } else {
2420                 if (trident->spdif == NULL)
2421                         outl(trident->spdif_bits, TRID_REG(trident, SI_SPDIF_CS));
2422         }
2423         spin_unlock_irqrestore(&trident->reg_lock, flags);
2424         return change;
2425 }
2426 
2427 static snd_kcontrol_new_t snd_trident_spdif_default __devinitdata =
2428 {
2429         .iface =        SNDRV_CTL_ELEM_IFACE_PCM,
2430         .name =         SNDRV_CTL_NAME_IEC958("",PLAYBACK,DEFAULT),
2431         .info =         snd_trident_spdif_default_info,
2432         .get =          snd_trident_spdif_default_get,
2433         .put =          snd_trident_spdif_default_put
2434 };
2435 
2436 /*---------------------------------------------------------------------------
2437     snd_trident_spdif_mask
2438 
2439     Description: put/get the S/PDIF mask
2440   ---------------------------------------------------------------------------*/
2441 
2442 static int snd_trident_spdif_mask_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
2443 {
2444         uinfo->type = SNDRV_CTL_ELEM_TYPE_IEC958;
2445         uinfo->count = 1;
2446         return 0;
2447 }
2448 
2449 static int snd_trident_spdif_mask_get(snd_kcontrol_t * kcontrol,
2450                                       snd_ctl_elem_value_t * ucontrol)
2451 {
2452         ucontrol->value.iec958.status[0] = 0xff;
2453         ucontrol->value.iec958.status[1] = 0xff;
2454         ucontrol->value.iec958.status[2] = 0xff;
2455         ucontrol->value.iec958.status[3] = 0xff;
2456         return 0;
2457 }
2458 
2459 static snd_kcontrol_new_t snd_trident_spdif_mask __devinitdata =
2460 {
2461         .access =       SNDRV_CTL_ELEM_ACCESS_READ,
2462         .iface =        SNDRV_CTL_ELEM_IFACE_PCM,
2463         .name =         SNDRV_CTL_NAME_IEC958("",PLAYBACK,MASK),
2464         .info =         snd_trident_spdif_mask_info,
2465         .get =          snd_trident_spdif_mask_get,
2466 };
2467 
2468 /*---------------------------------------------------------------------------
2469     snd_trident_spdif_stream
2470 
2471     Description: put/get the S/PDIF stream settings
2472   ---------------------------------------------------------------------------*/
2473 
2474 static int snd_trident_spdif_stream_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
2475 {
2476         uinfo->type = SNDRV_CTL_ELEM_TYPE_IEC958;
2477         uinfo->count = 1;
2478         return 0;
2479 }
2480 
2481 static int snd_trident_spdif_stream_get(snd_kcontrol_t * kcontrol,
2482                                         snd_ctl_elem_value_t * ucontrol)
2483 {
2484         trident_t *trident = snd_kcontrol_chip(kcontrol);
2485         unsigned long flags;
2486 
2487         spin_lock_irqsave(&trident->reg_lock, flags);
2488         ucontrol->value.iec958.status[0] = (trident->spdif_pcm_bits >> 0) & 0xff;
2489         ucontrol->value.iec958.status[1] = (trident->spdif_pcm_bits >> 8) & 0xff;
2490         ucontrol->value.iec958.status[2] = (trident->spdif_pcm_bits >> 16) & 0xff;
2491         ucontrol->value.iec958.status[3] = (trident->spdif_pcm_bits >> 24) & 0xff;
2492         spin_unlock_irqrestore(&trident->reg_lock, flags);
2493         return 0;
2494 }
2495 
2496 static int snd_trident_spdif_stream_put(snd_kcontrol_t * kcontrol,
2497                                         snd_ctl_elem_value_t * ucontrol)
2498 {
2499         trident_t *trident = snd_kcontrol_chip(kcontrol);
2500         unsigned long flags;
2501         unsigned int val;
2502         int change;
2503 
2504         val = (ucontrol->value.iec958.status[0] << 0) |
2505               (ucontrol->value.iec958.status[1] << 8) |
2506               (ucontrol->value.iec958.status[2] << 16) |
2507               (ucontrol->value.iec958.status[3] << 24);
2508         spin_lock_irqsave(&trident->reg_lock, flags);
2509         change = trident->spdif_pcm_bits != val;
2510         trident->spdif_pcm_bits = val;
2511         if (trident->spdif != NULL) {
2512                 if (trident->device != TRIDENT_DEVICE_ID_SI7018) {
2513                         outl(trident->spdif_pcm_bits, TRID_REG(trident, NX_SPCSTATUS));
2514                 } else {
2515                         outl(trident->spdif_bits, TRID_REG(trident, SI_SPDIF_CS));
2516                 }
2517         }
2518         spin_unlock_irqrestore(&trident->reg_lock, flags);
2519         return change;
2520 }
2521 
2522 static snd_kcontrol_new_t snd_trident_spdif_stream __devinitdata =
2523 {
2524         .access =       SNDRV_CTL_ELEM_ACCESS_READWRITE | SNDRV_CTL_ELEM_ACCESS_INACTIVE,
2525         .iface =        SNDRV_CTL_ELEM_IFACE_PCM,
2526         .name =         SNDRV_CTL_NAME_IEC958("",PLAYBACK,PCM_STREAM),
2527         .info =         snd_trident_spdif_stream_info,
2528         .get =          snd_trident_spdif_stream_get,
2529         .put =          snd_trident_spdif_stream_put
2530 };
2531 
2532 /*---------------------------------------------------------------------------
2533     snd_trident_ac97_control
2534 
2535     Description: enable/disable rear path for ac97
2536   ---------------------------------------------------------------------------*/
2537 
2538 static int snd_trident_ac97_control_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
2539 {
2540         uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
2541         uinfo->count = 1;
2542         uinfo->value.integer.min = 0;
2543         uinfo->value.integer.max = 1;
2544         return 0;
2545 }
2546 
2547 static int snd_trident_ac97_control_get(snd_kcontrol_t * kcontrol,
2548                                         snd_ctl_elem_value_t * ucontrol)
2549 {
2550         trident_t *trident = snd_kcontrol_chip(kcontrol);
2551         unsigned long flags;
2552         unsigned char val;
2553 
2554         spin_lock_irqsave(&trident->reg_lock, flags);
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_irqrestore(&trident->reg_lock, flags);
2558         return 0;
2559 }
2560 
2561 static 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 long flags;
2566         unsigned char val;
2567         int change = 0;
2568 
2569         spin_lock_irqsave(&trident->reg_lock, flags);
2570         val = trident->ac97_ctrl = inl(TRID_REG(trident, NX_ACR0_AC97_COM_STAT));
2571         val &= ~(1 << kcontrol->private_value);
2572         if (ucontrol->value.integer.value[0])
2573                 val |= 1 << kcontrol->private_value;
2574         change = val != trident->ac97_ctrl;
2575         trident->ac97_ctrl = val;
2576         outl(trident->ac97_ctrl = val, TRID_REG(trident, NX_ACR0_AC97_COM_STAT));
2577         spin_unlock_irqrestore(&trident->reg_lock, flags);
2578         return change;
2579 }
2580 
2581 static snd_kcontrol_new_t snd_trident_ac97_rear_control __devinitdata =
2582 {
2583         .iface =        SNDRV_CTL_ELEM_IFACE_MIXER,
2584         .name =         "Rear Path",
2585         .info =         snd_trident_ac97_control_info,
2586         .get =          snd_trident_ac97_control_get,
2587         .put =          snd_trident_ac97_control_put,
2588         .private_value = 4,
2589 };
2590 
2591 /*---------------------------------------------------------------------------
2592     snd_trident_vol_control
2593 
2594     Description: wave & music volume control
2595   ---------------------------------------------------------------------------*/
2596 
2597 static int snd_trident_vol_control_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
2598 {
2599         uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
2600         uinfo->count = 2;
2601         uinfo->value.integer.min = 0;
2602         uinfo->value.integer.max = 255;
2603         return 0;
2604 }
2605 
2606 static int snd_trident_vol_control_get(snd_kcontrol_t * kcontrol,
2607                                        snd_ctl_elem_value_t * ucontrol)
2608 {
2609         trident_t *trident = snd_kcontrol_chip(kcontrol);
2610         unsigned int val;
2611 
2612         val = trident->musicvol_wavevol;
2613         ucontrol->value.integer.value[0] = 255 - ((val >> kcontrol->private_value) & 0xff);
2614         ucontrol->value.integer.value[1] = 255 - ((val >> (kcontrol->private_value + 8)) & 0xff);
2615         return 0;
2616 }
2617 
2618 static int snd_trident_vol_control_put(snd_kcontrol_t * kcontrol,
2619                                        snd_ctl_elem_value_t * ucontrol)
2620 {
2621         unsigned long flags;
2622         trident_t *trident = snd_kcontrol_chip(kcontrol);
2623         unsigned int val;
2624         int change = 0;
2625 
2626         spin_lock_irqsave(&trident->reg_lock, flags);
2627         val = trident->musicvol_wavevol;
2628         val &= ~(0xffff << kcontrol->private_value);
2629         val |= ((255 - (ucontrol->value.integer.value[0] & 0xff)) |
2630                 ((255 - (ucontrol->value.integer.value[1] & 0xff)) << 8)) << kcontrol->private_value;
2631         change = val != trident->musicvol_wavevol;
2632         outl(trident->musicvol_wavevol = val, TRID_REG(trident, T4D_MUSICVOL_WAVEVOL));
2633         spin_unlock_irqrestore(&trident->reg_lock, flags);
2634         return change;
2635 }
2636 
2637 static snd_kcontrol_new_t snd_trident_vol_music_control __devinitdata =
2638 {
2639         .iface =        SNDRV_CTL_ELEM_IFACE_MIXER,
2640         .name =         "Music Playback Volume",
2641         .info =         snd_trident_vol_control_info,
2642         .get =          snd_trident_vol_control_get,
2643         .put =          snd_trident_vol_control_put,
2644         .private_value = 16,
2645 };
2646 
2647 static snd_kcontrol_new_t snd_trident_vol_wave_control __devinitdata =
2648 {
2649         .iface =        SNDRV_CTL_ELEM_IFACE_MIXER,
2650         .name =         "Wave Playback Volume",
2651         .info =         snd_trident_vol_control_info,
2652         .get =          snd_trident_vol_control_get,
2653         .put =          snd_trident_vol_control_put,
2654         .private_value = 0,
2655 };
2656 
2657 /*---------------------------------------------------------------------------
2658     snd_trident_pcm_vol_control
2659 
2660     Description: PCM front volume control
2661   ---------------------------------------------------------------------------*/
2662 
2663 static int snd_trident_pcm_vol_control_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
2664 {
2665         trident_t *trident = snd_kcontrol_chip(kcontrol);
2666 
2667         uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
2668         uinfo->count = 1;
2669         uinfo->value.integer.min = 0;
2670         uinfo->value.integer.max = 255;
2671         if (trident->device == TRIDENT_DEVICE_ID_SI7018)
2672                 uinfo->value.integer.max = 1023;
2673         return 0;
2674 }
2675 
2676 static int snd_trident_pcm_vol_control_get(snd_kcontrol_t * kcontrol,
2677                                            snd_ctl_elem_value_t * ucontrol)
2678 {
2679         trident_t *trident = snd_kcontrol_chip(kcontrol);
2680         snd_trident_pcm_mixer_t *mix = &trident->pcm_mixer[snd_ctl_get_ioffnum(kcontrol, &ucontrol->id)];
2681 
2682         if (trident->device == TRIDENT_DEVICE_ID_SI7018) {
2683                 ucontrol->value.integer.value[0] = 1023 - mix->vol;
2684         } else {
2685                 ucontrol->value.integer.value[0] = 255 - (mix->vol>>2);
2686         }
2687         return 0;
2688 }
2689 
2690 static int snd_trident_pcm_vol_control_put(snd_kcontrol_t * kcontrol,
2691                                            snd_ctl_elem_value_t * ucontrol)
2692 {
2693         unsigned long flags;
2694         trident_t *trident = snd_kcontrol_chip(kcontrol);
2695         snd_trident_pcm_mixer_t *mix = &trident->pcm_mixer[snd_ctl_get_ioffnum(kcontrol, &ucontrol->id)];
2696         unsigned int val;
2697         int change = 0;
2698 
2699         if (trident->device == TRIDENT_DEVICE_ID_SI7018) {
2700                 val = 1023 - (ucontrol->value.integer.value[0] & 1023);
2701         } else {
2702                 val = (255 - (ucontrol->value.integer.value[0] & 255)) << 2;
2703         }
2704         spin_lock_irqsave(&trident->reg_lock, flags);
2705         change = val != mix->vol;
2706         mix->vol = val;
2707         if (mix->voice != NULL)
2708                 snd_trident_write_vol_reg(trident, mix->voice, val);
2709         spin_unlock_irqrestore(&trident->reg_lock, flags);
2710         return change;
2711 }
2712 
2713 static snd_kcontrol_new_t snd_trident_pcm_vol_control __devinitdata =
2714 {
2715         .iface =        SNDRV_CTL_ELEM_IFACE_MIXER,
2716         .name =         "PCM Front Playback Volume",
2717         .access =       SNDRV_CTL_ELEM_ACCESS_READWRITE | SNDRV_CTL_ELEM_ACCESS_INACTIVE,
2718         .count =        32,
2719         .info =         snd_trident_pcm_vol_control_info,
2720         .get =          snd_trident_pcm_vol_control_get,
2721         .put =          snd_trident_pcm_vol_control_put,
2722 };
2723 
2724 /*---------------------------------------------------------------------------
2725     snd_trident_pcm_pan_control
2726 
2727     Description: PCM front pan control
2728   ---------------------------------------------------------------------------*/
2729 
2730 static int snd_trident_pcm_pan_control_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
2731 {
2732         uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
2733         uinfo->count = 1;
2734         uinfo->value.integer.min = 0;
2735         uinfo->value.integer.max = 127;
2736         return 0;
2737 }
2738 
2739 static int snd_trident_pcm_pan_control_get(snd_kcontrol_t * kcontrol,
2740                                            snd_ctl_elem_value_t * ucontrol)
2741 {
2742         trident_t *trident = snd_kcontrol_chip(kcontrol);
2743         snd_trident_pcm_mixer_t *mix = &trident->pcm_mixer[snd_ctl_get_ioffnum(kcontrol, &ucontrol->id)];
2744 
2745         ucontrol->value.integer.value[0] = mix->pan;
2746         if (ucontrol->value.integer.value[0] & 0x40) {
2747                 ucontrol->value.integer.value[0] = (0x3f - (ucontrol->value.integer.value[0] & 0x3f));
2748         } else {
2749                 ucontrol->value.integer.value[0] |= 0x40;
2750         }
2751         return 0;
2752 }
2753 
2754 static int snd_trident_pcm_pan_control_put(snd_kcontrol_t * kcontrol,
2755                                            snd_ctl_elem_value_t * ucontrol)
2756 {
2757         unsigned long flags;
2758         trident_t *trident = snd_kcontrol_chip(kcontrol);
2759         snd_trident_pcm_mixer_t *mix = &trident->pcm_mixer[snd_ctl_get_ioffnum(kcontrol, &ucontrol->id)];
2760         unsigned char val;
2761         int change = 0;
2762 
2763         if (ucontrol->value.integer.value[0] & 0x40)
2764                 val = ucontrol->value.integer.value[0] & 0x3f;
2765         else
2766                 val = (0x3f - (ucontrol->value.integer.value[0] & 0x3f)) | 0x40;
2767         spin_lock_irqsave(&trident->reg_lock, flags);
2768         change = val != mix->pan;
2769         mix->pan = val;
2770         if (mix->voice != NULL)
2771                 snd_trident_write_pan_reg(trident, mix->voice, val);
2772         spin_unlock_irqrestore(&trident->reg_lock, flags);
2773         return change;
2774 }
2775 
2776 static snd_kcontrol_new_t snd_trident_pcm_pan_control __devinitdata =
2777 {
2778         .iface =        SNDRV_CTL_ELEM_IFACE_MIXER,
2779         .name =         "PCM Pan Playback Control",
2780         .access =       SNDRV_CTL_ELEM_ACCESS_READWRITE | SNDRV_CTL_ELEM_ACCESS_INACTIVE,
2781         .count =        32,
2782         .info =         snd_trident_pcm_pan_control_info,
2783         .get =          snd_trident_pcm_pan_control_get,
2784         .put =          snd_trident_pcm_pan_control_put,
2785 };
2786 
2787 /*---------------------------------------------------------------------------
2788     snd_trident_pcm_rvol_control
2789 
2790     Description: PCM reverb volume control
2791   ---------------------------------------------------------------------------*/
2792 
2793 static int snd_trident_pcm_rvol_control_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
2794 {
2795         uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
2796         uinfo->count = 1;
2797         uinfo->value.integer.min = 0;
2798         uinfo->value.integer.max = 127;
2799         return 0;
2800 }
2801 
2802 static int snd_trident_pcm_rvol_control_get(snd_kcontrol_t * kcontrol,
2803                                             snd_ctl_elem_value_t * ucontrol)
2804 {
2805         trident_t *trident = snd_kcontrol_chip(kcontrol);
2806         snd_trident_pcm_mixer_t *mix = &trident->pcm_mixer[snd_ctl_get_ioffnum(kcontrol, &ucontrol->id)];
2807 
2808         ucontrol->value.integer.value[0] = 127 - mix->rvol;
2809         return 0;
2810 }
2811 
2812 static int snd_trident_pcm_rvol_control_put(snd_kcontrol_t * kcontrol,
2813                                             snd_ctl_elem_value_t * ucontrol)
2814 {
2815         unsigned long flags;
2816         trident_t *trident = snd_kcontrol_chip(kcontrol);
2817         snd_trident_pcm_mixer_t *mix = &trident->pcm_mixer[snd_ctl_get_ioffnum(kcontrol, &ucontrol->id)];
2818         unsigned short val;
2819         int change = 0;
2820 
2821         val = 0x7f - (ucontrol->value.integer.value[0] & 0x7f);
2822         spin_lock_irqsave(&trident->reg_lock, flags);
2823         change = val != mix->rvol;
2824         mix->rvol = val;
2825         if (mix->voice != NULL)
2826                 snd_trident_write_rvol_reg(trident, mix->voice, val);
2827         spin_unlock_irqrestore(&trident->reg_lock, flags);
2828         return change;
2829 }
2830 
2831 static snd_kcontrol_new_t snd_trident_pcm_rvol_control __devinitdata =
2832 {
2833         .iface =        SNDRV_CTL_ELEM_IFACE_MIXER,
2834         .name =         "PCM Reverb Playback Volume",
2835         .access =       SNDRV_CTL_ELEM_ACCESS_READWRITE | SNDRV_CTL_ELEM_ACCESS_INACTIVE,
2836         .count =        32,
2837         .info =         snd_trident_pcm_rvol_control_info,
2838         .get =          snd_trident_pcm_rvol_control_get,
2839         .put =          snd_trident_pcm_rvol_control_put,
2840 };
2841 
2842 /*---------------------------------------------------------------------------
2843     snd_trident_pcm_cvol_control
2844 
2845     Description: PCM chorus volume control
2846   ---------------------------------------------------------------------------*/
2847 
2848 static int snd_trident_pcm_cvol_control_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
2849 {
2850         uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
2851         uinfo->count = 1;
2852         uinfo->value.integer.min = 0;
2853         uinfo->value.integer.max = 127;
2854         return 0;
2855 }
2856 
2857 static int snd_trident_pcm_cvol_control_get(snd_kcontrol_t * kcontrol,
2858                                             snd_ctl_elem_value_t * ucontrol)
2859 {
2860         trident_t *trident = snd_kcontrol_chip(kcontrol);
2861         snd_trident_pcm_mixer_t *mix = &trident->pcm_mixer[snd_ctl_get_ioffnum(kcontrol, &ucontrol->id)];
2862 
2863         ucontrol->value.integer.value[0] = 127 - mix->cvol;
2864         return 0;
2865 }
2866 
2867 static int snd_trident_pcm_cvol_control_put(snd_kcontrol_t * kcontrol,
2868                                             snd_ctl_elem_value_t * ucontrol)
2869 {
2870         unsigned long flags;
2871         trident_t *trident = snd_kcontrol_chip(kcontrol);
2872         snd_trident_pcm_mixer_t *mix = &trident->pcm_mixer[snd_ctl_get_ioffnum(kcontrol, &ucontrol->id)];
2873         unsigned short val;
2874         int change = 0;
2875 
2876         val = 0x7f - (ucontrol->value.integer.value[0] & 0x7f);
2877         spin_lock_irqsave(&trident->reg_lock, flags);
2878         change = val != mix->cvol;
2879         mix->cvol = val;
2880         if (mix->voice != NULL)
2881                 snd_trident_write_cvol_reg(trident, mix->voice, val);
2882         spin_unlock_irqrestore(&trident->reg_lock, flags);
2883         return change;
2884 }
2885 
2886 static snd_kcontrol_new_t snd_trident_pcm_cvol_control __devinitdata =
2887 {
2888         .iface =        SNDRV_CTL_ELEM_IFACE_MIXER,
2889         .name =         "PCM Chorus Playback Volume",
2890         .access =       SNDRV_CTL_ELEM_ACCESS_READWRITE | SNDRV_CTL_ELEM_ACCESS_INACTIVE,
2891         .count =        32,
2892         .info =         snd_trident_pcm_cvol_control_info,
2893         .get =          snd_trident_pcm_cvol_control_get,
2894         .put =          snd_trident_pcm_cvol_control_put,
2895 };
2896 
2897 static void snd_trident_notify_pcm_change1(snd_card_t * card, snd_kcontrol_t *kctl, int num, int activate)
2898 {
2899         snd_ctl_elem_id_t id;
2900 
2901         snd_runtime_check(kctl != NULL, return);
2902         if (activate)
2903                 kctl->vd[num].access &= ~SNDRV_CTL_ELEM_ACCESS_INACTIVE;
2904         else
2905                 kctl->vd[num].access |= SNDRV_CTL_ELEM_ACCESS_INACTIVE;
2906         snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_VALUE |
2907                        SNDRV_CTL_EVENT_MASK_INFO,
2908                        snd_ctl_build_ioff(&id, kctl, num));
2909 }
2910 
2911 static void snd_trident_notify_pcm_change(trident_t *trident, snd_trident_pcm_mixer_t *tmix, int num, int activate)
2912 {
2913         snd_trident_notify_pcm_change1(trident->card, trident->ctl_vol, num, activate);
2914         snd_trident_notify_pcm_change1(trident->card, trident->ctl_pan, num, activate);
2915         snd_trident_notify_pcm_change1(trident->card, trident->ctl_rvol, num, activate);
2916         snd_trident_notify_pcm_change1(trident->card, trident->ctl_cvol, num, activate);
2917 }
2918 
2919 static int snd_trident_pcm_mixer_build(trident_t *trident, snd_trident_voice_t *voice, snd_pcm_substream_t *substream)
2920 {
2921         snd_trident_pcm_mixer_t *tmix;
2922 
2923         snd_assert(trident != NULL && voice != NULL && substream != NULL, return -EINVAL);
2924         tmix = &trident->pcm_mixer[substream->number];
2925         tmix->voice = voice;
2926         tmix->vol = T4D_DEFAULT_PCM_VOL;
2927         tmix->pan = T4D_DEFAULT_PCM_PAN;
2928         tmix->rvol = T4D_DEFAULT_PCM_RVOL;
2929         tmix->cvol = T4D_DEFAULT_PCM_CVOL;
2930         snd_trident_notify_pcm_change(trident, tmix, substream->number, 1);
2931         return 0;
2932 }
2933 
2934 static int snd_trident_pcm_mixer_free(trident_t *trident, snd_trident_voice_t *voice, snd_pcm_substream_t *substream)
2935 {
2936         snd_trident_pcm_mixer_t *tmix;
2937 
2938         snd_assert(trident != NULL && substream != NULL, return -EINVAL);
2939         tmix = &trident->pcm_mixer[substream->number];
2940         tmix->voice = NULL;
2941         snd_trident_notify_pcm_change(trident, tmix, substream->number, 0);
2942         return 0;
2943 }
2944 
2945 /*---------------------------------------------------------------------------
2946    snd_trident_mixer
2947   
2948    Description: This routine registers the 4DWave device for mixer support.
2949                 
2950    Paramters:   trident - pointer to target device class for 4DWave.
2951 
2952    Returns:     None
2953   
2954   ---------------------------------------------------------------------------*/
2955 
2956 static int __devinit snd_trident_mixer(trident_t * trident, int pcm_spdif_device)
2957 {
2958         ac97_t _ac97;
2959         snd_card_t * card = trident->card;
2960         snd_kcontrol_t *kctl;
2961         snd_ctl_elem_value_t *uctl;
2962         int idx, err, retries = 2;
2963 
2964         uctl = (snd_ctl_elem_value_t *)snd_kcalloc(sizeof(*uctl), GFP_KERNEL);
2965         if (!uctl)
2966                 return -ENOMEM;
2967 
2968         memset(&_ac97, 0, sizeof(_ac97));
2969         _ac97.write = snd_trident_codec_write;
2970         _ac97.read = snd_trident_codec_read;
2971         _ac97.private_data = trident;
2972         trident->ac97_detect = 1;
2973 
2974       __again:
2975         if ((err = snd_ac97_mixer(trident->card, &_ac97, &trident->ac97)) < 0) {
2976                 if (trident->device == TRIDENT_DEVICE_ID_SI7018) {
2977                         if ((err = snd_trident_sis_reset(trident)) < 0)
2978                                 goto __out;
2979                         if (retries-- > 0)
2980                                 goto __again;
2981                         err = -EIO;
2982                 }
2983                 goto __out;
2984         }
2985         
2986         /* secondary codec? */
2987         if (trident->device == TRIDENT_DEVICE_ID_SI7018 &&
2988             (inl(TRID_REG(trident, SI_SERIAL_INTF_CTRL)) & SI_AC97_PRIMARY_READY) != 0) {
2989                 _ac97.num = 1;
2990                 err = snd_ac97_mixer(trident->card, &_ac97, &trident->ac97_sec);
2991                 if (err < 0)
2992                         snd_printk("SI7018: the secondary codec - invalid access\n");
2993 #if 0   // only for my testing purpose --jk
2994                 {
2995                         ac97_t *mc97;
2996                         err = snd_ac97_modem(trident->card, &_ac97, &mc97);
2997                         if (err < 0)
2998                                 snd_printk("snd_ac97_modem returned error %i\n", err);
2999                 }
3000 #endif
3001         }
3002         
3003         trident->ac97_detect = 0;
3004 
3005         if (trident->device != TRIDENT_DEVICE_ID_SI7018) {
3006                 if ((err = snd_ctl_add(card, kctl = snd_ctl_new1(&snd_trident_vol_wave_control, trident))) < 0)
3007                         goto __out;
3008                 kctl->put(kctl, uctl);
3009                 if ((err = snd_ctl_add(card, kctl = snd_ctl_new1(&snd_trident_vol_music_control, trident))) < 0)
3010                         goto __out;
3011                 kctl->put(kctl, uctl);
3012                 outl(trident->musicvol_wavevol = 0x00000000, TRID_REG(trident, T4D_MUSICVOL_WAVEVOL));
3013         } else {
3014                 outl(trident->musicvol_wavevol = 0xffff0000, TRID_REG(trident, T4D_MUSICVOL_WAVEVOL));
3015         }
3016 
3017         for (idx = 0; idx < 32; idx++) {
3018                 snd_trident_pcm_mixer_t *tmix;
3019                 
3020                 tmix = &trident->pcm_mixer[idx];
3021                 tmix->voice = NULL;
3022         }
3023         if ((trident->ctl_vol = snd_ctl_new1(&snd_trident_pcm_vol_control, trident)) == NULL)
3024                 goto __nomem;
3025         if ((err = snd_ctl_add(card, trident->ctl_vol)))
3026                 goto __out;
3027                 
3028         if ((trident->ctl_pan = snd_ctl_new1(&snd_trident_pcm_pan_control, trident)) == NULL)
3029                 goto __nomem;
3030         if ((err = snd_ctl_add(card, trident->ctl_pan)))
3031                 goto __out;
3032 
3033         if ((trident->ctl_rvol = snd_ctl_new1(&snd_trident_pcm_rvol_control, trident)) == NULL)
3034                 goto __nomem;
3035         if ((err = snd_ctl_add(card, trident->ctl_rvol)))
3036                 goto __out;
3037 
3038         if ((trident->ctl_cvol = snd_ctl_new1(&snd_trident_pcm_cvol_control, trident)) == NULL)
3039                 goto __nomem;
3040         if ((err = snd_ctl_add(card, trident->ctl_cvol)))
3041                 goto __out;
3042 
3043         if (trident->device == TRIDENT_DEVICE_ID_NX) {
3044                 if ((err = snd_ctl_add(card, kctl = snd_ctl_new1(&snd_trident_ac97_rear_control, trident))) < 0)
3045                         goto __out;
3046                 kctl->put(kctl, uctl);
3047         }
3048         if (trident->device == TRIDENT_DEVICE_ID_NX || trident->device == TRIDENT_DEVICE_ID_SI7018) {
3049 
3050                 if ((err = snd_ctl_add(card, kctl = snd_ctl_new1(&snd_trident_spdif_control, trident))) < 0)
3051                         goto __out;
3052                 if (trident->ac97->ext_id & AC97_EI_SPDIF)
3053                         kctl->id.index++;
3054                 if (trident->ac97_sec && (trident->ac97_sec->ext_id & AC97_EI_SPDIF))
3055                         kctl->id.index++;
3056                 idx = kctl->id.index;
3057                 kctl->put(kctl, uctl);
3058 
3059                 if ((err = snd_ctl_add(card, kctl = snd_ctl_new1(&snd_trident_spdif_default, trident))) < 0)
3060                         goto __out;
3061                 kctl->id.index = idx;
3062                 kctl->id.device = pcm_spdif_device;
3063 
3064                 if ((err = snd_ctl_add(card, kctl = snd_ctl_new1(&snd_trident_spdif_mask, trident))) < 0)
3065                         goto __out;
3066                 kctl->id.index = idx;
3067                 kctl->id.device = pcm_spdif_device;
3068 
3069                 if ((err = snd_ctl_add(card, kctl = snd_ctl_new1(&snd_trident_spdif_stream, trident))) < 0)
3070                         goto __out;
3071                 kctl->id.index = idx;
3072                 kctl->id.device = pcm_spdif_device;
3073                 trident->spdif_pcm_ctl = kctl;
3074         }
3075 
3076         err = 0;
3077         goto __out;
3078 
3079  __nomem:
3080         err = -ENOMEM;
3081 
3082  __out:
3083         kfree(uctl);
3084 
3085         return err;
3086 }
3087 
3088 /*
3089  * gameport interface
3090  */
3091 
3092 #if defined(CONFIG_GAMEPORT) || (defined(MODULE) && defined(CONFIG_GAMEPORT_MODULE))
3093 
3094 typedef struct snd_trident_gameport {
3095         struct gameport info;
3096         trident_t *chip;
3097 } trident_gameport_t;
3098 
3099 static unsigned char snd_trident_gameport_read(struct gameport *gameport)
3100 {
3101         trident_gameport_t *gp = (trident_gameport_t *)gameport;
3102         trident_t *chip;
3103         snd_assert(gp, return 0);
3104         chip = snd_magic_cast(trident_t, gp->chip, return 0);
3105         return inb(TRID_REG(chip, GAMEPORT_LEGACY));
3106 }
3107 
3108 static void snd_trident_gameport_trigger(struct gameport *gameport)
3109 {
3110         trident_gameport_t *gp = (trident_gameport_t *)gameport;
3111         trident_t *chip;
3112         snd_assert(gp, return);
3113         chip = snd_magic_cast(trident_t, gp->chip, return);
3114         outb(0xff, TRID_REG(chip, GAMEPORT_LEGACY));
3115 }
3116 
3117 static int snd_trident_gameport_cooked_read(struct gameport *gameport, int *axes, int *buttons)
3118 {
3119         trident_gameport_t *gp = (trident_gameport_t *)gameport;
3120         trident_t *chip;
3121         int i;
3122 
3123         snd_assert(gp, return 0);
3124         chip = snd_magic_cast(trident_t, gp->chip, return 0);
3125 
3126         *buttons = (~inb(TRID_REG(chip, GAMEPORT_LEGACY)) >> 4) & 0xf;
3127 
3128         for (i = 0; i < 4; i++) {
3129                 axes[i] = inw(TRID_REG(chip, GAMEPORT_AXES + i * 2));
3130                 if (axes[i] == 0xffff) axes[i] = -1;
3131         }
3132         
3133         return 0;
3134 }
3135 
3136 static int snd_trident_gameport_open(struct gameport *gameport, int mode)
3137 {
3138         trident_gameport_t *gp = (trident_gameport_t *)gameport;
3139         trident_t *chip;
3140         snd_assert(gp, return -1);
3141         chip = snd_magic_cast(trident_t, gp->chip, return -1);
3142 
3143         switch (mode) {
3144                 case GAMEPORT_MODE_COOKED:
3145                         outb(GAMEPORT_MODE_ADC, TRID_REG(chip, GAMEPORT_GCR));
3146                         set_current_state(TASK_UNINTERRUPTIBLE);
3147                         schedule_timeout(1 + 20 * HZ / 1000); /* 20msec */
3148                         return 0;
3149                 case GAMEPORT_MODE_RAW:
3150                         outb(0, TRID_REG(chip, GAMEPORT_GCR));
3151                         return 0;
3152                 default:
3153                         return -1;
3154         }
3155 }
3156 
3157 void __devinit snd_trident_gameport(trident_t *chip)
3158 {
3159         trident_gameport_t *gp;
3160         gp = kmalloc(sizeof(*gp), GFP_KERNEL);
3161         if (! gp) {
3162                 snd_printk("cannot allocate gameport area\n");
3163                 return;
3164         }
3165         memset(gp, 0, sizeof(*gp));
3166         gp->chip = chip;
3167         gp->info.fuzz = 64;
3168         gp->info.read = snd_trident_gameport_read;
3169         gp->info.trigger = snd_trident_gameport_trigger;
3170         gp->info.cooked_read = snd_trident_gameport_cooked_read;
3171         gp->info.open = snd_trident_gameport_open;
3172         chip->gameport = gp;
3173 
3174         gameport_register_port(&gp->info);
3175 }
3176 
3177 #else
3178 void __devinit snd_trident_gameport(trident_t *chip)
3179 {
3180 }
3181 #endif /* CONFIG_GAMEPORT */
3182 
3183 /*
3184  * delay for 1 tick
3185  */
3186 inline static void do_delay(trident_t *chip)
3187 {
3188         set_current_state(TASK_UNINTERRUPTIBLE);
3189         schedule_timeout(1);
3190 }
3191 
3192 /*
3193  *  SiS reset routine
3194  */
3195 
3196 static int snd_trident_sis_reset(trident_t *trident)
3197 {
3198         unsigned long end_time;
3199         unsigned int i;
3200         int r;
3201 
3202         r = trident->in_suspend ? 0 : 2;        /* count of retries */
3203       __si7018_retry:
3204         pci_write_config_byte(trident->pci, 0x46, 0x04);        /* SOFTWARE RESET */
3205         udelay(100);
3206         pci_write_config_byte(trident->pci, 0x46, 0x00);
3207         udelay(100);
3208         /* disable AC97 GPIO interrupt */
3209         outb(0x00, TRID_REG(trident, SI_AC97_GPIO));
3210         /* initialize serial interface, force cold reset */
3211         i = PCMOUT|SURROUT|CENTEROUT|LFEOUT|SECONDARY_ID|COLD_RESET;
3212         outl(i, TRID_REG(trident, SI_SERIAL_INTF_CTRL));
3213         udelay(1000);
3214         /* remove cold reset */
3215         i &= ~COLD_RESET;
3216         outl(i, TRID_REG(trident, SI_SERIAL_INTF_CTRL));
3217         udelay(2000);
3218         /* wait, until the codec is ready */
3219         end_time = (jiffies + (HZ * 3) / 4) + 1;
3220         do {
3221                 if ((inl(TRID_REG(trident, SI_SERIAL_INTF_CTRL)) & SI_AC97_PRIMARY_READY) != 0)
3222                         goto __si7018_ok;
3223                 do_delay(trident);
3224         } while (time_after_eq(end_time, jiffies));
3225         snd_printk("AC'97 codec ready error [0x%x]\n", inl(TRID_REG(trident, SI_SERIAL_INTF_CTRL)));
3226         if (r-- > 0) {
3227                 end_time = jiffies + HZ;
3228                 do {
3229                         do_delay(trident);
3230                 } while (time_after_eq(end_time, jiffies));
3231                 goto __si7018_retry;
3232         }
3233       __si7018_ok:
3234         /* wait for the second codec */
3235         do {
3236                 if ((inl(TRID_REG(trident, SI_SERIAL_INTF_CTRL)) & SI_AC97_SECONDARY_READY) != 0)
3237                         break;
3238                 do_delay(trident);
3239         } while (time_after_eq(end_time, jiffies));
3240         /* enable 64 channel mode */
3241         outl(BANK_B_EN, TRID_REG(trident, T4D_LFO_GC_CIR));
3242         return 0;
3243 }
3244 
3245 /*  
3246  *  /proc interface
3247  */
3248 
3249 static void snd_trident_proc_read(snd_info_entry_t *entry, 
3250                                   snd_info_buffer_t * buffer)
3251 {
3252         trident_t *trident = snd_magic_cast(trident_t, entry->private_data, return);
3253         char *s;
3254 
3255         switch (trident->device) {
3256         case TRIDENT_DEVICE_ID_SI7018:
3257                 s = "SiS 7018 Audio";
3258                 break;
3259         case TRIDENT_DEVICE_ID_DX:
3260                 s = "Trident 4DWave PCI DX";
3261                 break;
3262         case TRIDENT_DEVICE_ID_NX:
3263                 s = "Trident 4DWave PCI NX";
3264                 break;
3265         default:
3266                 s = "???";
3267         }
3268         snd_iprintf(buffer, "%s\n\n", s);
3269         snd_iprintf(buffer, "Spurious IRQs    : %d\n", trident->spurious_irq_count);
3270         snd_iprintf(buffer, "Spurious IRQ dlta: %d\n", trident->spurious_irq_max_delta);
3271         if (trident->device == TRIDENT_DEVICE_ID_NX || trident->device == TRIDENT_DEVICE_ID_SI7018)
3272                 snd_iprintf(buffer, "IEC958 Mixer Out : %s\n", trident->spdif_ctrl == 0x28 ? "on" : "off");
3273         if (trident->device == TRIDENT_DEVICE_ID_NX) {
3274                 snd_iprintf(buffer, "Rear Speakers    : %s\n", trident->ac97_ctrl & 0x00000010 ? "on" : "off");
3275                 if (trident->tlb.entries) {
3276                         snd_iprintf(buffer,"\nVirtual Memory\n");
3277                         snd_iprintf(buffer, "Memory Maximum : %d\n", trident->tlb.memhdr->size);
3278                         snd_iprintf(buffer, "Memory Used    : %d\n", trident->tlb.memhdr->used);
3279                         snd_iprintf(buffer, "Memory Free    : %d\n", snd_util_mem_avail(trident->tlb.memhdr));
3280                 }
3281         }
3282 #if defined(CONFIG_SND_SEQUENCER) || (defined(MODULE) && defined(CONFIG_SND_SEQUENCER_MODULE))
3283         snd_iprintf(buffer,"\nWavetable Synth\n");
3284         snd_iprintf(buffer, "Memory Maximum : %d\n", trident->synth.max_size);
3285         snd_iprintf(buffer, "Memory Used    : %d\n", trident->synth.current_size);
3286         snd_iprintf(buffer, "Memory Free    : %d\n", (trident->synth.max_size-trident->synth.current_size));
3287 #endif
3288 }
3289 
3290 static void __devinit snd_trident_proc_init(trident_t * trident)
3291 {
3292         snd_info_entry_t *entry;
3293         const char *s = "trident";
3294         
3295         if (trident->device == TRIDENT_DEVICE_ID_SI7018)
3296                 s = "sis7018";
3297         if (! snd_card_proc_new(trident->card, s, &entry))
3298                 snd_info_set_text_ops(entry, trident, snd_trident_proc_read);
3299 }
3300 
3301 static int snd_trident_dev_free(snd_device_t *device)
3302 {
3303         trident_t *trident = snd_magic_cast(trident_t, device->device_data, return -ENXIO);
3304         return snd_trident_free(trident);
3305 }
3306 
3307 /*---------------------------------------------------------------------------
3308    snd_trident_tlb_alloc
3309   
3310    Description: Allocate and set up the TLB page table on 4D NX.
3311                 Each entry has 4 bytes (physical PCI address).
3312                 
3313    Paramters:   trident - pointer to target device class for 4DWave.
3314 
3315    Returns:     0 or negative error code
3316   
3317   ---------------------------------------------------------------------------*/
3318 
3319 static int __devinit snd_trident_tlb_alloc(trident_t *trident)
3320 {
3321         int i;
3322 
3323         /* TLB array must be aligned to 16kB !!! so we allocate
3324            32kB region and correct offset when necessary */
3325 
3326         trident->tlb.buffer = snd_malloc_pci_pages(trident->pci, 2 * SNDRV_TRIDENT_MAX_PAGES * 4, &trident->tlb.buffer_dmaaddr);
3327         if (trident->tlb.buffer == NULL) {
3328                 snd_printk(KERN_ERR "trident: unable to allocate TLB buffer\n");
3329                 return -ENOMEM;
3330         }
3331         trident->tlb.entries = (unsigned int*)(((unsigned long)trident->tlb.buffer + SNDRV_TRIDENT_MAX_PAGES * 4 - 1) & ~(SNDRV_TRIDENT_MAX_PAGES * 4 - 1));
3332         trident->tlb.entries_dmaaddr = (trident->tlb.buffer_dmaaddr + SNDRV_TRIDENT_MAX_PAGES * 4 - 1) & ~(SNDRV_TRIDENT_MAX_PAGES * 4 - 1);
3333         /* allocate shadow TLB page table (virtual addresses) */
3334         trident->tlb.shadow_entries = (unsigned long *)vmalloc(SNDRV_TRIDENT_MAX_PAGES*sizeof(unsigned long));
3335         if (trident->tlb.shadow_entries == NULL) {
3336                 snd_printk(KERN_ERR "trident: unable to allocate shadow TLB entries\n");
3337                 return -ENOMEM;
3338         }
3339         /* allocate and setup silent page and initialise TLB entries */
3340         trident->tlb.silent_page = snd_malloc_pci_pages(trident->pci, SNDRV_TRIDENT_PAGE_SIZE, &trident->tlb.silent_page_dmaaddr);
3341         if (trident->tlb.silent_page == 0UL) {
3342                 snd_printk(KERN_ERR "trident: unable to allocate silent page\n");
3343                 return -ENOMEM;
3344         }
3345         memset(trident->tlb.silent_page, 0, SNDRV_TRIDENT_PAGE_SIZE);
3346         for (i = 0; i < SNDRV_TRIDENT_MAX_PAGES; i++) {
3347                 trident->tlb.entries[i] = cpu_to_le32(trident->tlb.silent_page_dmaaddr & ~(SNDRV_TRIDENT_PAGE_SIZE-1));
3348                 trident->tlb.shadow_entries[i] = (unsigned long)trident->tlb.silent_page;
3349         }
3350 
3351         /* use emu memory block manager code to manage tlb page allocation */
3352         trident->tlb.memhdr = snd_util_memhdr_new(SNDRV_TRIDENT_PAGE_SIZE * SNDRV_TRIDENT_MAX_PAGES);
3353         if (trident->tlb.memhdr == NULL)
3354                 return -ENOMEM;
3355 
3356         trident->tlb.memhdr->block_extra_size = sizeof(snd_trident_memblk_arg_t);
3357         return 0;
3358 }
3359 
3360 /*
3361  * initialize 4D DX chip
3362  */
3363 
3364 static void snd_trident_stop_all_voices(trident_t *trident)
3365 {
3366         outl(0xffffffff, TRID_REG(trident, T4D_STOP_A));
3367         outl(0xffffffff, TRID_REG(trident, T4D_STOP_B));
3368         outl(0, TRID_REG(trident, T4D_AINTEN_A));
3369         outl(0, TRID_REG(trident, T4D_AINTEN_B));
3370 }
3371 
3372 static int snd_trident_4d_dx_init(trident_t *trident)
3373 {
3374         struct pci_dev *pci = trident->pci;
3375         unsigned long end_time;
3376 
3377         /* reset the legacy configuration and whole audio/wavetable block */
3378         pci_write_config_dword(pci, 0x40, 0);   /* DDMA */
3379         pci_write_config_byte(pci, 0x44, 0);    /* ports */
3380         pci_write_config_byte(pci, 0x45, 0);    /* Legacy DMA */
3381         pci_write_config_byte(pci, 0x46, 4); /* reset */
3382         udelay(100);
3383         pci_write_config_byte(pci, 0x46, 0); /* release reset */
3384         udelay(100);
3385         
3386         /* warm reset of the AC'97 codec */
3387         outl(0x00000001, TRID_REG(trident, DX_ACR2_AC97_COM_STAT));
3388         udelay(100);
3389         outl(0x00000000, TRID_REG(trident, DX_ACR2_AC97_COM_STAT));
3390         /* DAC on, disable SB IRQ and try to force ADC valid signal */
3391         trident->ac97_ctrl = 0x0000004a;
3392         outl(trident->ac97_ctrl, TRID_REG(trident, DX_ACR2_AC97_COM_STAT));
3393         /* wait, until the codec is ready */
3394         end_time = (jiffies + (HZ * 3) / 4) + 1;
3395         do {
3396                 if ((inl(TRID_REG(trident, DX_ACR2_AC97_COM_STAT)) & 0x0010) != 0)
3397                         goto __dx_ok;
3398                 do_delay(trident);
3399         } while (time_after_eq(end_time, jiffies));
3400         snd_printk(KERN_ERR "AC'97 codec ready error\n");
3401         return -EIO;
3402 
3403  __dx_ok:
3404         snd_trident_stop_all_voices(trident);
3405 
3406         return 0;
3407 }
3408 
3409 /*
3410  * initialize 4D NX chip
3411  */
3412 static int snd_trident_4d_nx_init(trident_t *trident)
3413 {
3414         struct pci_dev *pci = trident->pci;
3415         unsigned long end_time;
3416 
3417         /* reset the legacy configuration and whole audio/wavetable block */
3418         pci_write_config_dword(pci, 0x40, 0);   /* DDMA */
3419         pci_write_config_byte(pci, 0x44, 0);    /* ports */
3420         pci_write_config_byte(pci, 0x45, 0);    /* Legacy DMA */
3421 
3422         pci_write_config_byte(pci, 0x46, 1); /* reset */
3423         udelay(100);
3424         pci_write_config_byte(pci, 0x46, 0); /* release reset */
3425         udelay(100);
3426 
3427         /* warm reset of the AC'97 codec */
3428         outl(0x00000001, TRID_REG(trident, NX_ACR0_AC97_COM_STAT));
3429         udelay(100);
3430         outl(0x00000000, TRID_REG(trident, NX_ACR0_AC97_COM_STAT));
3431         /* wait, until the codec is ready */
3432         end_time = (jiffies + (HZ * 3) / 4) + 1;
3433         do {
3434                 if ((inl(TRID_REG(trident, NX_ACR0_AC97_COM_STAT)) & 0x0008) != 0)
3435                         goto __nx_ok;
3436                 do_delay(trident);
3437         } while (time_after_eq(end_time, jiffies));
3438         snd_printk(KERN_ERR "AC'97 codec ready error [0x%x]\n", inl(TRID_REG(trident, NX_ACR0_AC97_COM_STAT)));
3439         return -EIO;
3440 
3441  __nx_ok:
3442         /* DAC on */
3443         trident->ac97_ctrl = 0x00000002;
3444         outl(trident->ac97_ctrl, TRID_REG(trident, NX_ACR0_AC97_COM_STAT));
3445         /* disable SB IRQ */
3446         outl(NX_SB_IRQ_DISABLE, TRID_REG(trident, T4D_MISCINT));
3447 
3448         snd_trident_stop_all_voices(trident);
3449 
3450         if (trident->tlb.entries != NULL) {
3451                 unsigned int i;
3452                 /* enable virtual addressing via TLB */
3453                 i = trident->tlb.entries_dmaaddr;
3454                 i |= 0x00000001;
3455                 outl(i, TRID_REG(trident, NX_TLBC));
3456         } else {
3457                 outl(0, TRID_REG(trident, NX_TLBC));
3458         }
3459         /* initialize S/PDIF */
3460         outl(trident->spdif_bits, TRID_REG(trident, NX_SPCSTATUS));
3461         outb(trident->spdif_ctrl, TRID_REG(trident, NX_SPCTRL_SPCSO + 3));
3462 
3463         return 0;
3464 }
3465 
3466 /*
3467  * initialize sis7018 chip
3468  */
3469 static int snd_trident_sis_init(trident_t *trident)
3470 {
3471         int err;
3472 
3473         if ((err = snd_trident_sis_reset(trident)) < 0)
3474                 return err;
3475 
3476         snd_trident_stop_all_voices(trident);
3477 
3478         /* initialize S/PDIF */
3479         outl(trident->spdif_bits, TRID_REG(trident, SI_SPDIF_CS));
3480 
3481         return 0;
3482 }
3483 
3484 /*---------------------------------------------------------------------------
3485    snd_trident_create
3486   
3487    Description: This routine will create the device specific class for
3488                 the 4DWave card. It will also perform basic initialization.
3489                 
3490    Paramters:   card  - which card to create
3491                 pci   - interface to PCI bus resource info
3492                 dma1ptr - playback dma buffer
3493                 dma2ptr - capture dma buffer
3494                 irqptr  -  interrupt resource info
3495 
3496    Returns:     4DWave device class private data
3497   
3498   ---------------------------------------------------------------------------*/
3499 
3500 int __devinit snd_trident_create(snd_card_t * card,
3501                        struct pci_dev *pci,
3502                        int pcm_streams,
3503                        int pcm_spdif_device,
3504                        int max_wavetable_size,
3505                        trident_t ** rtrident)
3506 {
3507         trident_t *trident;
3508         int i, err;
3509         snd_trident_voice_t *voice;
3510         snd_trident_pcm_mixer_t *tmix;
3511         static snd_device_ops_t ops = {
3512                 .dev_free =     snd_trident_dev_free,
3513         };
3514 
3515         *rtrident = NULL;
3516 
3517         /* enable PCI device */
3518         if ((err = pci_enable_device(pci)) < 0)
3519                 return err;
3520         /* check, if we can restrict PCI DMA transfers to 30 bits */
3521         if (!pci_dma_supported(pci, 0x3fffffff)) {
3522                 snd_printk("architecture does not support 30bit PCI busmaster DMA\n");
3523                 return -ENXIO;
3524         }
3525         pci_set_dma_mask(pci, 0x3fffffff);
3526         
3527         trident = snd_magic_kcalloc(trident_t, 0, GFP_KERNEL);
3528         if (trident == NULL)
3529                 return -ENOMEM;
3530         trident->device = (pci->vendor << 16) | pci->device;
3531         trident->card = card;
3532         trident->pci = pci;
3533         spin_lock_init(&trident->reg_lock);
3534         spin_lock_init(&trident->event_lock);
3535         spin_lock_init(&trident->voice_alloc);
3536         if (pcm_streams < 1)
3537                 pcm_streams = 1;
3538         if (pcm_streams > 32)
3539                 pcm_streams = 32;
3540         trident->ChanPCM = pcm_streams;
3541         if (max_wavetable_size < 0 )
3542                 max_wavetable_size = 0;
3543         trident->synth.max_size = max_wavetable_size * 1024;
3544         trident->port = pci_resource_start(pci, 0);
3545         trident->irq = -1;
3546 
3547         trident->midi_port = TRID_REG(trident, T4D_MPU401_BASE);
3548         pci_set_master(pci);
3549         trident->port = pci_resource_start(pci, 0);
3550 
3551         if ((trident->res_port = request_region(trident->port, 0x100, "Trident Audio")) == NULL) {
3552                 snd_printk("unable to grab I/O region 0x%lx-0x%lx\n", trident->port, trident->port + 0x100 - 1);
3553                 snd_trident_free(trident);
3554                 return -EBUSY;
3555         }
3556         if (request_irq(pci->irq, snd_trident_interrupt, SA_INTERRUPT|SA_SHIRQ, "Trident Audio", (void *) trident)) {
3557                 snd_printk("unable to grab IRQ %d\n", pci->irq);
3558                 snd_trident_free(trident);
3559                 return -EBUSY;
3560         }
3561         trident->irq = pci->irq;
3562 
3563         /* allocate 16k-aligned TLB for NX cards */
3564         trident->tlb.entries = NULL;
3565         trident->tlb.buffer = NULL;
3566         if (trident->device == TRIDENT_DEVICE_ID_NX) {
3567                 if ((err = snd_trident_tlb_alloc(trident)) < 0) {
3568                         snd_trident_free(trident);
3569                         return err;
3570                 }
3571         }
3572 
3573         trident->spdif_bits = trident->spdif_pcm_bits = SNDRV_PCM_DEFAULT_CON_SPDIF;
3574 
3575         /* initialize chip */
3576         switch (trident->device) {
3577         case TRIDENT_DEVICE_ID_DX:
3578                 err = snd_trident_4d_dx_init(trident);
3579                 break;
3580         case TRIDENT_DEVICE_ID_NX:
3581                 err = snd_trident_4d_nx_init(trident);
3582                 break;
3583         case TRIDENT_DEVICE_ID_SI7018:
3584                 err = snd_trident_sis_init(trident);
3585                 break;
3586         default:
3587                 snd_BUG();
3588                 break;
3589         }
3590         if (err < 0) {
3591                 snd_trident_free(trident);
3592                 return err;
3593         }
3594 
3595         if ((err = snd_trident_mixer(trident, pcm_spdif_device)) < 0) {
3596                 snd_trident_free(trident);
3597                 return err;
3598         }
3599         
3600         /* initialise synth voices */
3601         for (i = 0; i < 64; i++) {
3602                 voice = &trident->synth.voices[i];
3603                 voice->number = i;
3604                 voice->trident = trident;
3605         }
3606         /* initialize pcm mixer entries */
3607         for (i = 0; i < 32; i++) {
3608                 tmix = &trident->pcm_mixer[i];
3609                 tmix->vol = T4D_DEFAULT_PCM_VOL;
3610                 tmix->pan = T4D_DEFAULT_PCM_PAN;
3611                 tmix->rvol = T4D_DEFAULT_PCM_RVOL;
3612                 tmix->cvol = T4D_DEFAULT_PCM_CVOL;
3613         }
3614 
3615         snd_trident_enable_eso(trident);
3616 
3617 #ifdef CONFIG_PM
3618         card->set_power_state = snd_trident_set_power_state;
3619         card->power_state_private_data = trident;
3620 #endif
3621 
3622         snd_trident_proc_init(trident);
3623         if ((err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, trident, &ops)) < 0) {
3624                 snd_trident_free(trident);
3625                 return err;
3626         }
3627         *rtrident = trident;
3628         return 0;
3629 }
3630 
3631 /*---------------------------------------------------------------------------
3632    snd_trident_free
3633   
3634    Description: This routine will free the device specific class for
3635             q    the 4DWave card. 
3636                 
3637    Paramters:   trident  - device specific private data for 4DWave card
3638 
3639    Returns:     None.
3640   
3641   ---------------------------------------------------------------------------*/
3642 
3643 int snd_trident_free(trident_t *trident)
3644 {
3645 #if defined(CONFIG_GAMEPORT) || (defined(MODULE) && defined(CONFIG_GAMEPORT_MODULE))
3646         if (trident->gameport) {
3647                 gameport_unregister_port(&trident->gameport->info);
3648                 kfree(trident->gameport);
3649         }
3650 #endif
3651         snd_trident_disable_eso(trident);
3652         // Disable S/PDIF out
3653         if (trident->device == TRIDENT_DEVICE_ID_NX)
3654                 outb(0x00, TRID_REG(trident, NX_SPCTRL_SPCSO + 3));
3655         else if (trident->device == TRIDENT_DEVICE_ID_SI7018) {
3656                 outl(0, TRID_REG(trident, SI_SERIAL_INTF_CTRL));
3657         }
3658         if (trident->tlb.buffer) {
3659                 outl(0, TRID_REG(trident, NX_TLBC));
3660                 if (trident->tlb.memhdr)
3661                         snd_util_memhdr_free(trident->tlb.memhdr);
3662                 if (trident->tlb.silent_page)
3663                         snd_free_pci_pages(trident->pci, SNDRV_TRIDENT_PAGE_SIZE, trident->tlb.silent_page, trident->tlb.silent_page_dmaaddr);
3664                 if (trident->tlb.shadow_entries)
3665                         vfree(trident->tlb.shadow_entries);
3666                 snd_free_pci_pages(trident->pci, 2 * SNDRV_TRIDENT_MAX_PAGES * 4, trident->tlb.buffer, trident->tlb.buffer_dmaaddr);
3667         }
3668         if (trident->irq >= 0)
3669                 free_irq(trident->irq, (void *)trident);
3670         if (trident->res_port) {
3671                 release_resource(trident->res_port);
3672                 kfree_nocheck(trident->res_port);
3673         }
3674         snd_magic_kfree(trident);
3675         return 0;
3676 }
3677 
3678 /*---------------------------------------------------------------------------
3679    snd_trident_interrupt
3680   
3681    Description: ISR for Trident 4DWave device
3682                 
3683    Paramters:   trident  - device specific private data for 4DWave card
3684 
3685    Problems:    It seems that Trident chips generates interrupts more than
3686                 one time in special cases. The spurious interrupts are
3687                 detected via sample timer (T4D_STIMER) and computing
3688                 corresponding delta value. The limits are detected with
3689                 the method try & fail so it is possible that it won't
3690                 work on all computers. [jaroslav]
3691 
3692    Returns:     None.
3693   
3694   ---------------------------------------------------------------------------*/
3695 
3696 static irqreturn_t snd_trident_interrupt(int irq, void *dev_id, struct pt_regs *regs)
3697 {
3698         trident_t *trident = snd_magic_cast(trident_t, dev_id, return IRQ_NONE);
3699         unsigned int audio_int, chn_int, stimer, channel, mask, tmp;
3700         int delta;
3701         snd_trident_voice_t *voice;
3702 
3703         audio_int = inl(TRID_REG(trident, T4D_MISCINT));
3704         if ((audio_int & (ADDRESS_IRQ|MPU401_IRQ)) == 0)
3705                 return IRQ_NONE;
3706         if (audio_int & ADDRESS_IRQ) {
3707                 // get interrupt status for all channels
3708                 spin_lock(&trident->reg_lock);
3709                 stimer = inl(TRID_REG(trident, T4D_STIMER)) & 0x00ffffff;
3710                 chn_int = inl(TRID_REG(trident, T4D_AINT_A));
3711                 if (chn_int == 0)
3712                         goto __skip1;
3713                 outl(chn_int, TRID_REG(trident, T4D_AINT_A));   /* ack */
3714               __skip1:
3715                 chn_int = inl(TRID_REG(trident, T4D_AINT_B));
3716                 if (chn_int == 0)
3717                         goto __skip2;
3718                 for (channel = 63; channel >= 32; channel--) {
3719                         mask = 1 << (channel&0x1f);
3720                         if ((chn_int & mask) == 0)
3721                                 continue;
3722                         voice = &trident->synth.voices[channel];
3723                         if (!voice->pcm || voice->substream == NULL) {
3724                                 outl(mask, TRID_REG(trident, T4D_STOP_B));
3725                                 continue;
3726                         }
3727                         delta = (int)stimer - (int)voice->stimer;
3728                         if (delta < 0)
3729                                 delta = -delta;
3730                         if ((unsigned int)delta < voice->spurious_threshold) {
3731                                 /* do some statistics here */
3732                                 trident->spurious_irq_count++;
3733                                 if (trident->spurious_irq_max_delta < (unsigned int)delta)
3734                                         trident->spurious_irq_max_delta = delta;
3735                                 continue;
3736                         }
3737                         voice->stimer = stimer;
3738                         if (voice->isync) {
3739                                 if (!voice->isync3) {
3740                                         tmp = inw(TRID_REG(trident, T4D_SBBL_SBCL));
3741                                         if (trident->bDMAStart & 0x40)
3742                                                 tmp >>= 1;
3743                                         if (tmp > 0)
3744                                                 tmp = voice->isync_max - tmp;
3745                                 } else {
3746                                         tmp = inl(TRID_REG(trident, NX_SPCTRL_SPCSO)) & 0x00ffffff;
3747                                 }
3748                                 if (tmp < voice->isync_mark) {
3749                                         if (tmp > 0x10)
3750                                                 tmp = voice->isync_ESO - 7;
3751                                         else
3752                                                 tmp = voice->isync_ESO + 2;
3753                                         /* update ESO for IRQ voice to preserve sync */
3754                                         snd_trident_stop_voice(trident, voice->number);
3755                                         snd_trident_write_eso_reg(trident, voice, tmp);
3756                                         snd_trident_start_voice(trident, voice->number);
3757                                 }
3758                         } else if (voice->isync2) {
3759                                 voice->isync2 = 0;
3760                                 /* write original ESO and update CSO for IRQ voice to preserve sync */
3761                                 snd_trident_stop_voice(trident, voice->number);
3762                                 snd_trident_write_cso_reg(trident, voice, voice->isync_mark);
3763                                 snd_trident_write_eso_reg(trident, voice, voice->ESO);
3764                                 snd_trident_start_voice(trident, voice->number);
3765                         }
3766 #if 0
3767                         if (voice->extra) {
3768                                 /* update CSO for extra voice to preserve sync */
3769                                 snd_trident_stop_voice(trident, voice->extra->number);
3770                                 snd_trident_write_cso_reg(trident, voice->extra, 0);
3771                                 snd_trident_start_voice(trident, voice->extra->number);
3772                         }
3773 #endif
3774                         spin_unlock(&trident->reg_lock);
3775                         snd_pcm_period_elapsed(voice->substream);
3776                         spin_lock(&trident->reg_lock);
3777                 }
3778                 outl(chn_int, TRID_REG(trident, T4D_AINT_B));   /* ack */
3779               __skip2:
3780                 spin_unlock(&trident->reg_lock);
3781         }
3782         if (audio_int & MPU401_IRQ) {
3783                 if (trident->rmidi) {
3784                         snd_mpu401_uart_interrupt(irq, trident->rmidi->private_data, regs);
3785                 } else {
3786                         inb(TRID_REG(trident, T4D_MPUR0));
3787                 }
3788         }
3789         // outl((ST_TARGET_REACHED | MIXER_OVERFLOW | MIXER_UNDERFLOW), TRID_REG(trident, T4D_MISCINT));
3790         return IRQ_HANDLED;
3791 }
3792 
3793 /*---------------------------------------------------------------------------
3794    snd_trident_attach_synthesizer, snd_trident_detach_synthesizer
3795   
3796    Description: Attach/detach synthesizer hooks
3797                 
3798    Paramters:   trident  - device specific private data for 4DWave card
3799 
3800    Returns:     None.
3801   
3802   ---------------------------------------------------------------------------*/
3803 int snd_trident_attach_synthesizer(trident_t *trident)
3804 {       
3805 #if defined(CONFIG_SND_SEQUENCER) || (defined(MODULE) && defined(CONFIG_SND_SEQUENCER_MODULE))
3806         if (snd_seq_device_new(trident->card, 1, SNDRV_SEQ_DEV_ID_TRIDENT,
3807                                sizeof(trident_t*), &trident->seq_dev) >= 0) {
3808                 strcpy(trident->seq_dev->name, "4DWave");
3809                 *(trident_t**)SNDRV_SEQ_DEVICE_ARGPTR(trident->seq_dev) = trident;
3810         }
3811 #endif
3812         return 0;
3813 }
3814 
3815 int snd_trident_detach_synthesizer(trident_t *trident)
3816 {
3817 #if defined(CONFIG_SND_SEQUENCER) || (defined(MODULE) && defined(CONFIG_SND_SEQUENCER_MODULE))
3818         if (trident->seq_dev) {
3819                 snd_device_free(trident->card, trident->seq_dev);
3820                 trident->seq_dev = NULL;
3821         }
3822 #endif
3823         return 0;
3824 }
3825 
3826 snd_trident_voice_t *snd_trident_alloc_voice(trident_t * trident, int type, int client, int port)
3827 {
3828         snd_trident_voice_t *pvoice;
3829         unsigned long flags;
3830         int idx;
3831 
3832         spin_lock_irqsave(&trident->voice_alloc, flags);
3833         if (type == SNDRV_TRIDENT_VOICE_TYPE_PCM) {
3834                 idx = snd_trident_allocate_pcm_channel(trident);
3835                 if(idx < 0) {
3836                         spin_unlock_irqrestore(&trident->voice_alloc, flags);
3837                         return NULL;
3838                 }
3839                 pvoice = &trident->synth.voices[idx];
3840                 pvoice->use = 1;
3841                 pvoice->pcm = 1;
3842                 pvoice->capture = 0;
3843                 pvoice->spdif = 0;
3844                 pvoice->memblk = NULL;
3845                 pvoice->substream = NULL;
3846                 spin_unlock_irqrestore(&trident->voice_alloc, flags);
3847                 return pvoice;
3848         }
3849         if (type == SNDRV_TRIDENT_VOICE_TYPE_SYNTH) {
3850                 idx = snd_trident_allocate_synth_channel(trident);
3851                 if(idx < 0) {
3852                         spin_unlock_irqrestore(&trident->voice_alloc, flags);
3853                         return NULL;
3854                 }
3855                 pvoice = &trident->synth.voices[idx];
3856                 pvoice->use = 1;
3857                 pvoice->synth = 1;
3858                 pvoice->client = client;
3859                 pvoice->port = port;
3860                 pvoice->memblk = NULL;
3861                 spin_unlock_irqrestore(&trident->voice_alloc, flags);
3862                 return pvoice;
3863         }
3864         if (type == SNDRV_TRIDENT_VOICE_TYPE_MIDI) {
3865         }
3866         spin_unlock_irqrestore(&trident->voice_alloc, flags);
3867         return NULL;
3868 }
3869 
3870 void snd_trident_free_voice(trident_t * trident, snd_trident_voice_t *voice)
3871 {
3872         unsigned long flags;
3873         void (*private_free)(snd_trident_voice_t *);
3874         void *private_data;
3875 
3876         if (voice == NULL || !voice->use)
3877                 return;
3878         snd_trident_clear_voices(trident, voice->number, voice->number);
3879         spin_lock_irqsave(&trident->voice_alloc, flags);
3880         private_free = voice->private_free;
3881         private_data = voice->private_data;
3882         voice->private_free = NULL;
3883         voice->private_data = NULL;
3884         if (voice->pcm)
3885                 snd_trident_free_pcm_channel(trident, voice->number);
3886         if (voice->synth)
3887                 snd_trident_free_synth_channel(trident, voice->number);
3888         voice->use = voice->pcm = voice->synth = voice->midi = 0;
3889         voice->capture = voice->spdif = 0;
3890         voice->sample_ops = NULL;
3891         voice->substream = NULL;
3892         voice->extra = NULL;
3893         spin_unlock_irqrestore(&trident->voice_alloc, flags);
3894         if (private_free)
3895                 private_free(voice);
3896 }
3897 
3898 void snd_trident_clear_voices(trident_t * trident, unsigned short v_min, unsigned short v_max)
3899 {
3900         unsigned int i, val, mask[2] = { 0, 0 };
3901 
3902         snd_assert(v_min <= 63, return);
3903         snd_assert(v_max <= 63, return);
3904         for (i = v_min; i <= v_max; i++)
3905                 mask[i >> 5] |= 1 << (i & 0x1f);
3906         if (mask[0]) {
3907                 outl(mask[0], TRID_REG(trident, T4D_STOP_A));
3908                 val = inl(TRID_REG(trident, T4D_AINTEN_A));
3909                 outl(val & ~mask[0], TRID_REG(trident, T4D_AINTEN_A));
3910         }
3911         if (mask[1]) {
3912                 outl(mask[1], TRID_REG(trident, T4D_STOP_B));
3913                 val = inl(TRID_REG(trident, T4D_AINTEN_B));
3914                 outl(val & ~mask[1], TRID_REG(trident, T4D_AINTEN_B));
3915         }
3916 }
3917 
3918 #ifdef CONFIG_PM
3919 
3920 void snd_trident_suspend(trident_t *trident)
3921 {
3922         snd_card_t *card = trident->card;
3923 
3924         if (card->power_state == SNDRV_CTL_POWER_D3hot)
3925                 return;
3926         trident->in_suspend = 1;
3927         snd_pcm_suspend_all(trident->pcm);
3928         if (trident->foldback)
3929                 snd_pcm_suspend_all(trident->foldback);
3930         if (trident->spdif)
3931                 snd_pcm_suspend_all(trident->spdif);
3932         switch (trident->device) {
3933         case TRIDENT_DEVICE_ID_DX:
3934         case TRIDENT_DEVICE_ID_NX:
3935                 break;                  /* TODO */
3936         case TRIDENT_DEVICE_ID_SI7018:
3937                 break;
3938         }
3939         snd_power_change_state(card, SNDRV_CTL_POWER_D3hot);
3940 }
3941 
3942 void snd_trident_resume(trident_t *trident)
3943 {
3944         snd_card_t *card = trident->card;
3945 
3946         if (card->power_state == SNDRV_CTL_POWER_D0)
3947                 return;
3948 
3949         pci_enable_device(trident->pci);
3950         pci_set_dma_mask(trident->pci, 0x3fffffff); /* to be sure */
3951         pci_set_master(trident->pci); /* to be sure */
3952 
3953         switch (trident->device) {
3954         case TRIDENT_DEVICE_ID_DX:
3955                 snd_trident_4d_dx_init(trident);
3956                 break;
3957         case TRIDENT_DEVICE_ID_NX:
3958                 snd_trident_4d_nx_init(trident);
3959                 break;
3960         case TRIDENT_DEVICE_ID_SI7018:
3961                 snd_trident_sis_init(trident);
3962                 break;
3963         }
3964 
3965         snd_ac97_resume(trident->ac97);
3966 
3967         /* restore some registers */
3968         outl(trident->musicvol_wavevol, TRID_REG(trident, T4D_MUSICVOL_WAVEVOL));
3969 
3970         snd_trident_enable_eso(trident);
3971 
3972         snd_power_change_state(card, SNDRV_CTL_POWER_D0);
3973         trident->in_suspend = 0;
3974 }
3975 
3976 static int snd_trident_set_power_state(snd_card_t *card, unsigned int power_state)
3977 {
3978         trident_t *chip = snd_magic_cast(trident_t, card->power_state_private_data, return -ENXIO);
3979         
3980         switch (power_state) {
3981         case SNDRV_CTL_POWER_D0:
3982         case SNDRV_CTL_POWER_D1:
3983         case SNDRV_CTL_POWER_D2:
3984                 snd_trident_resume(chip);
3985                 break;
3986         case SNDRV_CTL_POWER_D3hot:
3987         case SNDRV_CTL_POWER_D3cold:
3988                 snd_trident_suspend(chip);
3989                 break;
3990         default:
3991                 return -EINVAL;
3992         }
3993         return 0;
3994 }
3995 
3996 #endif /* CONFIG_PM */
3997 
3998 EXPORT_SYMBOL(snd_trident_alloc_voice);
3999 EXPORT_SYMBOL(snd_trident_free_voice);
4000 EXPORT_SYMBOL(snd_trident_start_voice);
4001 EXPORT_SYMBOL(snd_trident_stop_voice);
4002 EXPORT_SYMBOL(snd_trident_write_voice_regs);
4003 EXPORT_SYMBOL(snd_trident_clear_voices);
4004 /* trident_memory.c symbols */
4005 EXPORT_SYMBOL(snd_trident_synth_alloc);
4006 EXPORT_SYMBOL(snd_trident_synth_free);
4007 EXPORT_SYMBOL(snd_trident_synth_bzero);
4008 EXPORT_SYMBOL(snd_trident_synth_copy_from_user);
4009 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | Wiki (Japanese) | Wiki (English) | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

osdn.jp