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

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

Version: ~ [ linux-5.2 ] ~ [ linux-5.1.16 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.57 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.132 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.184 ] ~ [ linux-4.8.17 ] ~ [ linux-4.7.10 ] ~ [ linux-4.6.7 ] ~ [ linux-4.5.7 ] ~ [ linux-4.4.184 ] ~ [ linux-4.3.6 ] ~ [ linux-4.2.8 ] ~ [ linux-4.1.52 ] ~ [ linux-4.0.9 ] ~ [ linux-3.19.8 ] ~ [ linux-3.18.140 ] ~ [ linux-3.17.8 ] ~ [ linux-3.16.69 ] ~ [ 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@perex.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 <linux/delay.h>
 31 #include <linux/init.h>
 32 #include <linux/interrupt.h>
 33 #include <linux/pci.h>
 34 #include <linux/slab.h>
 35 #include <linux/vmalloc.h>
 36 #include <linux/gameport.h>
 37 #include <linux/dma-mapping.h>
 38 #include <linux/export.h>
 39 
 40 #include <sound/core.h>
 41 #include <sound/info.h>
 42 #include <sound/control.h>
 43 #include <sound/tlv.h>
 44 #include <sound/trident.h>
 45 #include <sound/asoundef.h>
 46 
 47 #include <asm/io.h>
 48 
 49 static int snd_trident_pcm_mixer_build(struct snd_trident *trident,
 50                                        struct snd_trident_voice * voice,
 51                                        struct snd_pcm_substream *substream);
 52 static int snd_trident_pcm_mixer_free(struct snd_trident *trident,
 53                                       struct snd_trident_voice * voice,
 54                                       struct snd_pcm_substream *substream);
 55 static irqreturn_t snd_trident_interrupt(int irq, void *dev_id);
 56 static int snd_trident_sis_reset(struct snd_trident *trident);
 57 
 58 static void snd_trident_clear_voices(struct snd_trident * trident,
 59                                      unsigned short v_min, unsigned short v_max);
 60 static int snd_trident_free(struct snd_trident *trident);
 61 
 62 /*
 63  *  common I/O routines
 64  */
 65 
 66 
 67 #if 0
 68 static void snd_trident_print_voice_regs(struct snd_trident *trident, int voice)
 69 {
 70         unsigned int val, tmp;
 71 
 72         printk(KERN_DEBUG "Trident voice %i:\n", voice);
 73         outb(voice, TRID_REG(trident, T4D_LFO_GC_CIR));
 74         val = inl(TRID_REG(trident, CH_LBA));
 75         printk(KERN_DEBUG "LBA: 0x%x\n", val);
 76         val = inl(TRID_REG(trident, CH_GVSEL_PAN_VOL_CTRL_EC));
 77         printk(KERN_DEBUG "GVSel: %i\n", val >> 31);
 78         printk(KERN_DEBUG "Pan: 0x%x\n", (val >> 24) & 0x7f);
 79         printk(KERN_DEBUG "Vol: 0x%x\n", (val >> 16) & 0xff);
 80         printk(KERN_DEBUG "CTRL: 0x%x\n", (val >> 12) & 0x0f);
 81         printk(KERN_DEBUG "EC: 0x%x\n", val & 0x0fff);
 82         if (trident->device != TRIDENT_DEVICE_ID_NX) {
 83                 val = inl(TRID_REG(trident, CH_DX_CSO_ALPHA_FMS));
 84                 printk(KERN_DEBUG "CSO: 0x%x\n", val >> 16);
 85                 printk("Alpha: 0x%x\n", (val >> 4) & 0x0fff);
 86                 printk(KERN_DEBUG "FMS: 0x%x\n", val & 0x0f);
 87                 val = inl(TRID_REG(trident, CH_DX_ESO_DELTA));
 88                 printk(KERN_DEBUG "ESO: 0x%x\n", val >> 16);
 89                 printk(KERN_DEBUG "Delta: 0x%x\n", val & 0xffff);
 90                 val = inl(TRID_REG(trident, CH_DX_FMC_RVOL_CVOL));
 91         } else {                // TRIDENT_DEVICE_ID_NX
 92                 val = inl(TRID_REG(trident, CH_NX_DELTA_CSO));
 93                 tmp = (val >> 24) & 0xff;
 94                 printk(KERN_DEBUG "CSO: 0x%x\n", val & 0x00ffffff);
 95                 val = inl(TRID_REG(trident, CH_NX_DELTA_ESO));
 96                 tmp |= (val >> 16) & 0xff00;
 97                 printk(KERN_DEBUG "Delta: 0x%x\n", tmp);
 98                 printk(KERN_DEBUG "ESO: 0x%x\n", val & 0x00ffffff);
 99                 val = inl(TRID_REG(trident, CH_NX_ALPHA_FMS_FMC_RVOL_CVOL));
100                 printk(KERN_DEBUG "Alpha: 0x%x\n", val >> 20);
101                 printk(KERN_DEBUG "FMS: 0x%x\n", (val >> 16) & 0x0f);
102         }
103         printk(KERN_DEBUG "FMC: 0x%x\n", (val >> 14) & 3);
104         printk(KERN_DEBUG "RVol: 0x%x\n", (val >> 7) & 0x7f);
105         printk(KERN_DEBUG "CVol: 0x%x\n", val & 0x7f);
106 }
107 #endif
108 
109 /*---------------------------------------------------------------------------
110    unsigned short snd_trident_codec_read(struct snd_ac97 *ac97, unsigned short reg)
111   
112    Description: This routine will do all of the reading from the external
113                 CODEC (AC97).
114   
115    Parameters:  ac97 - ac97 codec structure
116                 reg - CODEC register index, from AC97 Hal.
117  
118    returns:     16 bit value read from the AC97.
119   
120   ---------------------------------------------------------------------------*/
121 static unsigned short snd_trident_codec_read(struct snd_ac97 *ac97, unsigned short reg)
122 {
123         unsigned int data = 0, treg;
124         unsigned short count = 0xffff;
125         unsigned long flags;
126         struct snd_trident *trident = ac97->private_data;
127 
128         spin_lock_irqsave(&trident->reg_lock, flags);
129         if (trident->device == TRIDENT_DEVICE_ID_DX) {
130                 data = (DX_AC97_BUSY_READ | (reg & 0x000000ff));
131                 outl(data, TRID_REG(trident, DX_ACR1_AC97_R));
132                 do {
133                         data = inl(TRID_REG(trident, DX_ACR1_AC97_R));
134                         if ((data & DX_AC97_BUSY_READ) == 0)
135                                 break;
136                 } while (--count);
137         } else if (trident->device == TRIDENT_DEVICE_ID_NX) {
138                 data = (NX_AC97_BUSY_READ | (reg & 0x000000ff));
139                 treg = ac97->num == 0 ? NX_ACR2_AC97_R_PRIMARY : NX_ACR3_AC97_R_SECONDARY;
140                 outl(data, TRID_REG(trident, treg));
141                 do {
142                         data = inl(TRID_REG(trident, treg));
143                         if ((data & 0x00000C00) == 0)
144                                 break;
145                 } while (--count);
146         } else if (trident->device == TRIDENT_DEVICE_ID_SI7018) {
147                 data = SI_AC97_BUSY_READ | SI_AC97_AUDIO_BUSY | (reg & 0x000000ff);
148                 if (ac97->num == 1)
149                         data |= SI_AC97_SECONDARY;
150                 outl(data, TRID_REG(trident, SI_AC97_READ));
151                 do {
152                         data = inl(TRID_REG(trident, SI_AC97_READ));
153                         if ((data & (SI_AC97_BUSY_READ)) == 0)
154                                 break;
155                 } while (--count);
156         }
157 
158         if (count == 0 && !trident->ac97_detect) {
159                 snd_printk(KERN_ERR "ac97 codec read TIMEOUT [0x%x/0x%x]!!!\n",
160                            reg, data);
161                 data = 0;
162         }
163 
164         spin_unlock_irqrestore(&trident->reg_lock, flags);
165         return ((unsigned short) (data >> 16));
166 }
167 
168 /*---------------------------------------------------------------------------
169    void snd_trident_codec_write(struct snd_ac97 *ac97, unsigned short reg,
170    unsigned short wdata)
171   
172    Description: This routine will do all of the writing to the external
173                 CODEC (AC97).
174   
175    Parameters:  ac97 - ac97 codec structure
176                 reg - CODEC register index, from AC97 Hal.
177                 data  - Lower 16 bits are the data to write to CODEC.
178   
179    returns:     TRUE if everything went ok, else FALSE.
180   
181   ---------------------------------------------------------------------------*/
182 static void snd_trident_codec_write(struct snd_ac97 *ac97, unsigned short reg,
183                                     unsigned short wdata)
184 {
185         unsigned int address, data;
186         unsigned short count = 0xffff;
187         unsigned long flags;
188         struct snd_trident *trident = ac97->private_data;
189 
190         data = ((unsigned long) wdata) << 16;
191 
192         spin_lock_irqsave(&trident->reg_lock, flags);
193         if (trident->device == TRIDENT_DEVICE_ID_DX) {
194                 address = DX_ACR0_AC97_W;
195 
196                 /* read AC-97 write register status */
197                 do {
198                         if ((inw(TRID_REG(trident, address)) & DX_AC97_BUSY_WRITE) == 0)
199                                 break;
200                 } while (--count);
201 
202                 data |= (DX_AC97_BUSY_WRITE | (reg & 0x000000ff));
203         } else if (trident->device == TRIDENT_DEVICE_ID_NX) {
204                 address = NX_ACR1_AC97_W;
205 
206                 /* read AC-97 write register status */
207                 do {
208                         if ((inw(TRID_REG(trident, address)) & NX_AC97_BUSY_WRITE) == 0)
209                                 break;
210                 } while (--count);
211 
212                 data |= (NX_AC97_BUSY_WRITE | (ac97->num << 8) | (reg & 0x000000ff));
213         } else if (trident->device == TRIDENT_DEVICE_ID_SI7018) {
214                 address = SI_AC97_WRITE;
215 
216                 /* read AC-97 write register status */
217                 do {
218                         if ((inw(TRID_REG(trident, address)) & (SI_AC97_BUSY_WRITE)) == 0)
219                                 break;
220                 } while (--count);
221 
222                 data |= SI_AC97_BUSY_WRITE | SI_AC97_AUDIO_BUSY | (reg & 0x000000ff);
223                 if (ac97->num == 1)
224                         data |= SI_AC97_SECONDARY;
225         } else {
226                 address = 0;    /* keep GCC happy */
227                 count = 0;      /* return */
228         }
229 
230         if (count == 0) {
231                 spin_unlock_irqrestore(&trident->reg_lock, flags);
232                 return;
233         }
234         outl(data, TRID_REG(trident, address));
235         spin_unlock_irqrestore(&trident->reg_lock, flags);
236 }
237 
238 /*---------------------------------------------------------------------------
239    void snd_trident_enable_eso(struct snd_trident *trident)
240   
241    Description: This routine will enable end of loop interrupts.
242                 End of loop interrupts will occur when a running
243                 channel reaches ESO.
244                 Also enables middle of loop interrupts.
245   
246    Parameters:  trident - pointer to target device class for 4DWave.
247   
248   ---------------------------------------------------------------------------*/
249 
250 static void snd_trident_enable_eso(struct snd_trident * trident)
251 {
252         unsigned int val;
253 
254         val = inl(TRID_REG(trident, T4D_LFO_GC_CIR));
255         val |= ENDLP_IE;
256         val |= MIDLP_IE;
257         if (trident->device == TRIDENT_DEVICE_ID_SI7018)
258                 val |= BANK_B_EN;
259         outl(val, TRID_REG(trident, T4D_LFO_GC_CIR));
260 }
261 
262 /*---------------------------------------------------------------------------
263    void snd_trident_disable_eso(struct snd_trident *trident)
264   
265    Description: This routine will disable end of loop interrupts.
266                 End of loop interrupts will occur when a running
267                 channel reaches ESO.
268                 Also disables middle of loop interrupts.
269   
270    Parameters:  
271                 trident - pointer to target device class for 4DWave.
272   
273    returns:     TRUE if everything went ok, else FALSE.
274   
275   ---------------------------------------------------------------------------*/
276 
277 static void snd_trident_disable_eso(struct snd_trident * trident)
278 {
279         unsigned int tmp;
280 
281         tmp = inl(TRID_REG(trident, T4D_LFO_GC_CIR));
282         tmp &= ~ENDLP_IE;
283         tmp &= ~MIDLP_IE;
284         outl(tmp, TRID_REG(trident, T4D_LFO_GC_CIR));
285 }
286 
287 /*---------------------------------------------------------------------------
288    void snd_trident_start_voice(struct snd_trident * trident, unsigned int voice)
289 
290     Description: Start a voice, any channel 0 thru 63.
291                  This routine automatically handles the fact that there are
292                  more than 32 channels available.
293 
294     Parameters : voice - Voice number 0 thru n.
295                  trident - pointer to target device class for 4DWave.
296 
297     Return Value: None.
298 
299   ---------------------------------------------------------------------------*/
300 
301 void snd_trident_start_voice(struct snd_trident * trident, unsigned int voice)
302 {
303         unsigned int mask = 1 << (voice & 0x1f);
304         unsigned int reg = (voice & 0x20) ? T4D_START_B : T4D_START_A;
305 
306         outl(mask, TRID_REG(trident, reg));
307 }
308 
309 EXPORT_SYMBOL(snd_trident_start_voice);
310 
311 /*---------------------------------------------------------------------------
312    void snd_trident_stop_voice(struct snd_trident * trident, unsigned int voice)
313 
314     Description: Stop a voice, any channel 0 thru 63.
315                  This routine automatically handles the fact that there are
316                  more than 32 channels available.
317 
318     Parameters : voice - Voice number 0 thru n.
319                  trident - pointer to target device class for 4DWave.
320 
321     Return Value: None.
322 
323   ---------------------------------------------------------------------------*/
324 
325 void snd_trident_stop_voice(struct snd_trident * trident, unsigned int voice)
326 {
327         unsigned int mask = 1 << (voice & 0x1f);
328         unsigned int reg = (voice & 0x20) ? T4D_STOP_B : T4D_STOP_A;
329 
330         outl(mask, TRID_REG(trident, reg));
331 }
332 
333 EXPORT_SYMBOL(snd_trident_stop_voice);
334 
335 /*---------------------------------------------------------------------------
336     int snd_trident_allocate_pcm_channel(struct snd_trident *trident)
337   
338     Description: Allocate hardware channel in Bank B (32-63).
339   
340     Parameters :  trident - pointer to target device class for 4DWave.
341   
342     Return Value: hardware channel - 32-63 or -1 when no channel is available
343   
344   ---------------------------------------------------------------------------*/
345 
346 static int snd_trident_allocate_pcm_channel(struct snd_trident * trident)
347 {
348         int idx;
349 
350         if (trident->ChanPCMcnt >= trident->ChanPCM)
351                 return -1;
352         for (idx = 31; idx >= 0; idx--) {
353                 if (!(trident->ChanMap[T4D_BANK_B] & (1 << idx))) {
354                         trident->ChanMap[T4D_BANK_B] |= 1 << idx;
355                         trident->ChanPCMcnt++;
356                         return idx + 32;
357                 }
358         }
359         return -1;
360 }
361 
362 /*---------------------------------------------------------------------------
363     void snd_trident_free_pcm_channel(int channel)
364   
365     Description: Free hardware channel in Bank B (32-63)
366   
367     Parameters :  trident - pointer to target device class for 4DWave.
368                   channel - hardware channel number 0-63
369   
370     Return Value: none
371   
372   ---------------------------------------------------------------------------*/
373 
374 static void snd_trident_free_pcm_channel(struct snd_trident *trident, int channel)
375 {
376         if (channel < 32 || channel > 63)
377                 return;
378         channel &= 0x1f;
379         if (trident->ChanMap[T4D_BANK_B] & (1 << channel)) {
380                 trident->ChanMap[T4D_BANK_B] &= ~(1 << channel);
381                 trident->ChanPCMcnt--;
382         }
383 }
384 
385 /*---------------------------------------------------------------------------
386     unsigned int snd_trident_allocate_synth_channel(void)
387   
388     Description: Allocate hardware channel in Bank A (0-31).
389   
390     Parameters :  trident - pointer to target device class for 4DWave.
391   
392     Return Value: hardware channel - 0-31 or -1 when no channel is available
393   
394   ---------------------------------------------------------------------------*/
395 
396 static int snd_trident_allocate_synth_channel(struct snd_trident * trident)
397 {
398         int idx;
399 
400         for (idx = 31; idx >= 0; idx--) {
401                 if (!(trident->ChanMap[T4D_BANK_A] & (1 << idx))) {
402                         trident->ChanMap[T4D_BANK_A] |= 1 << idx;
403                         trident->synth.ChanSynthCount++;
404                         return idx;
405                 }
406         }
407         return -1;
408 }
409 
410 /*---------------------------------------------------------------------------
411     void snd_trident_free_synth_channel( int channel )
412   
413     Description: Free hardware channel in Bank B (0-31).
414   
415     Parameters :  trident - pointer to target device class for 4DWave.
416                   channel - hardware channel number 0-63
417   
418     Return Value: none
419   
420   ---------------------------------------------------------------------------*/
421 
422 static void snd_trident_free_synth_channel(struct snd_trident *trident, int channel)
423 {
424         if (channel < 0 || channel > 31)
425                 return;
426         channel &= 0x1f;
427         if (trident->ChanMap[T4D_BANK_A] & (1 << channel)) {
428                 trident->ChanMap[T4D_BANK_A] &= ~(1 << channel);
429                 trident->synth.ChanSynthCount--;
430         }
431 }
432 
433 /*---------------------------------------------------------------------------
434    snd_trident_write_voice_regs
435   
436    Description: This routine will complete and write the 5 hardware channel
437                 registers to hardware.
438   
439    Parameters:  trident - pointer to target device class for 4DWave.
440                 voice - synthesizer voice structure
441                 Each register field.
442   
443   ---------------------------------------------------------------------------*/
444 
445 void snd_trident_write_voice_regs(struct snd_trident * trident,
446                                   struct snd_trident_voice * voice)
447 {
448         unsigned int FmcRvolCvol;
449         unsigned int regs[5];
450 
451         regs[1] = voice->LBA;
452         regs[4] = (voice->GVSel << 31) |
453                   ((voice->Pan & 0x0000007f) << 24) |
454                   ((voice->CTRL & 0x0000000f) << 12);
455         FmcRvolCvol = ((voice->FMC & 3) << 14) |
456                       ((voice->RVol & 0x7f) << 7) |
457                       (voice->CVol & 0x7f);
458 
459         switch (trident->device) {
460         case TRIDENT_DEVICE_ID_SI7018:
461                 regs[4] |= voice->number > 31 ?
462                                 (voice->Vol & 0x000003ff) :
463                                 ((voice->Vol & 0x00003fc) << (16-2)) |
464                                 (voice->EC & 0x00000fff);
465                 regs[0] = (voice->CSO << 16) | ((voice->Alpha & 0x00000fff) << 4) |
466                         (voice->FMS & 0x0000000f);
467                 regs[2] = (voice->ESO << 16) | (voice->Delta & 0x0ffff);
468                 regs[3] = (voice->Attribute << 16) | FmcRvolCvol;
469                 break;
470         case TRIDENT_DEVICE_ID_DX:
471                 regs[4] |= ((voice->Vol & 0x000003fc) << (16-2)) |
472                            (voice->EC & 0x00000fff);
473                 regs[0] = (voice->CSO << 16) | ((voice->Alpha & 0x00000fff) << 4) |
474                         (voice->FMS & 0x0000000f);
475                 regs[2] = (voice->ESO << 16) | (voice->Delta & 0x0ffff);
476                 regs[3] = FmcRvolCvol;
477                 break;
478         case TRIDENT_DEVICE_ID_NX:
479                 regs[4] |= ((voice->Vol & 0x000003fc) << (16-2)) |
480                            (voice->EC & 0x00000fff);
481                 regs[0] = (voice->Delta << 24) | (voice->CSO & 0x00ffffff);
482                 regs[2] = ((voice->Delta << 16) & 0xff000000) |
483                         (voice->ESO & 0x00ffffff);
484                 regs[3] = (voice->Alpha << 20) |
485                         ((voice->FMS & 0x0000000f) << 16) | FmcRvolCvol;
486                 break;
487         default:
488                 snd_BUG();
489                 return;
490         }
491 
492         outb(voice->number, TRID_REG(trident, T4D_LFO_GC_CIR));
493         outl(regs[0], TRID_REG(trident, CH_START + 0));
494         outl(regs[1], TRID_REG(trident, CH_START + 4));
495         outl(regs[2], TRID_REG(trident, CH_START + 8));
496         outl(regs[3], TRID_REG(trident, CH_START + 12));
497         outl(regs[4], TRID_REG(trident, CH_START + 16));
498 
499 #if 0
500         printk(KERN_DEBUG "written %i channel:\n", voice->number);
501         printk(KERN_DEBUG "  regs[0] = 0x%x/0x%x\n",
502                regs[0], inl(TRID_REG(trident, CH_START + 0)));
503         printk(KERN_DEBUG "  regs[1] = 0x%x/0x%x\n",
504                regs[1], inl(TRID_REG(trident, CH_START + 4)));
505         printk(KERN_DEBUG "  regs[2] = 0x%x/0x%x\n",
506                regs[2], inl(TRID_REG(trident, CH_START + 8)));
507         printk(KERN_DEBUG "  regs[3] = 0x%x/0x%x\n",
508                regs[3], inl(TRID_REG(trident, CH_START + 12)));
509         printk(KERN_DEBUG "  regs[4] = 0x%x/0x%x\n",
510                regs[4], inl(TRID_REG(trident, CH_START + 16)));
511 #endif
512 }
513 
514 EXPORT_SYMBOL(snd_trident_write_voice_regs);
515 
516 /*---------------------------------------------------------------------------
517    snd_trident_write_cso_reg
518   
519    Description: This routine will write the new CSO offset
520                 register to hardware.
521   
522    Parameters:  trident - pointer to target device class for 4DWave.
523                 voice - synthesizer voice structure
524                 CSO - new CSO value
525   
526   ---------------------------------------------------------------------------*/
527 
528 static void snd_trident_write_cso_reg(struct snd_trident * trident,
529                                       struct snd_trident_voice * voice,
530                                       unsigned int CSO)
531 {
532         voice->CSO = CSO;
533         outb(voice->number, TRID_REG(trident, T4D_LFO_GC_CIR));
534         if (trident->device != TRIDENT_DEVICE_ID_NX) {
535                 outw(voice->CSO, TRID_REG(trident, CH_DX_CSO_ALPHA_FMS) + 2);
536         } else {
537                 outl((voice->Delta << 24) |
538                      (voice->CSO & 0x00ffffff), TRID_REG(trident, CH_NX_DELTA_CSO));
539         }
540 }
541 
542 /*---------------------------------------------------------------------------
543    snd_trident_write_eso_reg
544   
545    Description: This routine will write the new ESO offset
546                 register to hardware.
547   
548    Parameters:  trident - pointer to target device class for 4DWave.
549                 voice - synthesizer voice structure
550                 ESO - new ESO value
551   
552   ---------------------------------------------------------------------------*/
553 
554 static void snd_trident_write_eso_reg(struct snd_trident * trident,
555                                       struct snd_trident_voice * voice,
556                                       unsigned int ESO)
557 {
558         voice->ESO = ESO;
559         outb(voice->number, TRID_REG(trident, T4D_LFO_GC_CIR));
560         if (trident->device != TRIDENT_DEVICE_ID_NX) {
561                 outw(voice->ESO, TRID_REG(trident, CH_DX_ESO_DELTA) + 2);
562         } else {
563                 outl(((voice->Delta << 16) & 0xff000000) | (voice->ESO & 0x00ffffff),
564                      TRID_REG(trident, CH_NX_DELTA_ESO));
565         }
566 }
567 
568 /*---------------------------------------------------------------------------
569    snd_trident_write_vol_reg
570   
571    Description: This routine will write the new voice volume
572                 register to hardware.
573   
574    Parameters:  trident - pointer to target device class for 4DWave.
575                 voice - synthesizer voice structure
576                 Vol - new voice volume
577   
578   ---------------------------------------------------------------------------*/
579 
580 static void snd_trident_write_vol_reg(struct snd_trident * trident,
581                                       struct snd_trident_voice * voice,
582                                       unsigned int Vol)
583 {
584         voice->Vol = Vol;
585         outb(voice->number, TRID_REG(trident, T4D_LFO_GC_CIR));
586         switch (trident->device) {
587         case TRIDENT_DEVICE_ID_DX:
588         case TRIDENT_DEVICE_ID_NX:
589                 outb(voice->Vol >> 2, TRID_REG(trident, CH_GVSEL_PAN_VOL_CTRL_EC + 2));
590                 break;
591         case TRIDENT_DEVICE_ID_SI7018:
592                 /* printk(KERN_DEBUG "voice->Vol = 0x%x\n", voice->Vol); */
593                 outw((voice->CTRL << 12) | voice->Vol,
594                      TRID_REG(trident, CH_GVSEL_PAN_VOL_CTRL_EC));
595                 break;
596         }
597 }
598 
599 /*---------------------------------------------------------------------------
600    snd_trident_write_pan_reg
601   
602    Description: This routine will write the new voice pan
603                 register to hardware.
604   
605    Parameters:  trident - pointer to target device class for 4DWave.
606                 voice - synthesizer voice structure
607                 Pan - new pan value
608   
609   ---------------------------------------------------------------------------*/
610 
611 static void snd_trident_write_pan_reg(struct snd_trident * trident,
612                                       struct snd_trident_voice * voice,
613                                       unsigned int Pan)
614 {
615         voice->Pan = Pan;
616         outb(voice->number, TRID_REG(trident, T4D_LFO_GC_CIR));
617         outb(((voice->GVSel & 0x01) << 7) | (voice->Pan & 0x7f),
618              TRID_REG(trident, CH_GVSEL_PAN_VOL_CTRL_EC + 3));
619 }
620 
621 /*---------------------------------------------------------------------------
622    snd_trident_write_rvol_reg
623   
624    Description: This routine will write the new reverb volume
625                 register to hardware.
626   
627    Parameters:  trident - pointer to target device class for 4DWave.
628                 voice - synthesizer voice structure
629                 RVol - new reverb volume
630   
631   ---------------------------------------------------------------------------*/
632 
633 static void snd_trident_write_rvol_reg(struct snd_trident * trident,
634                                        struct snd_trident_voice * voice,
635                                        unsigned int RVol)
636 {
637         voice->RVol = RVol;
638         outb(voice->number, TRID_REG(trident, T4D_LFO_GC_CIR));
639         outw(((voice->FMC & 0x0003) << 14) | ((voice->RVol & 0x007f) << 7) |
640              (voice->CVol & 0x007f),
641              TRID_REG(trident, trident->device == TRIDENT_DEVICE_ID_NX ?
642                       CH_NX_ALPHA_FMS_FMC_RVOL_CVOL : CH_DX_FMC_RVOL_CVOL));
643 }
644 
645 /*---------------------------------------------------------------------------
646    snd_trident_write_cvol_reg
647   
648    Description: This routine will write the new chorus volume
649                 register to hardware.
650   
651    Parameters:  trident - pointer to target device class for 4DWave.
652                 voice - synthesizer voice structure
653                 CVol - new chorus volume
654   
655   ---------------------------------------------------------------------------*/
656 
657 static void snd_trident_write_cvol_reg(struct snd_trident * trident,
658                                        struct snd_trident_voice * voice,
659                                        unsigned int CVol)
660 {
661         voice->CVol = CVol;
662         outb(voice->number, TRID_REG(trident, T4D_LFO_GC_CIR));
663         outw(((voice->FMC & 0x0003) << 14) | ((voice->RVol & 0x007f) << 7) |
664              (voice->CVol & 0x007f),
665              TRID_REG(trident, trident->device == TRIDENT_DEVICE_ID_NX ?
666                       CH_NX_ALPHA_FMS_FMC_RVOL_CVOL : CH_DX_FMC_RVOL_CVOL));
667 }
668 
669 /*---------------------------------------------------------------------------
670    snd_trident_convert_rate
671 
672    Description: This routine converts rate in HZ to hardware delta value.
673   
674    Parameters:  trident - pointer to target device class for 4DWave.
675                 rate - Real or Virtual channel number.
676   
677    Returns:     Delta value.
678   
679   ---------------------------------------------------------------------------*/
680 static unsigned int snd_trident_convert_rate(unsigned int rate)
681 {
682         unsigned int delta;
683 
684         // We special case 44100 and 8000 since rounding with the equation
685         // does not give us an accurate enough value. For 11025 and 22050
686         // the equation gives us the best answer. All other frequencies will
687         // also use the equation. JDW
688         if (rate == 44100)
689                 delta = 0xeb3;
690         else if (rate == 8000)
691                 delta = 0x2ab;
692         else if (rate == 48000)
693                 delta = 0x1000;
694         else
695                 delta = (((rate << 12) + 24000) / 48000) & 0x0000ffff;
696         return delta;
697 }
698 
699 /*---------------------------------------------------------------------------
700    snd_trident_convert_adc_rate
701 
702    Description: This routine converts rate in HZ to hardware delta value.
703   
704    Parameters:  trident - pointer to target device class for 4DWave.
705                 rate - Real or Virtual channel number.
706   
707    Returns:     Delta value.
708   
709   ---------------------------------------------------------------------------*/
710 static unsigned int snd_trident_convert_adc_rate(unsigned int rate)
711 {
712         unsigned int delta;
713 
714         // We special case 44100 and 8000 since rounding with the equation
715         // does not give us an accurate enough value. For 11025 and 22050
716         // the equation gives us the best answer. All other frequencies will
717         // also use the equation. JDW
718         if (rate == 44100)
719                 delta = 0x116a;
720         else if (rate == 8000)
721                 delta = 0x6000;
722         else if (rate == 48000)
723                 delta = 0x1000;
724         else
725                 delta = ((48000 << 12) / rate) & 0x0000ffff;
726         return delta;
727 }
728 
729 /*---------------------------------------------------------------------------
730    snd_trident_spurious_threshold
731 
732    Description: This routine converts rate in HZ to spurious threshold.
733   
734    Parameters:  trident - pointer to target device class for 4DWave.
735                 rate - Real or Virtual channel number.
736   
737    Returns:     Delta value.
738   
739   ---------------------------------------------------------------------------*/
740 static unsigned int snd_trident_spurious_threshold(unsigned int rate,
741                                                    unsigned int period_size)
742 {
743         unsigned int res = (rate * period_size) / 48000;
744         if (res < 64)
745                 res = res / 2;
746         else
747                 res -= 32;
748         return res;
749 }
750 
751 /*---------------------------------------------------------------------------
752    snd_trident_control_mode
753 
754    Description: This routine returns a control mode for a PCM channel.
755   
756    Parameters:  trident - pointer to target device class for 4DWave.
757                 substream  - PCM substream
758   
759    Returns:     Control value.
760   
761   ---------------------------------------------------------------------------*/
762 static unsigned int snd_trident_control_mode(struct snd_pcm_substream *substream)
763 {
764         unsigned int CTRL;
765         struct snd_pcm_runtime *runtime = substream->runtime;
766 
767         /* set ctrl mode
768            CTRL default: 8-bit (unsigned) mono, loop mode enabled
769          */
770         CTRL = 0x00000001;
771         if (snd_pcm_format_width(runtime->format) == 16)
772                 CTRL |= 0x00000008;     // 16-bit data
773         if (snd_pcm_format_signed(runtime->format))
774                 CTRL |= 0x00000002;     // signed data
775         if (runtime->channels > 1)
776                 CTRL |= 0x00000004;     // stereo data
777         return CTRL;
778 }
779 
780 /*
781  *  PCM part
782  */
783 
784 /*---------------------------------------------------------------------------
785    snd_trident_ioctl
786   
787    Description: Device I/O control handler for playback/capture parameters.
788   
789    Parameters:   substream  - PCM substream class
790                 cmd     - what ioctl message to process
791                 arg     - additional message infoarg     
792   
793    Returns:     Error status
794   
795   ---------------------------------------------------------------------------*/
796 
797 static int snd_trident_ioctl(struct snd_pcm_substream *substream,
798                              unsigned int cmd,
799                              void *arg)
800 {
801         /* FIXME: it seems that with small periods the behaviour of
802                   trident hardware is unpredictable and interrupt generator
803                   is broken */
804         return snd_pcm_lib_ioctl(substream, cmd, arg);
805 }
806 
807 /*---------------------------------------------------------------------------
808    snd_trident_allocate_pcm_mem
809   
810    Description: Allocate PCM ring buffer for given substream
811   
812    Parameters:  substream  - PCM substream class
813                 hw_params  - hardware parameters
814   
815    Returns:     Error status
816   
817   ---------------------------------------------------------------------------*/
818 
819 static int snd_trident_allocate_pcm_mem(struct snd_pcm_substream *substream,
820                                         struct snd_pcm_hw_params *hw_params)
821 {
822         struct snd_trident *trident = snd_pcm_substream_chip(substream);
823         struct snd_pcm_runtime *runtime = substream->runtime;
824         struct snd_trident_voice *voice = runtime->private_data;
825         int err;
826 
827         if ((err = snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(hw_params))) < 0)
828                 return err;
829         if (trident->tlb.entries) {
830                 if (err > 0) { /* change */
831                         if (voice->memblk)
832                                 snd_trident_free_pages(trident, voice->memblk);
833                         voice->memblk = snd_trident_alloc_pages(trident, substream);
834                         if (voice->memblk == NULL)
835                                 return -ENOMEM;
836                 }
837         }
838         return 0;
839 }
840 
841 /*---------------------------------------------------------------------------
842    snd_trident_allocate_evoice
843   
844    Description: Allocate extra voice as interrupt generator
845   
846    Parameters:  substream  - PCM substream class
847                 hw_params  - hardware parameters
848   
849    Returns:     Error status
850   
851   ---------------------------------------------------------------------------*/
852 
853 static int snd_trident_allocate_evoice(struct snd_pcm_substream *substream,
854                                        struct snd_pcm_hw_params *hw_params)
855 {
856         struct snd_trident *trident = snd_pcm_substream_chip(substream);
857         struct snd_pcm_runtime *runtime = substream->runtime;
858         struct snd_trident_voice *voice = runtime->private_data;
859         struct snd_trident_voice *evoice = voice->extra;
860 
861         /* voice management */
862 
863         if (params_buffer_size(hw_params) / 2 != params_period_size(hw_params)) {
864                 if (evoice == NULL) {
865                         evoice = snd_trident_alloc_voice(trident, SNDRV_TRIDENT_VOICE_TYPE_PCM, 0, 0);
866                         if (evoice == NULL)
867                                 return -ENOMEM;
868                         voice->extra = evoice;
869                         evoice->substream = substream;
870                 }
871         } else {
872                 if (evoice != NULL) {
873                         snd_trident_free_voice(trident, evoice);
874                         voice->extra = evoice = NULL;
875                 }
876         }
877 
878         return 0;
879 }
880 
881 /*---------------------------------------------------------------------------
882    snd_trident_hw_params
883   
884    Description: Set the hardware parameters for the playback device.
885   
886    Parameters:  substream  - PCM substream class
887                 hw_params  - hardware parameters
888   
889    Returns:     Error status
890   
891   ---------------------------------------------------------------------------*/
892 
893 static int snd_trident_hw_params(struct snd_pcm_substream *substream,
894                                  struct snd_pcm_hw_params *hw_params)
895 {
896         int err;
897 
898         err = snd_trident_allocate_pcm_mem(substream, hw_params);
899         if (err >= 0)
900                 err = snd_trident_allocate_evoice(substream, hw_params);
901         return err;
902 }
903 
904 /*---------------------------------------------------------------------------
905    snd_trident_playback_hw_free
906   
907    Description: Release the hardware resources for the playback device.
908   
909    Parameters:  substream  - PCM substream class
910   
911    Returns:     Error status
912   
913   ---------------------------------------------------------------------------*/
914 
915 static int snd_trident_hw_free(struct snd_pcm_substream *substream)
916 {
917         struct snd_trident *trident = snd_pcm_substream_chip(substream);
918         struct snd_pcm_runtime *runtime = substream->runtime;
919         struct snd_trident_voice *voice = runtime->private_data;
920         struct snd_trident_voice *evoice = voice ? voice->extra : NULL;
921 
922         if (trident->tlb.entries) {
923                 if (voice && voice->memblk) {
924                         snd_trident_free_pages(trident, voice->memblk);
925                         voice->memblk = NULL;
926                 }
927         }
928         snd_pcm_lib_free_pages(substream);
929         if (evoice != NULL) {
930                 snd_trident_free_voice(trident, evoice);
931                 voice->extra = NULL;
932         }
933         return 0;
934 }
935 
936 /*---------------------------------------------------------------------------
937    snd_trident_playback_prepare
938   
939    Description: Prepare playback device for playback.
940   
941    Parameters:  substream  - PCM substream class
942   
943    Returns:     Error status
944   
945   ---------------------------------------------------------------------------*/
946 
947 static int snd_trident_playback_prepare(struct snd_pcm_substream *substream)
948 {
949         struct snd_trident *trident = snd_pcm_substream_chip(substream);
950         struct snd_pcm_runtime *runtime = substream->runtime;
951         struct snd_trident_voice *voice = runtime->private_data;
952         struct snd_trident_voice *evoice = voice->extra;
953         struct snd_trident_pcm_mixer *mix = &trident->pcm_mixer[substream->number];
954 
955         spin_lock_irq(&trident->reg_lock);      
956 
957         /* set delta (rate) value */
958         voice->Delta = snd_trident_convert_rate(runtime->rate);
959         voice->spurious_threshold = snd_trident_spurious_threshold(runtime->rate, runtime->period_size);
960 
961         /* set Loop Begin Address */
962         if (voice->memblk)
963                 voice->LBA = voice->memblk->offset;
964         else
965                 voice->LBA = runtime->dma_addr;
966  
967         voice->CSO = 0;
968         voice->ESO = runtime->buffer_size - 1;  /* in samples */
969         voice->CTRL = snd_trident_control_mode(substream);
970         voice->FMC = 3;
971         voice->GVSel = 1;
972         voice->EC = 0;
973         voice->Alpha = 0;
974         voice->FMS = 0;
975         voice->Vol = mix->vol;
976         voice->RVol = mix->rvol;
977         voice->CVol = mix->cvol;
978         voice->Pan = mix->pan;
979         voice->Attribute = 0;
980 #if 0
981         voice->Attribute = (1<<(30-16))|(2<<(26-16))|
982                            (0<<(24-16))|(0x1f<<(19-16));
983 #else
984         voice->Attribute = 0;
985 #endif
986 
987         snd_trident_write_voice_regs(trident, voice);
988 
989         if (evoice != NULL) {
990                 evoice->Delta = voice->Delta;
991                 evoice->spurious_threshold = voice->spurious_threshold;
992                 evoice->LBA = voice->LBA;
993                 evoice->CSO = 0;
994                 evoice->ESO = (runtime->period_size * 2) + 4 - 1; /* in samples */
995                 evoice->CTRL = voice->CTRL;
996                 evoice->FMC = 3;
997                 evoice->GVSel = trident->device == TRIDENT_DEVICE_ID_SI7018 ? 0 : 1;
998                 evoice->EC = 0;
999                 evoice->Alpha = 0;
1000                 evoice->FMS = 0;
1001                 evoice->Vol = 0x3ff;                    /* mute */
1002                 evoice->RVol = evoice->CVol = 0x7f;     /* mute */
1003                 evoice->Pan = 0x7f;                     /* mute */
1004 #if 0
1005                 evoice->Attribute = (1<<(30-16))|(2<<(26-16))|
1006                                     (0<<(24-16))|(0x1f<<(19-16));
1007 #else
1008                 evoice->Attribute = 0;
1009 #endif
1010                 snd_trident_write_voice_regs(trident, evoice);
1011                 evoice->isync2 = 1;
1012                 evoice->isync_mark = runtime->period_size;
1013                 evoice->ESO = (runtime->period_size * 2) - 1;
1014         }
1015 
1016         spin_unlock_irq(&trident->reg_lock);
1017 
1018         return 0;
1019 }
1020 
1021 /*---------------------------------------------------------------------------
1022    snd_trident_capture_hw_params
1023   
1024    Description: Set the hardware parameters for the capture device.
1025   
1026    Parameters:  substream  - PCM substream class
1027                 hw_params  - hardware parameters
1028   
1029    Returns:     Error status
1030   
1031   ---------------------------------------------------------------------------*/
1032 
1033 static int snd_trident_capture_hw_params(struct snd_pcm_substream *substream,
1034                                          struct snd_pcm_hw_params *hw_params)
1035 {
1036         return snd_trident_allocate_pcm_mem(substream, hw_params);
1037 }
1038 
1039 /*---------------------------------------------------------------------------
1040    snd_trident_capture_prepare
1041   
1042    Description: Prepare capture device for playback.
1043   
1044    Parameters:  substream  - PCM substream class
1045   
1046    Returns:     Error status
1047   
1048   ---------------------------------------------------------------------------*/
1049 
1050 static int snd_trident_capture_prepare(struct snd_pcm_substream *substream)
1051 {
1052         struct snd_trident *trident = snd_pcm_substream_chip(substream);
1053         struct snd_pcm_runtime *runtime = substream->runtime;
1054         struct snd_trident_voice *voice = runtime->private_data;
1055         unsigned int val, ESO_bytes;
1056 
1057         spin_lock_irq(&trident->reg_lock);
1058 
1059         // Initialize the channel and set channel Mode
1060         outb(0, TRID_REG(trident, LEGACY_DMAR15));
1061 
1062         // Set DMA channel operation mode register
1063         outb(0x54, TRID_REG(trident, LEGACY_DMAR11));
1064 
1065         // Set channel buffer Address, DMAR0 expects contiguous PCI memory area 
1066         voice->LBA = runtime->dma_addr;
1067         outl(voice->LBA, TRID_REG(trident, LEGACY_DMAR0));
1068         if (voice->memblk)
1069                 voice->LBA = voice->memblk->offset;
1070 
1071         // set ESO
1072         ESO_bytes = snd_pcm_lib_buffer_bytes(substream) - 1;
1073         outb((ESO_bytes & 0x00ff0000) >> 16, TRID_REG(trident, LEGACY_DMAR6));
1074         outw((ESO_bytes & 0x0000ffff), TRID_REG(trident, LEGACY_DMAR4));
1075         ESO_bytes++;
1076 
1077         // Set channel sample rate, 4.12 format
1078         val = (((unsigned int) 48000L << 12) + (runtime->rate/2)) / runtime->rate;
1079         outw(val, TRID_REG(trident, T4D_SBDELTA_DELTA_R));
1080 
1081         // Set channel interrupt blk length
1082         if (snd_pcm_format_width(runtime->format) == 16) {
1083                 val = (unsigned short) ((ESO_bytes >> 1) - 1);
1084         } else {
1085                 val = (unsigned short) (ESO_bytes - 1);
1086         }
1087 
1088         outl((val << 16) | val, TRID_REG(trident, T4D_SBBL_SBCL));
1089 
1090         // Right now, set format and start to run captureing, 
1091         // continuous run loop enable.
1092         trident->bDMAStart = 0x19;      // 0001 1001b
1093 
1094         if (snd_pcm_format_width(runtime->format) == 16)
1095                 trident->bDMAStart |= 0x80;
1096         if (snd_pcm_format_signed(runtime->format))
1097                 trident->bDMAStart |= 0x20;
1098         if (runtime->channels > 1)
1099                 trident->bDMAStart |= 0x40;
1100 
1101         // Prepare capture intr channel
1102 
1103         voice->Delta = snd_trident_convert_rate(runtime->rate);
1104         voice->spurious_threshold = snd_trident_spurious_threshold(runtime->rate, runtime->period_size);
1105         voice->isync = 1;
1106         voice->isync_mark = runtime->period_size;
1107         voice->isync_max = runtime->buffer_size;
1108 
1109         // Set voice parameters
1110         voice->CSO = 0;
1111         voice->ESO = voice->isync_ESO = (runtime->period_size * 2) + 6 - 1;
1112         voice->CTRL = snd_trident_control_mode(substream);
1113         voice->FMC = 3;
1114         voice->RVol = 0x7f;
1115         voice->CVol = 0x7f;
1116         voice->GVSel = 1;
1117         voice->Pan = 0x7f;              /* mute */
1118         voice->Vol = 0x3ff;             /* mute */
1119         voice->EC = 0;
1120         voice->Alpha = 0;
1121         voice->FMS = 0;
1122         voice->Attribute = 0;
1123 
1124         snd_trident_write_voice_regs(trident, voice);
1125 
1126         spin_unlock_irq(&trident->reg_lock);
1127         return 0;
1128 }
1129 
1130 /*---------------------------------------------------------------------------
1131    snd_trident_si7018_capture_hw_params
1132   
1133    Description: Set the hardware parameters for the capture device.
1134   
1135    Parameters:  substream  - PCM substream class
1136                 hw_params  - hardware parameters
1137   
1138    Returns:     Error status
1139   
1140   ---------------------------------------------------------------------------*/
1141 
1142 static int snd_trident_si7018_capture_hw_params(struct snd_pcm_substream *substream,
1143                                                 struct snd_pcm_hw_params *hw_params)
1144 {
1145         int err;
1146 
1147         if ((err = snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(hw_params))) < 0)
1148                 return err;
1149 
1150         return snd_trident_allocate_evoice(substream, hw_params);
1151 }
1152 
1153 /*---------------------------------------------------------------------------
1154    snd_trident_si7018_capture_hw_free
1155   
1156    Description: Release the hardware resources for the capture device.
1157   
1158    Parameters:  substream  - PCM substream class
1159   
1160    Returns:     Error status
1161   
1162   ---------------------------------------------------------------------------*/
1163 
1164 static int snd_trident_si7018_capture_hw_free(struct snd_pcm_substream *substream)
1165 {
1166         struct snd_trident *trident = snd_pcm_substream_chip(substream);
1167         struct snd_pcm_runtime *runtime = substream->runtime;
1168         struct snd_trident_voice *voice = runtime->private_data;
1169         struct snd_trident_voice *evoice = voice ? voice->extra : NULL;
1170 
1171         snd_pcm_lib_free_pages(substream);
1172         if (evoice != NULL) {
1173                 snd_trident_free_voice(trident, evoice);
1174                 voice->extra = NULL;
1175         }
1176         return 0;
1177 }
1178 
1179 /*---------------------------------------------------------------------------
1180    snd_trident_si7018_capture_prepare
1181   
1182    Description: Prepare capture device for playback.
1183   
1184    Parameters:  substream  - PCM substream class
1185   
1186    Returns:     Error status
1187   
1188   ---------------------------------------------------------------------------*/
1189 
1190 static int snd_trident_si7018_capture_prepare(struct snd_pcm_substream *substream)
1191 {
1192         struct snd_trident *trident = snd_pcm_substream_chip(substream);
1193         struct snd_pcm_runtime *runtime = substream->runtime;
1194         struct snd_trident_voice *voice = runtime->private_data;
1195         struct snd_trident_voice *evoice = voice->extra;
1196 
1197         spin_lock_irq(&trident->reg_lock);
1198 
1199         voice->LBA = runtime->dma_addr;
1200         voice->Delta = snd_trident_convert_adc_rate(runtime->rate);
1201         voice->spurious_threshold = snd_trident_spurious_threshold(runtime->rate, runtime->period_size);
1202 
1203         // Set voice parameters
1204         voice->CSO = 0;
1205         voice->ESO = runtime->buffer_size - 1;          /* in samples */
1206         voice->CTRL = snd_trident_control_mode(substream);
1207         voice->FMC = 0;
1208         voice->RVol = 0;
1209         voice->CVol = 0;
1210         voice->GVSel = 1;
1211         voice->Pan = T4D_DEFAULT_PCM_PAN;
1212         voice->Vol = 0;
1213         voice->EC = 0;
1214         voice->Alpha = 0;
1215         voice->FMS = 0;
1216 
1217         voice->Attribute = (2 << (30-16)) |
1218                            (2 << (26-16)) |
1219                            (2 << (24-16)) |
1220                            (1 << (23-16));
1221 
1222         snd_trident_write_voice_regs(trident, voice);
1223 
1224         if (evoice != NULL) {
1225                 evoice->Delta = snd_trident_convert_rate(runtime->rate);
1226                 evoice->spurious_threshold = voice->spurious_threshold;
1227                 evoice->LBA = voice->LBA;
1228                 evoice->CSO = 0;
1229                 evoice->ESO = (runtime->period_size * 2) + 20 - 1; /* in samples, 20 means correction */
1230                 evoice->CTRL = voice->CTRL;
1231                 evoice->FMC = 3;
1232                 evoice->GVSel = 0;
1233                 evoice->EC = 0;
1234                 evoice->Alpha = 0;
1235                 evoice->FMS = 0;
1236                 evoice->Vol = 0x3ff;                    /* mute */
1237                 evoice->RVol = evoice->CVol = 0x7f;     /* mute */
1238                 evoice->Pan = 0x7f;                     /* mute */
1239                 evoice->Attribute = 0;
1240                 snd_trident_write_voice_regs(trident, evoice);
1241                 evoice->isync2 = 1;
1242                 evoice->isync_mark = runtime->period_size;
1243                 evoice->ESO = (runtime->period_size * 2) - 1;
1244         }
1245         
1246         spin_unlock_irq(&trident->reg_lock);
1247         return 0;
1248 }
1249 
1250 /*---------------------------------------------------------------------------
1251    snd_trident_foldback_prepare
1252   
1253    Description: Prepare foldback capture device for playback.
1254   
1255    Parameters:  substream  - PCM substream class
1256   
1257    Returns:     Error status
1258   
1259   ---------------------------------------------------------------------------*/
1260 
1261 static int snd_trident_foldback_prepare(struct snd_pcm_substream *substream)
1262 {
1263         struct snd_trident *trident = snd_pcm_substream_chip(substream);
1264         struct snd_pcm_runtime *runtime = substream->runtime;
1265         struct snd_trident_voice *voice = runtime->private_data;
1266         struct snd_trident_voice *evoice = voice->extra;
1267 
1268         spin_lock_irq(&trident->reg_lock);
1269 
1270         /* Set channel buffer Address */
1271         if (voice->memblk)
1272                 voice->LBA = voice->memblk->offset;
1273         else
1274                 voice->LBA = runtime->dma_addr;
1275 
1276         /* set target ESO for channel */
1277         voice->ESO = runtime->buffer_size - 1;  /* in samples */
1278 
1279         /* set sample rate */
1280         voice->Delta = 0x1000;
1281         voice->spurious_threshold = snd_trident_spurious_threshold(48000, runtime->period_size);
1282 
1283         voice->CSO = 0;
1284         voice->CTRL = snd_trident_control_mode(substream);
1285         voice->FMC = 3;
1286         voice->RVol = 0x7f;
1287         voice->CVol = 0x7f;
1288         voice->GVSel = 1;
1289         voice->Pan = 0x7f;      /* mute */
1290         voice->Vol = 0x3ff;     /* mute */
1291         voice->EC = 0;
1292         voice->Alpha = 0;
1293         voice->FMS = 0;
1294         voice->Attribute = 0;
1295 
1296         /* set up capture channel */
1297         outb(((voice->number & 0x3f) | 0x80), TRID_REG(trident, T4D_RCI + voice->foldback_chan));
1298 
1299         snd_trident_write_voice_regs(trident, voice);
1300 
1301         if (evoice != NULL) {
1302                 evoice->Delta = voice->Delta;
1303                 evoice->spurious_threshold = voice->spurious_threshold;
1304                 evoice->LBA = voice->LBA;
1305                 evoice->CSO = 0;
1306                 evoice->ESO = (runtime->period_size * 2) + 4 - 1; /* in samples */
1307                 evoice->CTRL = voice->CTRL;
1308                 evoice->FMC = 3;
1309                 evoice->GVSel = trident->device == TRIDENT_DEVICE_ID_SI7018 ? 0 : 1;
1310                 evoice->EC = 0;
1311                 evoice->Alpha = 0;
1312                 evoice->FMS = 0;
1313                 evoice->Vol = 0x3ff;                    /* mute */
1314                 evoice->RVol = evoice->CVol = 0x7f;     /* mute */
1315                 evoice->Pan = 0x7f;                     /* mute */
1316                 evoice->Attribute = 0;
1317                 snd_trident_write_voice_regs(trident, evoice);
1318                 evoice->isync2 = 1;
1319                 evoice->isync_mark = runtime->period_size;
1320                 evoice->ESO = (runtime->period_size * 2) - 1;
1321         }
1322 
1323         spin_unlock_irq(&trident->reg_lock);
1324         return 0;
1325 }
1326 
1327 /*---------------------------------------------------------------------------
1328    snd_trident_spdif_hw_params
1329   
1330    Description: Set the hardware parameters for the spdif device.
1331   
1332    Parameters:  substream  - PCM substream class
1333                 hw_params  - hardware parameters
1334   
1335    Returns:     Error status
1336   
1337   ---------------------------------------------------------------------------*/
1338 
1339 static int snd_trident_spdif_hw_params(struct snd_pcm_substream *substream,
1340                                        struct snd_pcm_hw_params *hw_params)
1341 {
1342         struct snd_trident *trident = snd_pcm_substream_chip(substream);
1343         unsigned int old_bits = 0, change = 0;
1344         int err;
1345 
1346         err = snd_trident_allocate_pcm_mem(substream, hw_params);
1347         if (err < 0)
1348                 return err;
1349 
1350         if (trident->device == TRIDENT_DEVICE_ID_SI7018) {
1351                 err = snd_trident_allocate_evoice(substream, hw_params);
1352                 if (err < 0)
1353                         return err;
1354         }
1355 
1356         /* prepare SPDIF channel */
1357         spin_lock_irq(&trident->reg_lock);
1358         old_bits = trident->spdif_pcm_bits;
1359         if (old_bits & IEC958_AES0_PROFESSIONAL)
1360                 trident->spdif_pcm_bits &= ~IEC958_AES0_PRO_FS;
1361         else
1362                 trident->spdif_pcm_bits &= ~(IEC958_AES3_CON_FS << 24);
1363         if (params_rate(hw_params) >= 48000) {
1364                 trident->spdif_pcm_ctrl = 0x3c; // 48000 Hz
1365                 trident->spdif_pcm_bits |=
1366                         trident->spdif_bits & IEC958_AES0_PROFESSIONAL ?
1367                                 IEC958_AES0_PRO_FS_48000 :
1368                                 (IEC958_AES3_CON_FS_48000 << 24);
1369         }
1370         else if (params_rate(hw_params) >= 44100) {
1371                 trident->spdif_pcm_ctrl = 0x3e; // 44100 Hz
1372                 trident->spdif_pcm_bits |=
1373                         trident->spdif_bits & IEC958_AES0_PROFESSIONAL ?
1374                                 IEC958_AES0_PRO_FS_44100 :
1375                                 (IEC958_AES3_CON_FS_44100 << 24);
1376         }
1377         else {
1378                 trident->spdif_pcm_ctrl = 0x3d; // 32000 Hz
1379                 trident->spdif_pcm_bits |=
1380                         trident->spdif_bits & IEC958_AES0_PROFESSIONAL ?
1381                                 IEC958_AES0_PRO_FS_32000 :
1382                                 (IEC958_AES3_CON_FS_32000 << 24);
1383         }
1384         change = old_bits != trident->spdif_pcm_bits;
1385         spin_unlock_irq(&trident->reg_lock);
1386 
1387         if (change)
1388                 snd_ctl_notify(trident->card, SNDRV_CTL_EVENT_MASK_VALUE, &trident->spdif_pcm_ctl->id);
1389 
1390         return 0;
1391 }
1392 
1393 /*---------------------------------------------------------------------------
1394    snd_trident_spdif_prepare
1395   
1396    Description: Prepare SPDIF device for playback.
1397   
1398    Parameters:  substream  - PCM substream class
1399   
1400    Returns:     Error status
1401   
1402   ---------------------------------------------------------------------------*/
1403 
1404 static int snd_trident_spdif_prepare(struct snd_pcm_substream *substream)
1405 {
1406         struct snd_trident *trident = snd_pcm_substream_chip(substream);
1407         struct snd_pcm_runtime *runtime = substream->runtime;
1408         struct snd_trident_voice *voice = runtime->private_data;
1409         struct snd_trident_voice *evoice = voice->extra;
1410         struct snd_trident_pcm_mixer *mix = &trident->pcm_mixer[substream->number];
1411         unsigned int RESO, LBAO;
1412         unsigned int temp;
1413 
1414         spin_lock_irq(&trident->reg_lock);
1415 
1416         if (trident->device != TRIDENT_DEVICE_ID_SI7018) {
1417 
1418                 /* set delta (rate) value */
1419                 voice->Delta = snd_trident_convert_rate(runtime->rate);
1420                 voice->spurious_threshold = snd_trident_spurious_threshold(runtime->rate, runtime->period_size);
1421 
1422                 /* set Loop Back Address */
1423                 LBAO = runtime->dma_addr;
1424                 if (voice->memblk)
1425                         voice->LBA = voice->memblk->offset;
1426                 else
1427                         voice->LBA = LBAO;
1428 
1429                 voice->isync = 1;
1430                 voice->isync3 = 1;
1431                 voice->isync_mark = runtime->period_size;
1432                 voice->isync_max = runtime->buffer_size;
1433 
1434                 /* set target ESO for channel */
1435                 RESO = runtime->buffer_size - 1;
1436                 voice->ESO = voice->isync_ESO = (runtime->period_size * 2) + 6 - 1;
1437 
1438                 /* set ctrl mode */
1439                 voice->CTRL = snd_trident_control_mode(substream);
1440 
1441                 voice->FMC = 3;
1442                 voice->RVol = 0x7f;
1443                 voice->CVol = 0x7f;
1444                 voice->GVSel = 1;
1445                 voice->Pan = 0x7f;
1446                 voice->Vol = 0x3ff;
1447                 voice->EC = 0;
1448                 voice->CSO = 0;
1449                 voice->Alpha = 0;
1450                 voice->FMS = 0;
1451                 voice->Attribute = 0;
1452 
1453                 /* prepare surrogate IRQ channel */
1454                 snd_trident_write_voice_regs(trident, voice);
1455 
1456                 outw((RESO & 0xffff), TRID_REG(trident, NX_SPESO));
1457                 outb((RESO >> 16), TRID_REG(trident, NX_SPESO + 2));
1458                 outl((LBAO & 0xfffffffc), TRID_REG(trident, NX_SPLBA));
1459                 outw((voice->CSO & 0xffff), TRID_REG(trident, NX_SPCTRL_SPCSO));
1460                 outb((voice->CSO >> 16), TRID_REG(trident, NX_SPCTRL_SPCSO + 2));
1461 
1462                 /* set SPDIF setting */
1463                 outb(trident->spdif_pcm_ctrl, TRID_REG(trident, NX_SPCTRL_SPCSO + 3));
1464                 outl(trident->spdif_pcm_bits, TRID_REG(trident, NX_SPCSTATUS));
1465 
1466         } else {        /* SiS */
1467         
1468                 /* set delta (rate) value */
1469                 voice->Delta = 0x800;
1470                 voice->spurious_threshold = snd_trident_spurious_threshold(48000, runtime->period_size);
1471 
1472                 /* set Loop Begin Address */
1473                 if (voice->memblk)
1474                         voice->LBA = voice->memblk->offset;
1475                 else
1476                         voice->LBA = runtime->dma_addr;
1477 
1478                 voice->CSO = 0;
1479                 voice->ESO = runtime->buffer_size - 1;  /* in samples */
1480                 voice->CTRL = snd_trident_control_mode(substream);
1481                 voice->FMC = 3;
1482                 voice->GVSel = 1;
1483                 voice->EC = 0;
1484                 voice->Alpha = 0;
1485                 voice->FMS = 0;
1486                 voice->Vol = mix->vol;
1487                 voice->RVol = mix->rvol;
1488                 voice->CVol = mix->cvol;
1489                 voice->Pan = mix->pan;
1490                 voice->Attribute = (1<<(30-16))|(7<<(26-16))|
1491                                    (0<<(24-16))|(0<<(19-16));
1492 
1493                 snd_trident_write_voice_regs(trident, voice);
1494 
1495                 if (evoice != NULL) {
1496                         evoice->Delta = voice->Delta;
1497                         evoice->spurious_threshold = voice->spurious_threshold;
1498                         evoice->LBA = voice->LBA;
1499                         evoice->CSO = 0;
1500                         evoice->ESO = (runtime->period_size * 2) + 4 - 1; /* in samples */
1501                         evoice->CTRL = voice->CTRL;
1502                         evoice->FMC = 3;
1503                         evoice->GVSel = trident->device == TRIDENT_DEVICE_ID_SI7018 ? 0 : 1;
1504                         evoice->EC = 0;
1505                         evoice->Alpha = 0;
1506                         evoice->FMS = 0;
1507                         evoice->Vol = 0x3ff;                    /* mute */
1508                         evoice->RVol = evoice->CVol = 0x7f;     /* mute */
1509                         evoice->Pan = 0x7f;                     /* mute */
1510                         evoice->Attribute = 0;
1511                         snd_trident_write_voice_regs(trident, evoice);
1512                         evoice->isync2 = 1;
1513                         evoice->isync_mark = runtime->period_size;
1514                         evoice->ESO = (runtime->period_size * 2) - 1;
1515                 }
1516 
1517                 outl(trident->spdif_pcm_bits, TRID_REG(trident, SI_SPDIF_CS));
1518                 temp = inl(TRID_REG(trident, T4D_LFO_GC_CIR));
1519                 temp &= ~(1<<19);
1520                 outl(temp, TRID_REG(trident, T4D_LFO_GC_CIR));
1521                 temp = inl(TRID_REG(trident, SI_SERIAL_INTF_CTRL));
1522                 temp |= SPDIF_EN;
1523                 outl(temp, TRID_REG(trident, SI_SERIAL_INTF_CTRL));
1524         }
1525 
1526         spin_unlock_irq(&trident->reg_lock);
1527 
1528         return 0;
1529 }
1530 
1531 /*---------------------------------------------------------------------------
1532    snd_trident_trigger
1533   
1534    Description: Start/stop devices
1535   
1536    Parameters:  substream  - PCM substream class
1537                 cmd     - trigger command (STOP, GO)
1538   
1539    Returns:     Error status
1540   
1541   ---------------------------------------------------------------------------*/
1542 
1543 static int snd_trident_trigger(struct snd_pcm_substream *substream,
1544                                int cmd)
1545                                     
1546 {
1547         struct snd_trident *trident = snd_pcm_substream_chip(substream);
1548         struct snd_pcm_substream *s;
1549         unsigned int what, whati, capture_flag, spdif_flag;
1550         struct snd_trident_voice *voice, *evoice;
1551         unsigned int val, go;
1552 
1553         switch (cmd) {
1554         case SNDRV_PCM_TRIGGER_START:
1555         case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
1556         case SNDRV_PCM_TRIGGER_RESUME:
1557                 go = 1;
1558                 break;
1559         case SNDRV_PCM_TRIGGER_STOP:
1560         case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
1561         case SNDRV_PCM_TRIGGER_SUSPEND:
1562                 go = 0;
1563                 break;
1564         default:
1565                 return -EINVAL;
1566         }
1567         what = whati = capture_flag = spdif_flag = 0;
1568         spin_lock(&trident->reg_lock);
1569         val = inl(TRID_REG(trident, T4D_STIMER)) & 0x00ffffff;
1570         snd_pcm_group_for_each_entry(s, substream) {
1571                 if ((struct snd_trident *) snd_pcm_substream_chip(s) == trident) {
1572                         voice = s->runtime->private_data;
1573                         evoice = voice->extra;
1574                         what |= 1 << (voice->number & 0x1f);
1575                         if (evoice == NULL) {
1576                                 whati |= 1 << (voice->number & 0x1f);
1577                         } else {
1578                                 what |= 1 << (evoice->number & 0x1f);
1579                                 whati |= 1 << (evoice->number & 0x1f);
1580                                 if (go)
1581                                         evoice->stimer = val;
1582                         }
1583                         if (go) {
1584                                 voice->running = 1;
1585                                 voice->stimer = val;
1586                         } else {
1587                                 voice->running = 0;
1588                         }
1589                         snd_pcm_trigger_done(s, substream);
1590                         if (voice->capture)
1591                                 capture_flag = 1;
1592                         if (voice->spdif)
1593                                 spdif_flag = 1;
1594                 }
1595         }
1596         if (spdif_flag) {
1597                 if (trident->device != TRIDENT_DEVICE_ID_SI7018) {
1598                         outl(trident->spdif_pcm_bits, TRID_REG(trident, NX_SPCSTATUS));
1599                         val = trident->spdif_pcm_ctrl;
1600                         if (!go)
1601                                 val &= ~(0x28);
1602                         outb(val, TRID_REG(trident, NX_SPCTRL_SPCSO + 3));
1603                 } else {
1604                         outl(trident->spdif_pcm_bits, TRID_REG(trident, SI_SPDIF_CS));
1605                         val = inl(TRID_REG(trident, SI_SERIAL_INTF_CTRL)) | SPDIF_EN;
1606                         outl(val, TRID_REG(trident, SI_SERIAL_INTF_CTRL));
1607                 }
1608         }
1609         if (!go)
1610                 outl(what, TRID_REG(trident, T4D_STOP_B));
1611         val = inl(TRID_REG(trident, T4D_AINTEN_B));
1612         if (go) {
1613                 val |= whati;
1614         } else {
1615                 val &= ~whati;
1616         }
1617         outl(val, TRID_REG(trident, T4D_AINTEN_B));
1618         if (go) {
1619                 outl(what, TRID_REG(trident, T4D_START_B));
1620 
1621                 if (capture_flag && trident->device != TRIDENT_DEVICE_ID_SI7018)
1622                         outb(trident->bDMAStart, TRID_REG(trident, T4D_SBCTRL_SBE2R_SBDD));
1623         } else {
1624                 if (capture_flag && trident->device != TRIDENT_DEVICE_ID_SI7018)
1625                         outb(0x00, TRID_REG(trident, T4D_SBCTRL_SBE2R_SBDD));
1626         }
1627         spin_unlock(&trident->reg_lock);
1628         return 0;
1629 }
1630 
1631 /*---------------------------------------------------------------------------
1632    snd_trident_playback_pointer
1633   
1634    Description: This routine return the playback position
1635                 
1636    Parameters:  substream  - PCM substream class
1637 
1638    Returns:     position of buffer
1639   
1640   ---------------------------------------------------------------------------*/
1641 
1642 static snd_pcm_uframes_t snd_trident_playback_pointer(struct snd_pcm_substream *substream)
1643 {
1644         struct snd_trident *trident = snd_pcm_substream_chip(substream);
1645         struct snd_pcm_runtime *runtime = substream->runtime;
1646         struct snd_trident_voice *voice = runtime->private_data;
1647         unsigned int cso;
1648 
1649         if (!voice->running)
1650                 return 0;
1651 
1652         spin_lock(&trident->reg_lock);
1653 
1654         outb(voice->number, TRID_REG(trident, T4D_LFO_GC_CIR));
1655 
1656         if (trident->device != TRIDENT_DEVICE_ID_NX) {
1657                 cso = inw(TRID_REG(trident, CH_DX_CSO_ALPHA_FMS + 2));
1658         } else {                // ID_4DWAVE_NX
1659                 cso = (unsigned int) inl(TRID_REG(trident, CH_NX_DELTA_CSO)) & 0x00ffffff;
1660         }
1661 
1662         spin_unlock(&trident->reg_lock);
1663 
1664         if (cso >= runtime->buffer_size)
1665                 cso = 0;
1666 
1667         return cso;
1668 }
1669 
1670 /*---------------------------------------------------------------------------
1671    snd_trident_capture_pointer
1672   
1673    Description: This routine return the capture position
1674                 
1675    Parameters:   pcm1    - PCM device class
1676 
1677    Returns:     position of buffer
1678   
1679   ---------------------------------------------------------------------------*/
1680 
1681 static snd_pcm_uframes_t snd_trident_capture_pointer(struct snd_pcm_substream *substream)
1682 {
1683         struct snd_trident *trident = snd_pcm_substream_chip(substream);
1684         struct snd_pcm_runtime *runtime = substream->runtime;
1685         struct snd_trident_voice *voice = runtime->private_data;
1686         unsigned int result;
1687 
1688         if (!voice->running)
1689                 return 0;
1690 
1691         result = inw(TRID_REG(trident, T4D_SBBL_SBCL));
1692         if (runtime->channels > 1)
1693                 result >>= 1;
1694         if (result > 0)
1695                 result = runtime->buffer_size - result;
1696 
1697         return result;
1698 }
1699 
1700 /*---------------------------------------------------------------------------
1701    snd_trident_spdif_pointer
1702   
1703    Description: This routine return the SPDIF playback position
1704                 
1705    Parameters:  substream  - PCM substream class
1706 
1707    Returns:     position of buffer
1708   
1709   ---------------------------------------------------------------------------*/
1710 
1711 static snd_pcm_uframes_t snd_trident_spdif_pointer(struct snd_pcm_substream *substream)
1712 {
1713         struct snd_trident *trident = snd_pcm_substream_chip(substream);
1714         struct snd_pcm_runtime *runtime = substream->runtime;
1715         struct snd_trident_voice *voice = runtime->private_data;
1716         unsigned int result;
1717 
1718         if (!voice->running)
1719                 return 0;
1720 
1721         result = inl(TRID_REG(trident, NX_SPCTRL_SPCSO)) & 0x00ffffff;
1722 
1723         return result;
1724 }
1725 
1726 /*
1727  *  Playback support device description
1728  */
1729 
1730 static struct snd_pcm_hardware snd_trident_playback =
1731 {
1732         .info =                 (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED |
1733                                  SNDRV_PCM_INFO_BLOCK_TRANSFER |
1734                                  SNDRV_PCM_INFO_MMAP_VALID | SNDRV_PCM_INFO_SYNC_START |
1735                                  SNDRV_PCM_INFO_PAUSE /* | SNDRV_PCM_INFO_RESUME */),
1736         .formats =              (SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S16_LE |
1737                                  SNDRV_PCM_FMTBIT_S8 | SNDRV_PCM_FMTBIT_U16_LE),
1738         .rates =                SNDRV_PCM_RATE_CONTINUOUS | SNDRV_PCM_RATE_8000_48000,
1739         .rate_min =             4000,
1740         .rate_max =             48000,
1741         .channels_min =         1,
1742         .channels_max =         2,
1743         .buffer_bytes_max =     (256*1024),
1744         .period_bytes_min =     64,
1745         .period_bytes_max =     (256*1024),
1746         .periods_min =          1,
1747         .periods_max =          1024,
1748         .fifo_size =            0,
1749 };
1750 
1751 /*
1752  *  Capture support device description
1753  */
1754 
1755 static struct snd_pcm_hardware snd_trident_capture =
1756 {
1757         .info =                 (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED |
1758                                  SNDRV_PCM_INFO_BLOCK_TRANSFER |
1759                                  SNDRV_PCM_INFO_MMAP_VALID | SNDRV_PCM_INFO_SYNC_START |
1760                                  SNDRV_PCM_INFO_PAUSE /* | SNDRV_PCM_INFO_RESUME */),
1761         .formats =              (SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S16_LE |
1762                                  SNDRV_PCM_FMTBIT_S8 | SNDRV_PCM_FMTBIT_U16_LE),
1763         .rates =                SNDRV_PCM_RATE_CONTINUOUS | SNDRV_PCM_RATE_8000_48000,
1764         .rate_min =             4000,
1765         .rate_max =             48000,
1766         .channels_min =         1,
1767         .channels_max =         2,
1768         .buffer_bytes_max =     (128*1024),
1769         .period_bytes_min =     64,
1770         .period_bytes_max =     (128*1024),
1771         .periods_min =          1,
1772         .periods_max =          1024,
1773         .fifo_size =            0,
1774 };
1775 
1776 /*
1777  *  Foldback capture support device description
1778  */
1779 
1780 static struct snd_pcm_hardware snd_trident_foldback =
1781 {
1782         .info =                 (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED |
1783                                  SNDRV_PCM_INFO_BLOCK_TRANSFER |
1784                                  SNDRV_PCM_INFO_MMAP_VALID | SNDRV_PCM_INFO_SYNC_START |
1785                                  SNDRV_PCM_INFO_PAUSE /* | SNDRV_PCM_INFO_RESUME */),
1786         .formats =              SNDRV_PCM_FMTBIT_S16_LE,
1787         .rates =                SNDRV_PCM_RATE_48000,
1788         .rate_min =             48000,
1789         .rate_max =             48000,
1790         .channels_min =         2,
1791         .channels_max =         2,
1792         .buffer_bytes_max =     (128*1024),
1793         .period_bytes_min =     64,
1794         .period_bytes_max =     (128*1024),
1795         .periods_min =          1,
1796         .periods_max =          1024,
1797         .fifo_size =            0,
1798 };
1799 
1800 /*
1801  *  SPDIF playback support device description
1802  */
1803 
1804 static struct snd_pcm_hardware snd_trident_spdif =
1805 {
1806         .info =                 (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED |
1807                                  SNDRV_PCM_INFO_BLOCK_TRANSFER |
1808                                  SNDRV_PCM_INFO_MMAP_VALID | SNDRV_PCM_INFO_SYNC_START |
1809                                  SNDRV_PCM_INFO_PAUSE /* | SNDRV_PCM_INFO_RESUME */),
1810         .formats =              SNDRV_PCM_FMTBIT_S16_LE,
1811         .rates =                (SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 |
1812                                  SNDRV_PCM_RATE_48000),
1813         .rate_min =             32000,
1814         .rate_max =             48000,
1815         .channels_min =         2,
1816         .channels_max =         2,
1817         .buffer_bytes_max =     (128*1024),
1818         .period_bytes_min =     64,
1819         .period_bytes_max =     (128*1024),
1820         .periods_min =          1,
1821         .periods_max =          1024,
1822         .fifo_size =            0,
1823 };
1824 
1825 static struct snd_pcm_hardware snd_trident_spdif_7018 =
1826 {
1827         .info =                 (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED |
1828                                  SNDRV_PCM_INFO_BLOCK_TRANSFER |
1829                                  SNDRV_PCM_INFO_MMAP_VALID | SNDRV_PCM_INFO_SYNC_START |
1830                                  SNDRV_PCM_INFO_PAUSE /* | SNDRV_PCM_INFO_RESUME */),
1831         .formats =              SNDRV_PCM_FMTBIT_S16_LE,
1832         .rates =                SNDRV_PCM_RATE_48000,
1833         .rate_min =             48000,
1834         .rate_max =             48000,
1835         .channels_min =         2,
1836         .channels_max =         2,
1837         .buffer_bytes_max =     (128*1024),
1838         .period_bytes_min =     64,
1839         .period_bytes_max =     (128*1024),
1840         .periods_min =          1,
1841         .periods_max =          1024,
1842         .fifo_size =            0,
1843 };
1844 
1845 static void snd_trident_pcm_free_substream(struct snd_pcm_runtime *runtime)
1846 {
1847         struct snd_trident_voice *voice = runtime->private_data;
1848         struct snd_trident *trident;
1849 
1850         if (voice) {
1851                 trident = voice->trident;
1852                 snd_trident_free_voice(trident, voice);
1853         }
1854 }
1855 
1856 static int snd_trident_playback_open(struct snd_pcm_substream *substream)
1857 {
1858         struct snd_trident *trident = snd_pcm_substream_chip(substream);
1859         struct snd_pcm_runtime *runtime = substream->runtime;
1860         struct snd_trident_voice *voice;
1861 
1862         voice = snd_trident_alloc_voice(trident, SNDRV_TRIDENT_VOICE_TYPE_PCM, 0, 0);
1863         if (voice == NULL)
1864                 return -EAGAIN;
1865         snd_trident_pcm_mixer_build(trident, voice, substream);
1866         voice->substream = substream;
1867         runtime->private_data = voice;
1868         runtime->private_free = snd_trident_pcm_free_substream;
1869         runtime->hw = snd_trident_playback;
1870         snd_pcm_set_sync(substream);
1871         snd_pcm_hw_constraint_minmax(runtime, SNDRV_PCM_HW_PARAM_BUFFER_SIZE, 0, 64*1024);
1872         return 0;
1873 }
1874 
1875 /*---------------------------------------------------------------------------
1876    snd_trident_playback_close
1877   
1878    Description: This routine will close the 4DWave playback device. For now 
1879                 we will simply free the dma transfer buffer.
1880                 
1881    Parameters:  substream  - PCM substream class
1882 
1883   ---------------------------------------------------------------------------*/
1884 static int snd_trident_playback_close(struct snd_pcm_substream *substream)
1885 {
1886         struct snd_trident *trident = snd_pcm_substream_chip(substream);
1887         struct snd_pcm_runtime *runtime = substream->runtime;
1888         struct snd_trident_voice *voice = runtime->private_data;
1889 
1890         snd_trident_pcm_mixer_free(trident, voice, substream);
1891         return 0;
1892 }
1893 
1894 /*---------------------------------------------------------------------------
1895    snd_trident_spdif_open
1896   
1897    Description: This routine will open the 4DWave SPDIF device.
1898 
1899    Parameters:  substream  - PCM substream class
1900 
1901    Returns:     status  - success or failure flag
1902   
1903   ---------------------------------------------------------------------------*/
1904 
1905 static int snd_trident_spdif_open(struct snd_pcm_substream *substream)
1906 {
1907         struct snd_trident *trident = snd_pcm_substream_chip(substream);
1908         struct snd_trident_voice *voice;
1909         struct snd_pcm_runtime *runtime = substream->runtime;
1910         
1911         voice = snd_trident_alloc_voice(trident, SNDRV_TRIDENT_VOICE_TYPE_PCM, 0, 0);
1912         if (voice == NULL)
1913                 return -EAGAIN;
1914         voice->spdif = 1;
1915         voice->substream = substream;
1916         spin_lock_irq(&trident->reg_lock);
1917         trident->spdif_pcm_bits = trident->spdif_bits;
1918         spin_unlock_irq(&trident->reg_lock);
1919 
1920         runtime->private_data = voice;
1921         runtime->private_free = snd_trident_pcm_free_substream;
1922         if (trident->device == TRIDENT_DEVICE_ID_SI7018) {
1923                 runtime->hw = snd_trident_spdif;
1924         } else {
1925                 runtime->hw = snd_trident_spdif_7018;
1926         }
1927 
1928         trident->spdif_pcm_ctl->vd[0].access &= ~SNDRV_CTL_ELEM_ACCESS_INACTIVE;
1929         snd_ctl_notify(trident->card, SNDRV_CTL_EVENT_MASK_VALUE |
1930                        SNDRV_CTL_EVENT_MASK_INFO, &trident->spdif_pcm_ctl->id);
1931 
1932         snd_pcm_hw_constraint_minmax(runtime, SNDRV_PCM_HW_PARAM_BUFFER_SIZE, 0, 64*1024);
1933         return 0;
1934 }
1935 
1936 
1937 /*---------------------------------------------------------------------------
1938    snd_trident_spdif_close
1939   
1940    Description: This routine will close the 4DWave SPDIF device.
1941                 
1942    Parameters:  substream  - PCM substream class
1943 
1944   ---------------------------------------------------------------------------*/
1945 
1946 static int snd_trident_spdif_close(struct snd_pcm_substream *substream)
1947 {
1948         struct snd_trident *trident = snd_pcm_substream_chip(substream);
1949         unsigned int temp;
1950 
1951         spin_lock_irq(&trident->reg_lock);
1952         // restore default SPDIF setting
1953         if (trident->device != TRIDENT_DEVICE_ID_SI7018) {
1954                 outb(trident->spdif_ctrl, TRID_REG(trident, NX_SPCTRL_SPCSO + 3));
1955                 outl(trident->spdif_bits, TRID_REG(trident, NX_SPCSTATUS));
1956         } else {
1957                 outl(trident->spdif_bits, TRID_REG(trident, SI_SPDIF_CS));
1958                 temp = inl(TRID_REG(trident, SI_SERIAL_INTF_CTRL));
1959                 if (trident->spdif_ctrl) {
1960                         temp |= SPDIF_EN;
1961                 } else {
1962                         temp &= ~SPDIF_EN;
1963                 }
1964                 outl(temp, TRID_REG(trident, SI_SERIAL_INTF_CTRL));
1965         }
1966         spin_unlock_irq(&trident->reg_lock);
1967         trident->spdif_pcm_ctl->vd[0].access |= SNDRV_CTL_ELEM_ACCESS_INACTIVE;
1968         snd_ctl_notify(trident->card, SNDRV_CTL_EVENT_MASK_VALUE |
1969                        SNDRV_CTL_EVENT_MASK_INFO, &trident->spdif_pcm_ctl->id);
1970         return 0;
1971 }
1972 
1973 /*---------------------------------------------------------------------------
1974    snd_trident_capture_open
1975   
1976    Description: This routine will open the 4DWave 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_capture_open(struct snd_pcm_substream *substream)
1985 {
1986         struct snd_trident *trident = snd_pcm_substream_chip(substream);
1987         struct snd_trident_voice *voice;
1988         struct snd_pcm_runtime *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->capture = 1;
1994         voice->substream = substream;
1995         runtime->private_data = voice;
1996         runtime->private_free = snd_trident_pcm_free_substream;
1997         runtime->hw = snd_trident_capture;
1998         snd_pcm_set_sync(substream);
1999         snd_pcm_hw_constraint_minmax(runtime, SNDRV_PCM_HW_PARAM_BUFFER_SIZE, 0, 64*1024);
2000         return 0;
2001 }
2002 
2003 /*---------------------------------------------------------------------------
2004    snd_trident_capture_close
2005   
2006    Description: This routine will close the 4DWave capture device. For now 
2007                 we will simply free the dma transfer buffer.
2008                 
2009    Parameters:  substream  - PCM substream class
2010 
2011   ---------------------------------------------------------------------------*/
2012 static int snd_trident_capture_close(struct snd_pcm_substream *substream)
2013 {
2014         return 0;
2015 }
2016 
2017 /*---------------------------------------------------------------------------
2018    snd_trident_foldback_open
2019   
2020    Description: This routine will open the 4DWave foldback capture device.
2021 
2022    Parameters:  substream  - PCM substream class
2023 
2024    Returns:     status  - success or failure flag
2025 
2026   ---------------------------------------------------------------------------*/
2027 
2028 static int snd_trident_foldback_open(struct snd_pcm_substream *substream)
2029 {
2030         struct snd_trident *trident = snd_pcm_substream_chip(substream);
2031         struct snd_trident_voice *voice;
2032         struct snd_pcm_runtime *runtime = substream->runtime;
2033 
2034         voice = snd_trident_alloc_voice(trident, SNDRV_TRIDENT_VOICE_TYPE_PCM, 0, 0);
2035         if (voice == NULL)
2036                 return -EAGAIN;
2037         voice->foldback_chan = substream->number;
2038         voice->substream = substream;
2039         runtime->private_data = voice;
2040         runtime->private_free = snd_trident_pcm_free_substream;
2041         runtime->hw = snd_trident_foldback;
2042         snd_pcm_hw_constraint_minmax(runtime, SNDRV_PCM_HW_PARAM_BUFFER_SIZE, 0, 64*1024);
2043         return 0;
2044 }
2045 
2046 /*---------------------------------------------------------------------------
2047    snd_trident_foldback_close
2048   
2049    Description: This routine will close the 4DWave foldback capture device. 
2050                 For now we will simply free the dma transfer buffer.
2051                 
2052    Parameters:  substream  - PCM substream class
2053 
2054   ---------------------------------------------------------------------------*/
2055 static int snd_trident_foldback_close(struct snd_pcm_substream *substream)
2056 {
2057         struct snd_trident *trident = snd_pcm_substream_chip(substream);
2058         struct snd_trident_voice *voice;
2059         struct snd_pcm_runtime *runtime = substream->runtime;
2060         voice = runtime->private_data;
2061         
2062         /* stop capture channel */
2063         spin_lock_irq(&trident->reg_lock);
2064         outb(0x00, TRID_REG(trident, T4D_RCI + voice->foldback_chan));
2065         spin_unlock_irq(&trident->reg_lock);
2066         return 0;
2067 }
2068 
2069 /*---------------------------------------------------------------------------
2070    PCM operations
2071   ---------------------------------------------------------------------------*/
2072 
2073 static struct snd_pcm_ops snd_trident_playback_ops = {
2074         .open =         snd_trident_playback_open,
2075         .close =        snd_trident_playback_close,
2076         .ioctl =        snd_trident_ioctl,
2077         .hw_params =    snd_trident_hw_params,
2078         .hw_free =      snd_trident_hw_free,
2079         .prepare =      snd_trident_playback_prepare,
2080         .trigger =      snd_trident_trigger,
2081         .pointer =      snd_trident_playback_pointer,
2082 };
2083 
2084 static struct snd_pcm_ops snd_trident_nx_playback_ops = {
2085         .open =         snd_trident_playback_open,
2086         .close =        snd_trident_playback_close,
2087         .ioctl =        snd_trident_ioctl,
2088         .hw_params =    snd_trident_hw_params,
2089         .hw_free =      snd_trident_hw_free,
2090         .prepare =      snd_trident_playback_prepare,
2091         .trigger =      snd_trident_trigger,
2092         .pointer =      snd_trident_playback_pointer,
2093         .page =         snd_pcm_sgbuf_ops_page,
2094 };
2095 
2096 static struct snd_pcm_ops snd_trident_capture_ops = {
2097         .open =         snd_trident_capture_open,
2098         .close =        snd_trident_capture_close,
2099         .ioctl =        snd_trident_ioctl,
2100         .hw_params =    snd_trident_capture_hw_params,
2101         .hw_free =      snd_trident_hw_free,
2102         .prepare =      snd_trident_capture_prepare,
2103         .trigger =      snd_trident_trigger,
2104         .pointer =      snd_trident_capture_pointer,
2105 };
2106 
2107 static struct snd_pcm_ops snd_trident_si7018_capture_ops = {
2108         .open =         snd_trident_capture_open,
2109         .close =        snd_trident_capture_close,
2110         .ioctl =        snd_trident_ioctl,
2111         .hw_params =    snd_trident_si7018_capture_hw_params,
2112         .hw_free =      snd_trident_si7018_capture_hw_free,
2113         .prepare =      snd_trident_si7018_capture_prepare,
2114         .trigger =      snd_trident_trigger,
2115         .pointer =      snd_trident_playback_pointer,
2116 };
2117 
2118 static struct snd_pcm_ops snd_trident_foldback_ops = {
2119         .open =         snd_trident_foldback_open,
2120         .close =        snd_trident_foldback_close,
2121         .ioctl =        snd_trident_ioctl,
2122         .hw_params =    snd_trident_hw_params,
2123         .hw_free =      snd_trident_hw_free,
2124         .prepare =      snd_trident_foldback_prepare,
2125         .trigger =      snd_trident_trigger,
2126         .pointer =      snd_trident_playback_pointer,
2127 };
2128 
2129 static struct snd_pcm_ops snd_trident_nx_foldback_ops = {
2130         .open =         snd_trident_foldback_open,
2131         .close =        snd_trident_foldback_close,
2132         .ioctl =        snd_trident_ioctl,
2133         .hw_params =    snd_trident_hw_params,
2134         .hw_free =      snd_trident_hw_free,
2135         .prepare =      snd_trident_foldback_prepare,
2136         .trigger =      snd_trident_trigger,
2137         .pointer =      snd_trident_playback_pointer,
2138         .page =         snd_pcm_sgbuf_ops_page,
2139 };
2140 
2141 static struct snd_pcm_ops snd_trident_spdif_ops = {
2142         .open =         snd_trident_spdif_open,
2143         .close =        snd_trident_spdif_close,
2144         .ioctl =        snd_trident_ioctl,
2145         .hw_params =    snd_trident_spdif_hw_params,
2146         .hw_free =      snd_trident_hw_free,
2147         .prepare =      snd_trident_spdif_prepare,
2148         .trigger =      snd_trident_trigger,
2149         .pointer =      snd_trident_spdif_pointer,
2150 };
2151 
2152 static struct snd_pcm_ops snd_trident_spdif_7018_ops = {
2153         .open =         snd_trident_spdif_open,
2154         .close =        snd_trident_spdif_close,
2155         .ioctl =        snd_trident_ioctl,
2156         .hw_params =    snd_trident_spdif_hw_params,
2157         .hw_free =      snd_trident_hw_free,
2158         .prepare =      snd_trident_spdif_prepare,
2159         .trigger =      snd_trident_trigger,
2160         .pointer =      snd_trident_playback_pointer,
2161 };
2162 
2163 /*---------------------------------------------------------------------------
2164    snd_trident_pcm
2165   
2166    Description: This routine registers the 4DWave device for PCM support.
2167                 
2168    Parameters:  trident - pointer to target device class for 4DWave.
2169 
2170    Returns:     None
2171   
2172   ---------------------------------------------------------------------------*/
2173 
2174 int __devinit snd_trident_pcm(struct snd_trident * trident,
2175                               int device, struct snd_pcm ** rpcm)
2176 {
2177         struct snd_pcm *pcm;
2178         int err;
2179 
2180         if (rpcm)
2181                 *rpcm = NULL;
2182         if ((err = snd_pcm_new(trident->card, "trident_dx_nx", device, trident->ChanPCM, 1, &pcm)) < 0)
2183                 return err;
2184 
2185         pcm->private_data = trident;
2186 
2187         if (trident->tlb.entries) {
2188                 snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_trident_nx_playback_ops);
2189         } else {
2190                 snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_trident_playback_ops);
2191         }
2192         snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE,
2193                         trident->device != TRIDENT_DEVICE_ID_SI7018 ?
2194                         &snd_trident_capture_ops :
2195                         &snd_trident_si7018_capture_ops);
2196 
2197         pcm->info_flags = 0;
2198         pcm->dev_subclass = SNDRV_PCM_SUBCLASS_GENERIC_MIX;
2199         strcpy(pcm->name, "Trident 4DWave");
2200         trident->pcm = pcm;
2201 
2202         if (trident->tlb.entries) {
2203                 struct snd_pcm_substream *substream;
2204                 for (substream = pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream; substream; substream = substream->next)
2205                         snd_pcm_lib_preallocate_pages(substream, SNDRV_DMA_TYPE_DEV_SG,
2206                                                       snd_dma_pci_data(trident->pci),
2207                                                       64*1024, 128*1024);
2208                 snd_pcm_lib_preallocate_pages(pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream,
2209                                               SNDRV_DMA_TYPE_DEV, snd_dma_pci_data(trident->pci),
2210                                               64*1024, 128*1024);
2211         } else {
2212                 snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV,
2213                                                       snd_dma_pci_data(trident->pci), 64*1024, 128*1024);
2214         }
2215 
2216         if (rpcm)
2217                 *rpcm = pcm;
2218         return 0;
2219 }
2220 
2221 /*---------------------------------------------------------------------------
2222    snd_trident_foldback_pcm
2223   
2224    Description: This routine registers the 4DWave device for foldback PCM support.
2225                 
2226    Parameters:  trident - pointer to target device class for 4DWave.
2227 
2228    Returns:     None
2229   
2230   ---------------------------------------------------------------------------*/
2231 
2232 int __devinit snd_trident_foldback_pcm(struct snd_trident * trident,
2233                                        int device, struct snd_pcm ** rpcm)
2234 {
2235         struct snd_pcm *foldback;
2236         int err;
2237         int num_chan = 3;
2238         struct snd_pcm_substream *substream;
2239 
2240         if (rpcm)
2241                 *rpcm = NULL;
2242         if (trident->device == TRIDENT_DEVICE_ID_NX)
2243                 num_chan = 4;
2244         if ((err = snd_pcm_new(trident->card, "trident_dx_nx", device, 0, num_chan, &foldback)) < 0)
2245                 return err;
2246 
2247         foldback->private_data = trident;
2248         if (trident->tlb.entries)
2249                 snd_pcm_set_ops(foldback, SNDRV_PCM_STREAM_CAPTURE, &snd_trident_nx_foldback_ops);
2250         else
2251                 snd_pcm_set_ops(foldback, SNDRV_PCM_STREAM_CAPTURE, &snd_trident_foldback_ops);
2252         foldback->info_flags = 0;
2253         strcpy(foldback->name, "Trident 4DWave");
2254         substream = foldback->streams[SNDRV_PCM_STREAM_CAPTURE].substream;
2255         strcpy(substream->name, "Front Mixer");
2256         substream = substream->next;
2257         strcpy(substream->name, "Reverb Mixer");
2258         substream = substream->next;
2259         strcpy(substream->name, "Chorus Mixer");
2260         if (num_chan == 4) {
2261                 substream = substream->next;
2262                 strcpy(substream->name, "Second AC'97 ADC");
2263         }
2264         trident->foldback = foldback;
2265 
2266         if (trident->tlb.entries)
2267                 snd_pcm_lib_preallocate_pages_for_all(foldback, SNDRV_DMA_TYPE_DEV_SG,
2268                                                       snd_dma_pci_data(trident->pci), 0, 128*1024);
2269         else
2270                 snd_pcm_lib_preallocate_pages_for_all(foldback, SNDRV_DMA_TYPE_DEV,
2271                                                       snd_dma_pci_data(trident->pci), 64*1024, 128*1024);
2272 
2273         if (rpcm)
2274                 *rpcm = foldback;
2275         return 0;
2276 }
2277 
2278 /*---------------------------------------------------------------------------
2279    snd_trident_spdif
2280   
2281    Description: This routine registers the 4DWave-NX device for SPDIF support.
2282                 
2283    Parameters:  trident - pointer to target device class for 4DWave-NX.
2284 
2285    Returns:     None
2286   
2287   ---------------------------------------------------------------------------*/
2288 
2289 int __devinit snd_trident_spdif_pcm(struct snd_trident * trident,
2290                                     int device, struct snd_pcm ** rpcm)
2291 {
2292         struct snd_pcm *spdif;
2293         int err;
2294 
2295         if (rpcm)
2296                 *rpcm = NULL;
2297         if ((err = snd_pcm_new(trident->card, "trident_dx_nx IEC958", device, 1, 0, &spdif)) < 0)
2298                 return err;
2299 
2300         spdif->private_data = trident;
2301         if (trident->device != TRIDENT_DEVICE_ID_SI7018) {
2302                 snd_pcm_set_ops(spdif, SNDRV_PCM_STREAM_PLAYBACK, &snd_trident_spdif_ops);
2303         } else {
2304                 snd_pcm_set_ops(spdif, SNDRV_PCM_STREAM_PLAYBACK, &snd_trident_spdif_7018_ops);
2305         }
2306         spdif->info_flags = 0;
2307         strcpy(spdif->name, "Trident 4DWave IEC958");
2308         trident->spdif = spdif;
2309 
2310         snd_pcm_lib_preallocate_pages_for_all(spdif, SNDRV_DMA_TYPE_DEV, snd_dma_pci_data(trident->pci), 64*1024, 128*1024);
2311 
2312         if (rpcm)
2313                 *rpcm = spdif;
2314         return 0;
2315 }
2316 
2317 /*
2318  *  Mixer part
2319  */
2320 
2321 
2322 /*---------------------------------------------------------------------------
2323     snd_trident_spdif_control
2324 
2325     Description: enable/disable S/PDIF out from ac97 mixer
2326   ---------------------------------------------------------------------------*/
2327 
2328 #define snd_trident_spdif_control_info  snd_ctl_boolean_mono_info
2329 
2330 static int snd_trident_spdif_control_get(struct snd_kcontrol *kcontrol,
2331                                          struct snd_ctl_elem_value *ucontrol)
2332 {
2333         struct snd_trident *trident = snd_kcontrol_chip(kcontrol);
2334         unsigned char val;
2335 
2336         spin_lock_irq(&trident->reg_lock);
2337         val = trident->spdif_ctrl;
2338         ucontrol->value.integer.value[0] = val == kcontrol->private_value;
2339         spin_unlock_irq(&trident->reg_lock);
2340         return 0;
2341 }
2342 
2343 static int snd_trident_spdif_control_put(struct snd_kcontrol *kcontrol,
2344                                          struct snd_ctl_elem_value *ucontrol)
2345 {
2346         struct snd_trident *trident = snd_kcontrol_chip(kcontrol);
2347         unsigned char val;
2348         int change;
2349 
2350         val = ucontrol->value.integer.value[0] ? (unsigned char) kcontrol->private_value : 0x00;
2351         spin_lock_irq(&trident->reg_lock);
2352         /* S/PDIF C Channel bits 0-31 : 48khz, SCMS disabled */
2353         change = trident->spdif_ctrl != val;
2354         trident->spdif_ctrl = val;
2355         if (trident->device != TRIDENT_DEVICE_ID_SI7018) {
2356                 if ((inb(TRID_REG(trident, NX_SPCTRL_SPCSO + 3)) & 0x10) == 0) {
2357                         outl(trident->spdif_bits, TRID_REG(trident, NX_SPCSTATUS));
2358                         outb(trident->spdif_ctrl, TRID_REG(trident, NX_SPCTRL_SPCSO + 3));
2359                 }
2360         } else {
2361                 if (trident->spdif == NULL) {
2362                         unsigned int temp;
2363                         outl(trident->spdif_bits, TRID_REG(trident, SI_SPDIF_CS));
2364                         temp = inl(TRID_REG(trident, SI_SERIAL_INTF_CTRL)) & ~SPDIF_EN;
2365                         if (val)
2366                                 temp |= SPDIF_EN;
2367                         outl(temp, TRID_REG(trident, SI_SERIAL_INTF_CTRL));
2368                 }
2369         }
2370         spin_unlock_irq(&trident->reg_lock);
2371         return change;
2372 }
2373 
2374 static struct snd_kcontrol_new snd_trident_spdif_control __devinitdata =
2375 {
2376         .iface =        SNDRV_CTL_ELEM_IFACE_MIXER,
2377         .name =         SNDRV_CTL_NAME_IEC958("",PLAYBACK,SWITCH),
2378         .info =         snd_trident_spdif_control_info,
2379         .get =          snd_trident_spdif_control_get,
2380         .put =          snd_trident_spdif_control_put,
2381         .private_value = 0x28,
2382 };
2383 
2384 /*---------------------------------------------------------------------------
2385     snd_trident_spdif_default
2386 
2387     Description: put/get the S/PDIF default settings
2388   ---------------------------------------------------------------------------*/
2389 
2390 static int snd_trident_spdif_default_info(struct snd_kcontrol *kcontrol,
2391                                           struct snd_ctl_elem_info *uinfo)
2392 {
2393         uinfo->type = SNDRV_CTL_ELEM_TYPE_IEC958;
2394         uinfo->count = 1;
2395         return 0;
2396 }
2397 
2398 static int snd_trident_spdif_default_get(struct snd_kcontrol *kcontrol,
2399                                          struct snd_ctl_elem_value *ucontrol)
2400 {
2401         struct snd_trident *trident = snd_kcontrol_chip(kcontrol);
2402 
2403         spin_lock_irq(&trident->reg_lock);
2404         ucontrol->value.iec958.status[0] = (trident->spdif_bits >> 0) & 0xff;
2405         ucontrol->value.iec958.status[1] = (trident->spdif_bits >> 8) & 0xff;
2406         ucontrol->value.iec958.status[2] = (trident->spdif_bits >> 16) & 0xff;
2407         ucontrol->value.iec958.status[3] = (trident->spdif_bits >> 24) & 0xff;
2408         spin_unlock_irq(&trident->reg_lock);
2409         return 0;
2410 }
2411 
2412 static int snd_trident_spdif_default_put(struct snd_kcontrol *kcontrol,
2413                                          struct snd_ctl_elem_value *ucontrol)
2414 {
2415         struct snd_trident *trident = snd_kcontrol_chip(kcontrol);
2416         unsigned int val;
2417         int change;
2418 
2419         val = (ucontrol->value.iec958.status[0] << 0) |
2420               (ucontrol->value.iec958.status[1] << 8) |
2421               (ucontrol->value.iec958.status[2] << 16) |
2422               (ucontrol->value.iec958.status[3] << 24);
2423         spin_lock_irq(&trident->reg_lock);
2424         change = trident->spdif_bits != val;
2425         trident->spdif_bits = val;
2426         if (trident->device != TRIDENT_DEVICE_ID_SI7018) {
2427                 if ((inb(TRID_REG(trident, NX_SPCTRL_SPCSO + 3)) & 0x10) == 0)
2428                         outl(trident->spdif_bits, TRID_REG(trident, NX_SPCSTATUS));
2429         } else {
2430                 if (trident->spdif == NULL)
2431                         outl(trident->spdif_bits, TRID_REG(trident, SI_SPDIF_CS));
2432         }
2433         spin_unlock_irq(&trident->reg_lock);
2434         return change;
2435 }
2436 
2437 static struct snd_kcontrol_new snd_trident_spdif_default __devinitdata =
2438 {
2439         .iface =        SNDRV_CTL_ELEM_IFACE_PCM,
2440         .name =         SNDRV_CTL_NAME_IEC958("",PLAYBACK,DEFAULT),
2441         .info =         snd_trident_spdif_default_info,
2442         .get =          snd_trident_spdif_default_get,
2443         .put =          snd_trident_spdif_default_put
2444 };
2445 
2446 /*---------------------------------------------------------------------------
2447     snd_trident_spdif_mask
2448 
2449     Description: put/get the S/PDIF mask
2450   ---------------------------------------------------------------------------*/
2451 
2452 static int snd_trident_spdif_mask_info(struct snd_kcontrol *kcontrol,
2453                                        struct snd_ctl_elem_info *uinfo)
2454 {
2455         uinfo->type = SNDRV_CTL_ELEM_TYPE_IEC958;
2456         uinfo->count = 1;
2457         return 0;
2458 }
2459 
2460 static int snd_trident_spdif_mask_get(struct snd_kcontrol *kcontrol,
2461                                       struct snd_ctl_elem_value *ucontrol)
2462 {
2463         ucontrol->value.iec958.status[0] = 0xff;
2464         ucontrol->value.iec958.status[1] = 0xff;
2465         ucontrol->value.iec958.status[2] = 0xff;
2466         ucontrol->value.iec958.status[3] = 0xff;
2467         return 0;
2468 }
2469 
2470 static struct snd_kcontrol_new snd_trident_spdif_mask __devinitdata =
2471 {
2472         .access =       SNDRV_CTL_ELEM_ACCESS_READ,
2473         .iface =        SNDRV_CTL_ELEM_IFACE_PCM,
2474         .name =         SNDRV_CTL_NAME_IEC958("",PLAYBACK,MASK),
2475         .info =         snd_trident_spdif_mask_info,
2476         .get =          snd_trident_spdif_mask_get,
2477 };
2478 
2479 /*---------------------------------------------------------------------------
2480     snd_trident_spdif_stream
2481 
2482     Description: put/get the S/PDIF stream settings
2483   ---------------------------------------------------------------------------*/
2484 
2485 static int snd_trident_spdif_stream_info(struct snd_kcontrol *kcontrol,
2486                                          struct snd_ctl_elem_info *uinfo)
2487 {
2488         uinfo->type = SNDRV_CTL_ELEM_TYPE_IEC958;
2489         uinfo->count = 1;
2490         return 0;
2491 }
2492 
2493 static int snd_trident_spdif_stream_get(struct snd_kcontrol *kcontrol,
2494                                         struct snd_ctl_elem_value *ucontrol)
2495 {
2496         struct snd_trident *trident = snd_kcontrol_chip(kcontrol);
2497 
2498         spin_lock_irq(&trident->reg_lock);
2499         ucontrol->value.iec958.status[0] = (trident->spdif_pcm_bits >> 0) & 0xff;
2500         ucontrol->value.iec958.status[1] = (trident->spdif_pcm_bits >> 8) & 0xff;
2501         ucontrol->value.iec958.status[2] = (trident->spdif_pcm_bits >> 16) & 0xff;
2502         ucontrol->value.iec958.status[3] = (trident->spdif_pcm_bits >> 24) & 0xff;
2503         spin_unlock_irq(&trident->reg_lock);
2504         return 0;
2505 }
2506 
2507 static int snd_trident_spdif_stream_put(struct snd_kcontrol *kcontrol,
2508                                         struct snd_ctl_elem_value *ucontrol)
2509 {
2510         struct snd_trident *trident = snd_kcontrol_chip(kcontrol);
2511         unsigned int val;
2512         int change;
2513 
2514         val = (ucontrol->value.iec958.status[0] << 0) |
2515               (ucontrol->value.iec958.status[1] << 8) |
2516               (ucontrol->value.iec958.status[2] << 16) |
2517               (ucontrol->value.iec958.status[3] << 24);
2518         spin_lock_irq(&trident->reg_lock);
2519         change = trident->spdif_pcm_bits != val;
2520         trident->spdif_pcm_bits = val;
2521         if (trident->spdif != NULL) {
2522                 if (trident->device != TRIDENT_DEVICE_ID_SI7018) {
2523                         outl(trident->spdif_pcm_bits, TRID_REG(trident, NX_SPCSTATUS));
2524                 } else {
2525                         outl(trident->spdif_bits, TRID_REG(trident, SI_SPDIF_CS));
2526                 }
2527         }
2528         spin_unlock_irq(&trident->reg_lock);
2529         return change;
2530 }
2531 
2532 static struct snd_kcontrol_new snd_trident_spdif_stream __devinitdata =
2533 {
2534         .access =       SNDRV_CTL_ELEM_ACCESS_READWRITE | SNDRV_CTL_ELEM_ACCESS_INACTIVE,
2535         .iface =        SNDRV_CTL_ELEM_IFACE_PCM,
2536         .name =         SNDRV_CTL_NAME_IEC958("",PLAYBACK,PCM_STREAM),
2537         .info =         snd_trident_spdif_stream_info,
2538         .get =          snd_trident_spdif_stream_get,
2539         .put =          snd_trident_spdif_stream_put
2540 };
2541 
2542 /*---------------------------------------------------------------------------
2543     snd_trident_ac97_control
2544 
2545     Description: enable/disable rear path for ac97
2546   ---------------------------------------------------------------------------*/
2547 
2548 #define snd_trident_ac97_control_info   snd_ctl_boolean_mono_info
2549 
2550 static int snd_trident_ac97_control_get(struct snd_kcontrol *kcontrol,
2551                                         struct snd_ctl_elem_value *ucontrol)
2552 {
2553         struct snd_trident *trident = snd_kcontrol_chip(kcontrol);
2554         unsigned char val;
2555 
2556         spin_lock_irq(&trident->reg_lock);
2557         val = trident->ac97_ctrl = inl(TRID_REG(trident, NX_ACR0_AC97_COM_STAT));
2558         ucontrol->value.integer.value[0] = (val & (1 << kcontrol->private_value)) ? 1 : 0;
2559         spin_unlock_irq(&trident->reg_lock);
2560         return 0;
2561 }
2562 
2563 static int snd_trident_ac97_control_put(struct snd_kcontrol *kcontrol,
2564                                         struct snd_ctl_elem_value *ucontrol)
2565 {
2566         struct snd_trident *trident = snd_kcontrol_chip(kcontrol);
2567         unsigned char val;
2568         int change = 0;
2569 
2570         spin_lock_irq(&trident->reg_lock);
2571         val = trident->ac97_ctrl = inl(TRID_REG(trident, NX_ACR0_AC97_COM_STAT));
2572         val &= ~(1 << kcontrol->private_value);
2573         if (ucontrol->value.integer.value[0])
2574                 val |= 1 << kcontrol->private_value;
2575         change = val != trident->ac97_ctrl;
2576         trident->ac97_ctrl = val;
2577         outl(trident->ac97_ctrl = val, TRID_REG(trident, NX_ACR0_AC97_COM_STAT));
2578         spin_unlock_irq(&trident->reg_lock);
2579         return change;
2580 }
2581 
2582 static struct snd_kcontrol_new snd_trident_ac97_rear_control __devinitdata =
2583 {
2584         .iface =        SNDRV_CTL_ELEM_IFACE_MIXER,
2585         .name =         "Rear Path",
2586         .info =         snd_trident_ac97_control_info,
2587         .get =          snd_trident_ac97_control_get,
2588         .put =          snd_trident_ac97_control_put,
2589         .private_value = 4,
2590 };
2591 
2592 /*---------------------------------------------------------------------------
2593     snd_trident_vol_control
2594 
2595     Description: wave & music volume control
2596   ---------------------------------------------------------------------------*/
2597 
2598 static int snd_trident_vol_control_info(struct snd_kcontrol *kcontrol,
2599                                         struct snd_ctl_elem_info *uinfo)
2600 {
2601         uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
2602         uinfo->count = 2;
2603         uinfo->value.integer.min = 0;
2604         uinfo->value.integer.max = 255;
2605         return 0;
2606 }
2607 
2608 static int snd_trident_vol_control_get(struct snd_kcontrol *kcontrol,
2609                                        struct snd_ctl_elem_value *ucontrol)
2610 {
2611         struct snd_trident *trident = snd_kcontrol_chip(kcontrol);
2612         unsigned int val;
2613 
2614         val = trident->musicvol_wavevol;
2615         ucontrol->value.integer.value[0] = 255 - ((val >> kcontrol->private_value) & 0xff);
2616         ucontrol->value.integer.value[1] = 255 - ((val >> (kcontrol->private_value + 8)) & 0xff);
2617         return 0;
2618 }
2619 
2620 static const DECLARE_TLV_DB_SCALE(db_scale_gvol, -6375, 25, 0);
2621 
2622 static int snd_trident_vol_control_put(struct snd_kcontrol *kcontrol,
2623                                        struct snd_ctl_elem_value *ucontrol)
2624 {
2625         struct snd_trident *trident = snd_kcontrol_chip(kcontrol);
2626         unsigned int val;
2627         int change = 0;
2628 
2629         spin_lock_irq(&trident->reg_lock);
2630         val = trident->musicvol_wavevol;
2631         val &= ~(0xffff << kcontrol->private_value);
2632         val |= ((255 - (ucontrol->value.integer.value[0] & 0xff)) |
2633                 ((255 - (ucontrol->value.integer.value[1] & 0xff)) << 8)) << kcontrol->private_value;
2634         change = val != trident->musicvol_wavevol;
2635         outl(trident->musicvol_wavevol = val, TRID_REG(trident, T4D_MUSICVOL_WAVEVOL));
2636         spin_unlock_irq(&trident->reg_lock);
2637         return change;
2638 }
2639 
2640 static struct snd_kcontrol_new snd_trident_vol_music_control __devinitdata =
2641 {
2642         .iface =        SNDRV_CTL_ELEM_IFACE_MIXER,
2643         .name =         "Music Playback Volume",
2644         .info =         snd_trident_vol_control_info,
2645         .get =          snd_trident_vol_control_get,
2646         .put =          snd_trident_vol_control_put,
2647         .private_value = 16,
2648         .tlv = { .p = db_scale_gvol },
2649 };
2650 
2651 static struct snd_kcontrol_new snd_trident_vol_wave_control __devinitdata =
2652 {
2653         .iface =        SNDRV_CTL_ELEM_IFACE_MIXER,
2654         .name =         "Wave Playback Volume",
2655         .info =         snd_trident_vol_control_info,
2656         .get =          snd_trident_vol_control_get,
2657         .put =          snd_trident_vol_control_put,
2658         .private_value = 0,
2659         .tlv = { .p = db_scale_gvol },
2660 };
2661 
2662 /*---------------------------------------------------------------------------
2663     snd_trident_pcm_vol_control
2664 
2665     Description: PCM front volume control
2666   ---------------------------------------------------------------------------*/
2667 
2668 static int snd_trident_pcm_vol_control_info(struct snd_kcontrol *kcontrol,
2669                                             struct snd_ctl_elem_info *uinfo)
2670 {
2671         struct snd_trident *trident = snd_kcontrol_chip(kcontrol);
2672 
2673         uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
2674         uinfo->count = 1;
2675         uinfo->value.integer.min = 0;
2676         uinfo->value.integer.max = 255;
2677         if (trident->device == TRIDENT_DEVICE_ID_SI7018)
2678                 uinfo->value.integer.max = 1023;
2679         return 0;
2680 }
2681 
2682 static int snd_trident_pcm_vol_control_get(struct snd_kcontrol *kcontrol,
2683                                            struct snd_ctl_elem_value *ucontrol)
2684 {
2685         struct snd_trident *trident = snd_kcontrol_chip(kcontrol);
2686         struct snd_trident_pcm_mixer *mix = &trident->pcm_mixer[snd_ctl_get_ioffnum(kcontrol, &ucontrol->id)];
2687 
2688         if (trident->device == TRIDENT_DEVICE_ID_SI7018) {
2689                 ucontrol->value.integer.value[0] = 1023 - mix->vol;
2690         } else {
2691                 ucontrol->value.integer.value[0] = 255 - (mix->vol>>2);
2692         }
2693         return 0;
2694 }
2695 
2696 static int snd_trident_pcm_vol_control_put(struct snd_kcontrol *kcontrol,
2697                                            struct snd_ctl_elem_value *ucontrol)
2698 {
2699         struct snd_trident *trident = snd_kcontrol_chip(kcontrol);
2700         struct snd_trident_pcm_mixer *mix = &trident->pcm_mixer[snd_ctl_get_ioffnum(kcontrol, &ucontrol->id)];
2701         unsigned int val;
2702         int change = 0;
2703 
2704         if (trident->device == TRIDENT_DEVICE_ID_SI7018) {
2705                 val = 1023 - (ucontrol->value.integer.value[0] & 1023);
2706         } else {
2707                 val = (255 - (ucontrol->value.integer.value[0] & 255)) << 2;
2708         }
2709         spin_lock_irq(&trident->reg_lock);
2710         change = val != mix->vol;
2711         mix->vol = val;
2712         if (mix->voice != NULL)
2713                 snd_trident_write_vol_reg(trident, mix->voice, val);
2714         spin_unlock_irq(&trident->reg_lock);
2715         return change;
2716 }
2717 
2718 static struct snd_kcontrol_new snd_trident_pcm_vol_control __devinitdata =
2719 {
2720         .iface =        SNDRV_CTL_ELEM_IFACE_MIXER,
2721         .name =         "PCM Front Playback Volume",
2722         .access =       SNDRV_CTL_ELEM_ACCESS_READWRITE | SNDRV_CTL_ELEM_ACCESS_INACTIVE,
2723         .count =        32,
2724         .info =         snd_trident_pcm_vol_control_info,
2725         .get =          snd_trident_pcm_vol_control_get,
2726         .put =          snd_trident_pcm_vol_control_put,
2727         /* FIXME: no tlv yet */
2728 };
2729 
2730 /*---------------------------------------------------------------------------
2731     snd_trident_pcm_pan_control
2732 
2733     Description: PCM front pan control
2734   ---------------------------------------------------------------------------*/
2735 
2736 static int snd_trident_pcm_pan_control_info(struct snd_kcontrol *kcontrol,
2737                                             struct snd_ctl_elem_info *uinfo)
2738 {
2739         uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
2740         uinfo->count = 1;
2741         uinfo->value.integer.min = 0;
2742         uinfo->value.integer.max = 127;
2743         return 0;
2744 }
2745 
2746 static int snd_trident_pcm_pan_control_get(struct snd_kcontrol *kcontrol,
2747                                            struct snd_ctl_elem_value *ucontrol)
2748 {
2749         struct snd_trident *trident = snd_kcontrol_chip(kcontrol);
2750         struct snd_trident_pcm_mixer *mix = &trident->pcm_mixer[snd_ctl_get_ioffnum(kcontrol, &ucontrol->id)];
2751 
2752         ucontrol->value.integer.value[0] = mix->pan;
2753         if (ucontrol->value.integer.value[0] & 0x40) {
2754                 ucontrol->value.integer.value[0] = (0x3f - (ucontrol->value.integer.value[0] & 0x3f));
2755         } else {
2756                 ucontrol->value.integer.value[0] |= 0x40;
2757         }
2758         return 0;
2759 }
2760 
2761 static int snd_trident_pcm_pan_control_put(struct snd_kcontrol *kcontrol,
2762                                            struct snd_ctl_elem_value *ucontrol)
2763 {
2764         struct snd_trident *trident = snd_kcontrol_chip(kcontrol);
2765         struct snd_trident_pcm_mixer *mix = &trident->pcm_mixer[snd_ctl_get_ioffnum(kcontrol, &ucontrol->id)];
2766         unsigned char val;
2767         int change = 0;
2768 
2769         if (ucontrol->value.integer.value[0] & 0x40)
2770                 val = ucontrol->value.integer.value[0] & 0x3f;
2771         else
2772                 val = (0x3f - (ucontrol->value.integer.value[0] & 0x3f)) | 0x40;
2773         spin_lock_irq(&trident->reg_lock);
2774         change = val != mix->pan;
2775         mix->pan = val;
2776         if (mix->voice != NULL)
2777                 snd_trident_write_pan_reg(trident, mix->voice, val);
2778         spin_unlock_irq(&trident->reg_lock);
2779         return change;
2780 }
2781 
2782 static struct snd_kcontrol_new snd_trident_pcm_pan_control __devinitdata =
2783 {
2784         .iface =        SNDRV_CTL_ELEM_IFACE_MIXER,
2785         .name =         "PCM Pan Playback Control",
2786         .access =       SNDRV_CTL_ELEM_ACCESS_READWRITE | SNDRV_CTL_ELEM_ACCESS_INACTIVE,
2787         .count =        32,
2788         .info =         snd_trident_pcm_pan_control_info,
2789         .get =          snd_trident_pcm_pan_control_get,
2790         .put =          snd_trident_pcm_pan_control_put,
2791 };
2792 
2793 /*---------------------------------------------------------------------------
2794     snd_trident_pcm_rvol_control
2795 
2796     Description: PCM reverb volume control
2797   ---------------------------------------------------------------------------*/
2798 
2799 static int snd_trident_pcm_rvol_control_info(struct snd_kcontrol *kcontrol,
2800                                              struct snd_ctl_elem_info *uinfo)
2801 {
2802         uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
2803         uinfo->count = 1;
2804         uinfo->value.integer.min = 0;
2805         uinfo->value.integer.max = 127;
2806         return 0;
2807 }
2808 
2809 static int snd_trident_pcm_rvol_control_get(struct snd_kcontrol *kcontrol,
2810                                             struct snd_ctl_elem_value *ucontrol)
2811 {
2812         struct snd_trident *trident = snd_kcontrol_chip(kcontrol);
2813         struct snd_trident_pcm_mixer *mix = &trident->pcm_mixer[snd_ctl_get_ioffnum(kcontrol, &ucontrol->id)];
2814 
2815         ucontrol->value.integer.value[0] = 127 - mix->rvol;
2816         return 0;
2817 }
2818 
2819 static int snd_trident_pcm_rvol_control_put(struct snd_kcontrol *kcontrol,
2820                                             struct snd_ctl_elem_value *ucontrol)
2821 {
2822         struct snd_trident *trident = snd_kcontrol_chip(kcontrol);
2823         struct snd_trident_pcm_mixer *mix = &trident->pcm_mixer[snd_ctl_get_ioffnum(kcontrol, &ucontrol->id)];
2824         unsigned short val;
2825         int change = 0;
2826 
2827         val = 0x7f - (ucontrol->value.integer.value[0] & 0x7f);
2828         spin_lock_irq(&trident->reg_lock);
2829         change = val != mix->rvol;
2830         mix->rvol = val;
2831         if (mix->voice != NULL)
2832                 snd_trident_write_rvol_reg(trident, mix->voice, val);
2833         spin_unlock_irq(&trident->reg_lock);
2834         return change;
2835 }
2836 
2837 static const DECLARE_TLV_DB_SCALE(db_scale_crvol, -3175, 25, 1);
2838 
2839 static struct snd_kcontrol_new snd_trident_pcm_rvol_control __devinitdata =
2840 {
2841         .iface =        SNDRV_CTL_ELEM_IFACE_MIXER,
2842         .name =         "PCM Reverb Playback Volume",
2843         .access =       SNDRV_CTL_ELEM_ACCESS_READWRITE | SNDRV_CTL_ELEM_ACCESS_INACTIVE,
2844         .count =        32,
2845         .info =         snd_trident_pcm_rvol_control_info,
2846         .get =          snd_trident_pcm_rvol_control_get,
2847         .put =          snd_trident_pcm_rvol_control_put,
2848         .tlv = { .p = db_scale_crvol },
2849 };
2850 
2851 /*---------------------------------------------------------------------------
2852     snd_trident_pcm_cvol_control
2853 
2854     Description: PCM chorus volume control
2855   ---------------------------------------------------------------------------*/
2856 
2857 static int snd_trident_pcm_cvol_control_info(struct snd_kcontrol *kcontrol,
2858                                              struct snd_ctl_elem_info *uinfo)
2859 {
2860         uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
2861         uinfo->count = 1;
2862         uinfo->value.integer.min = 0;
2863         uinfo->value.integer.max = 127;
2864         return 0;
2865 }
2866 
2867 static int snd_trident_pcm_cvol_control_get(struct snd_kcontrol *kcontrol,
2868                                             struct snd_ctl_elem_value *ucontrol)
2869 {
2870         struct snd_trident *trident = snd_kcontrol_chip(kcontrol);
2871         struct snd_trident_pcm_mixer *mix = &trident->pcm_mixer[snd_ctl_get_ioffnum(kcontrol, &ucontrol->id)];
2872 
2873         ucontrol->value.integer.value[0] = 127 - mix->cvol;
2874         return 0;
2875 }
2876 
2877 static int snd_trident_pcm_cvol_control_put(struct snd_kcontrol *kcontrol,
2878                                             struct snd_ctl_elem_value *ucontrol)
2879 {
2880         struct snd_trident *trident = snd_kcontrol_chip(kcontrol);
2881         struct snd_trident_pcm_mixer *mix = &trident->pcm_mixer[snd_ctl_get_ioffnum(kcontrol, &ucontrol->id)];
2882         unsigned short val;
2883         int change = 0;
2884 
2885         val = 0x7f - (ucontrol->value.integer.value[0] & 0x7f);
2886         spin_lock_irq(&trident->reg_lock);
2887         change = val != mix->cvol;
2888         mix->cvol = val;
2889         if (mix->voice != NULL)
2890                 snd_trident_write_cvol_reg(trident, mix->voice, val);
2891         spin_unlock_irq(&trident->reg_lock);
2892         return change;
2893 }
2894 
2895 static struct snd_kcontrol_new snd_trident_pcm_cvol_control __devinitdata =
2896 {
2897         .iface =        SNDRV_CTL_ELEM_IFACE_MIXER,
2898         .name =         "PCM Chorus Playback Volume",
2899         .access =       SNDRV_CTL_ELEM_ACCESS_READWRITE | SNDRV_CTL_ELEM_ACCESS_INACTIVE,
2900         .count =        32,
2901         .info =         snd_trident_pcm_cvol_control_info,
2902         .get =          snd_trident_pcm_cvol_control_get,
2903         .put =          snd_trident_pcm_cvol_control_put,
2904         .tlv = { .p = db_scale_crvol },
2905 };
2906 
2907 static void snd_trident_notify_pcm_change1(struct snd_card *card,
2908                                            struct snd_kcontrol *kctl,
2909                                            int num, int activate)
2910 {
2911         struct snd_ctl_elem_id id;
2912 
2913         if (! kctl)
2914                 return;
2915         if (activate)
2916                 kctl->vd[num].access &= ~SNDRV_CTL_ELEM_ACCESS_INACTIVE;
2917         else
2918                 kctl->vd[num].access |= SNDRV_CTL_ELEM_ACCESS_INACTIVE;
2919         snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_VALUE |
2920                        SNDRV_CTL_EVENT_MASK_INFO,
2921                        snd_ctl_build_ioff(&id, kctl, num));
2922 }
2923 
2924 static void snd_trident_notify_pcm_change(struct snd_trident *trident,
2925                                           struct snd_trident_pcm_mixer *tmix,
2926                                           int num, int activate)
2927 {
2928         snd_trident_notify_pcm_change1(trident->card, trident->ctl_vol, num, activate);
2929         snd_trident_notify_pcm_change1(trident->card, trident->ctl_pan, num, activate);
2930         snd_trident_notify_pcm_change1(trident->card, trident->ctl_rvol, num, activate);
2931         snd_trident_notify_pcm_change1(trident->card, trident->ctl_cvol, num, activate);
2932 }
2933 
2934 static int snd_trident_pcm_mixer_build(struct snd_trident *trident,
2935                                        struct snd_trident_voice *voice,
2936                                        struct snd_pcm_substream *substream)
2937 {
2938         struct snd_trident_pcm_mixer *tmix;
2939 
2940         if (snd_BUG_ON(!trident || !voice || !substream))
2941                 return -EINVAL;
2942         tmix = &trident->pcm_mixer[substream->number];
2943         tmix->voice = voice;
2944         tmix->vol = T4D_DEFAULT_PCM_VOL;
2945         tmix->pan = T4D_DEFAULT_PCM_PAN;
2946         tmix->rvol = T4D_DEFAULT_PCM_RVOL;
2947         tmix->cvol = T4D_DEFAULT_PCM_CVOL;
2948         snd_trident_notify_pcm_change(trident, tmix, substream->number, 1);
2949         return 0;
2950 }
2951 
2952 static int snd_trident_pcm_mixer_free(struct snd_trident *trident, struct snd_trident_voice *voice, struct snd_pcm_substream *substream)
2953 {
2954         struct snd_trident_pcm_mixer *tmix;
2955 
2956         if (snd_BUG_ON(!trident || !substream))
2957                 return -EINVAL;
2958         tmix = &trident->pcm_mixer[substream->number];
2959         tmix->voice = NULL;
2960         snd_trident_notify_pcm_change(trident, tmix, substream->number, 0);
2961         return 0;
2962 }
2963 
2964 /*---------------------------------------------------------------------------
2965    snd_trident_mixer
2966   
2967    Description: This routine registers the 4DWave device for mixer support.
2968                 
2969    Parameters:  trident - pointer to target device class for 4DWave.
2970 
2971    Returns:     None
2972   
2973   ---------------------------------------------------------------------------*/
2974 
2975 static int __devinit snd_trident_mixer(struct snd_trident * trident, int pcm_spdif_device)
2976 {
2977         struct snd_ac97_template _ac97;
2978         struct snd_card *card = trident->card;
2979         struct snd_kcontrol *kctl;
2980         struct snd_ctl_elem_value *uctl;
2981         int idx, err, retries = 2;
2982         static struct snd_ac97_bus_ops ops = {
2983                 .write = snd_trident_codec_write,
2984                 .read = snd_trident_codec_read,
2985         };
2986 
2987         uctl = kzalloc(sizeof(*uctl), GFP_KERNEL);
2988         if (!uctl)
2989                 return -ENOMEM;
2990 
2991         if ((err = snd_ac97_bus(trident->card, 0, &ops, NULL, &trident->ac97_bus)) < 0)
2992                 goto __out;
2993 
2994         memset(&_ac97, 0, sizeof(_ac97));
2995         _ac97.private_data = trident;
2996         trident->ac97_detect = 1;
2997 
2998       __again:
2999         if ((err = snd_ac97_mixer(trident->ac97_bus, &_ac97, &trident->ac97)) < 0) {
3000                 if (trident->device == TRIDENT_DEVICE_ID_SI7018) {
3001                         if ((err = snd_trident_sis_reset(trident)) < 0)
3002                                 goto __out;
3003                         if (retries-- > 0)
3004                                 goto __again;
3005                         err = -EIO;
3006                 }
3007                 goto __out;
3008         }
3009         
3010         /* secondary codec? */
3011         if (trident->device == TRIDENT_DEVICE_ID_SI7018 &&
3012             (inl(TRID_REG(trident, SI_SERIAL_INTF_CTRL)) & SI_AC97_PRIMARY_READY) != 0) {
3013                 _ac97.num = 1;
3014                 err = snd_ac97_mixer(trident->ac97_bus, &_ac97, &trident->ac97_sec);
3015                 if (err < 0)
3016                         snd_printk(KERN_ERR "SI7018: the secondary codec - invalid access\n");
3017 #if 0   // only for my testing purpose --jk
3018                 {
3019                         struct snd_ac97 *mc97;
3020                         err = snd_ac97_modem(trident->card, &_ac97, &mc97);
3021                         if (err < 0)
3022                                 snd_printk(KERN_ERR "snd_ac97_modem returned error %i\n", err);
3023                 }
3024 #endif
3025         }
3026         
3027         trident->ac97_detect = 0;
3028 
3029         if (trident->device != TRIDENT_DEVICE_ID_SI7018) {
3030                 if ((err = snd_ctl_add(card, kctl = snd_ctl_new1(&snd_trident_vol_wave_control, trident))) < 0)
3031                         goto __out;
3032                 kctl->put(kctl, uctl);
3033                 if ((err = snd_ctl_add(card, kctl = snd_ctl_new1(&snd_trident_vol_music_control, trident))) < 0)
3034                         goto __out;
3035                 kctl->put(kctl, uctl);
3036                 outl(trident->musicvol_wavevol = 0x00000000, TRID_REG(trident, T4D_MUSICVOL_WAVEVOL));
3037         } else {
3038                 outl(trident->musicvol_wavevol = 0xffff0000, TRID_REG(trident, T4D_MUSICVOL_WAVEVOL));
3039         }
3040 
3041         for (idx = 0; idx < 32; idx++) {
3042                 struct snd_trident_pcm_mixer *tmix;
3043                 
3044                 tmix = &trident->pcm_mixer[idx];
3045                 tmix->voice = NULL;
3046         }
3047         if ((trident->ctl_vol = snd_ctl_new1(&snd_trident_pcm_vol_control, trident)) == NULL)
3048                 goto __nomem;
3049         if ((err = snd_ctl_add(card, trident->ctl_vol)))
3050                 goto __out;
3051                 
3052         if ((trident->ctl_pan = snd_ctl_new1(&snd_trident_pcm_pan_control, trident)) == NULL)
3053                 goto __nomem;
3054         if ((err = snd_ctl_add(card, trident->ctl_pan)))
3055                 goto __out;
3056 
3057         if ((trident->ctl_rvol = snd_ctl_new1(&snd_trident_pcm_rvol_control, trident)) == NULL)
3058                 goto __nomem;
3059         if ((err = snd_ctl_add(card, trident->ctl_rvol)))
3060                 goto __out;
3061 
3062         if ((trident->ctl_cvol = snd_ctl_new1(&snd_trident_pcm_cvol_control, trident)) == NULL)
3063                 goto __nomem;
3064         if ((err = snd_ctl_add(card, trident->ctl_cvol)))
3065                 goto __out;
3066 
3067         if (trident->device == TRIDENT_DEVICE_ID_NX) {
3068                 if ((err = snd_ctl_add(card, kctl = snd_ctl_new1(&snd_trident_ac97_rear_control, trident))) < 0)
3069                         goto __out;
3070                 kctl->put(kctl, uctl);
3071         }
3072         if (trident->device == TRIDENT_DEVICE_ID_NX || trident->device == TRIDENT_DEVICE_ID_SI7018) {
3073 
3074                 kctl = snd_ctl_new1(&snd_trident_spdif_control, trident);
3075                 if (kctl == NULL) {
3076                         err = -ENOMEM;
3077                         goto __out;
3078                 }
3079                 if (trident->ac97->ext_id & AC97_EI_SPDIF)
3080                         kctl->id.index++;
3081                 if (trident->ac97_sec && (trident->ac97_sec->ext_id & AC97_EI_SPDIF))
3082                         kctl->id.index++;
3083                 idx = kctl->id.index;
3084                 if ((err = snd_ctl_add(card, kctl)) < 0)
3085                         goto __out;
3086                 kctl->put(kctl, uctl);
3087 
3088                 kctl = snd_ctl_new1(&snd_trident_spdif_default, trident);
3089                 if (kctl == NULL) {
3090                         err = -ENOMEM;
3091                         goto __out;
3092                 }
3093                 kctl->id.index = idx;
3094                 kctl->id.device = pcm_spdif_device;
3095                 if ((err = snd_ctl_add(card, kctl)) < 0)
3096                         goto __out;
3097 
3098                 kctl = snd_ctl_new1(&snd_trident_spdif_mask, trident);
3099                 if (kctl == NULL) {
3100                         err = -ENOMEM;
3101                         goto __out;
3102                 }
3103                 kctl->id.index = idx;
3104                 kctl->id.device = pcm_spdif_device;
3105                 if ((err = snd_ctl_add(card, kctl)) < 0)
3106                         goto __out;
3107 
3108                 kctl = snd_ctl_new1(&snd_trident_spdif_stream, trident);
3109                 if (kctl == NULL) {
3110                         err = -ENOMEM;
3111                         goto __out;
3112                 }
3113                 kctl->id.index = idx;
3114                 kctl->id.device = pcm_spdif_device;
3115                 if ((err = snd_ctl_add(card, kctl)) < 0)
3116                         goto __out;
3117                 trident->spdif_pcm_ctl = kctl;
3118         }
3119 
3120         err = 0;
3121         goto __out;
3122 
3123  __nomem:
3124         err = -ENOMEM;
3125 
3126  __out:
3127         kfree(uctl);
3128 
3129         return err;
3130 }
3131 
3132 /*
3133  * gameport interface
3134  */
3135 
3136 #if defined(CONFIG_GAMEPORT) || (defined(MODULE) && defined(CONFIG_GAMEPORT_MODULE))
3137 
3138 static unsigned char snd_trident_gameport_read(struct gameport *gameport)
3139 {
3140         struct snd_trident *chip = gameport_get_port_data(gameport);
3141 
3142         if (snd_BUG_ON(!chip))
3143                 return 0;
3144         return inb(TRID_REG(chip, GAMEPORT_LEGACY));
3145 }
3146 
3147 static void snd_trident_gameport_trigger(struct gameport *gameport)
3148 {
3149         struct snd_trident *chip = gameport_get_port_data(gameport);
3150 
3151         if (snd_BUG_ON(!chip))
3152                 return;
3153         outb(0xff, TRID_REG(chip, GAMEPORT_LEGACY));
3154 }
3155 
3156 static int snd_trident_gameport_cooked_read(struct gameport *gameport, int *axes, int *buttons)
3157 {
3158         struct snd_trident *chip = gameport_get_port_data(gameport);
3159         int i;
3160 
3161         if (snd_BUG_ON(!chip))
3162                 return 0;
3163 
3164         *buttons = (~inb(TRID_REG(chip, GAMEPORT_LEGACY)) >> 4) & 0xf;
3165 
3166         for (i = 0; i < 4; i++) {
3167                 axes[i] = inw(TRID_REG(chip, GAMEPORT_AXES + i * 2));
3168                 if (axes[i] == 0xffff) axes[i] = -1;
3169         }
3170         
3171         return 0;
3172 }
3173 
3174 static int snd_trident_gameport_open(struct gameport *gameport, int mode)
3175 {
3176         struct snd_trident *chip = gameport_get_port_data(gameport);
3177 
3178         if (snd_BUG_ON(!chip))
3179                 return 0;
3180 
3181         switch (mode) {
3182                 case GAMEPORT_MODE_COOKED:
3183                         outb(GAMEPORT_MODE_ADC, TRID_REG(chip, GAMEPORT_GCR));
3184                         msleep(20);
3185                         return 0;
3186                 case GAMEPORT_MODE_RAW:
3187                         outb(0, TRID_REG(chip, GAMEPORT_GCR));
3188                         return 0;
3189                 default:
3190                         return -1;
3191         }
3192 }
3193 
3194 int __devinit snd_trident_create_gameport(struct snd_trident *chip)
3195 {
3196         struct gameport *gp;
3197 
3198         chip->gameport = gp = gameport_allocate_port();
3199         if (!gp) {
3200                 printk(KERN_ERR "trident: cannot allocate memory for gameport\n");
3201                 return -ENOMEM;
3202         }
3203 
3204         gameport_set_name(gp, "Trident 4DWave");
3205         gameport_set_phys(gp, "pci%s/gameport0", pci_name(chip->pci));
3206         gameport_set_dev_parent(gp, &chip->pci->dev);
3207 
3208         gameport_set_port_data(gp, chip);
3209         gp->fuzz = 64;
3210         gp->read = snd_trident_gameport_read;
3211         gp->trigger = snd_trident_gameport_trigger;
3212         gp->cooked_read = snd_trident_gameport_cooked_read;
3213         gp->open = snd_trident_gameport_open;
3214 
3215         gameport_register_port(gp);
3216 
3217         return 0;
3218 }
3219 
3220 static inline void snd_trident_free_gameport(struct snd_trident *chip)
3221 {
3222         if (chip->gameport) {
3223                 gameport_unregister_port(chip->gameport);
3224                 chip->gameport = NULL;
3225         }
3226 }
3227 #else
3228 int __devinit snd_trident_create_gameport(struct snd_trident *chip) { return -ENOSYS; }
3229 static inline void snd_trident_free_gameport(struct snd_trident *chip) { }
3230 #endif /* CONFIG_GAMEPORT */
3231 
3232 /*
3233  * delay for 1 tick
3234  */
3235 static inline void do_delay(struct snd_trident *chip)
3236 {
3237         schedule_timeout_uninterruptible(1);
3238 }
3239 
3240 /*
3241  *  SiS reset routine
3242  */
3243 
3244 static int snd_trident_sis_reset(struct snd_trident *trident)
3245 {
3246         unsigned long end_time;
3247         unsigned int i;
3248         int r;
3249 
3250         r = trident->in_suspend ? 0 : 2;        /* count of retries */
3251       __si7018_retry:
3252         pci_write_config_byte(trident->pci, 0x46, 0x04);        /* SOFTWARE RESET */
3253         udelay(100);
3254         pci_write_config_byte(trident->pci, 0x46, 0x00);
3255         udelay(100);
3256         /* disable AC97 GPIO interrupt */
3257         outb(0x00, TRID_REG(trident, SI_AC97_GPIO));
3258         /* initialize serial interface, force cold reset */
3259         i = PCMOUT|SURROUT|CENTEROUT|LFEOUT|SECONDARY_ID|COLD_RESET;
3260         outl(i, TRID_REG(trident, SI_SERIAL_INTF_CTRL));
3261         udelay(1000);
3262         /* remove cold reset */
3263         i &= ~COLD_RESET;
3264         outl(i, TRID_REG(trident, SI_SERIAL_INTF_CTRL));
3265         udelay(2000);
3266         /* wait, until the codec is ready */
3267         end_time = (jiffies + (HZ * 3) / 4) + 1;
3268         do {
3269                 if ((inl(TRID_REG(trident, SI_SERIAL_INTF_CTRL)) & SI_AC97_PRIMARY_READY) != 0)
3270                         goto __si7018_ok;
3271                 do_delay(trident);
3272         } while (time_after_eq(end_time, jiffies));
3273         snd_printk(KERN_ERR "AC'97 codec ready error [0x%x]\n", inl(TRID_REG(trident, SI_SERIAL_INTF_CTRL)));
3274         if (r-- > 0) {
3275                 end_time = jiffies + HZ;
3276                 do {
3277                         do_delay(trident);
3278                 } while (time_after_eq(end_time, jiffies));
3279                 goto __si7018_retry;
3280         }
3281       __si7018_ok:
3282         /* wait for the second codec */
3283         do {
3284                 if ((inl(TRID_REG(trident, SI_SERIAL_INTF_CTRL)) & SI_AC97_SECONDARY_READY) != 0)
3285                         break;
3286                 do_delay(trident);
3287         } while (time_after_eq(end_time, jiffies));
3288         /* enable 64 channel mode */
3289         outl(BANK_B_EN, TRID_REG(trident, T4D_LFO_GC_CIR));
3290         return 0;
3291 }
3292 
3293 /*  
3294  *  /proc interface
3295  */
3296 
3297 static void snd_trident_proc_read(struct snd_info_entry *entry, 
3298                                   struct snd_info_buffer *buffer)
3299 {
3300         struct snd_trident *trident = entry->private_data;
3301         char *s;
3302 
3303         switch (trident->device) {
3304         case TRIDENT_DEVICE_ID_SI7018:
3305                 s = "SiS 7018 Audio";
3306                 break;
3307         case TRIDENT_DEVICE_ID_DX:
3308                 s = "Trident 4DWave PCI DX";
3309                 break;
3310         case TRIDENT_DEVICE_ID_NX:
3311                 s = "Trident 4DWave PCI NX";
3312                 break;
3313         default:
3314                 s = "???";
3315         }
3316         snd_iprintf(buffer, "%s\n\n", s);
3317         snd_iprintf(buffer, "Spurious IRQs    : %d\n", trident->spurious_irq_count);
3318         snd_iprintf(buffer, "Spurious IRQ dlta: %d\n", trident->spurious_irq_max_delta);
3319         if (trident->device == TRIDENT_DEVICE_ID_NX || trident->device == TRIDENT_DEVICE_ID_SI7018)
3320                 snd_iprintf(buffer, "IEC958 Mixer Out : %s\n", trident->spdif_ctrl == 0x28 ? "on" : "off");
3321         if (trident->device == TRIDENT_DEVICE_ID_NX) {
3322                 snd_iprintf(buffer, "Rear Speakers    : %s\n", trident->ac97_ctrl & 0x00000010 ? "on" : "off");
3323                 if (trident->tlb.entries) {
3324                         snd_iprintf(buffer,"\nVirtual Memory\n");
3325                         snd_iprintf(buffer, "Memory Maximum : %d\n", trident->tlb.memhdr->size);
3326                         snd_iprintf(buffer, "Memory Used    : %d\n", trident->tlb.memhdr->used);
3327                         snd_iprintf(buffer, "Memory Free    : %d\n", snd_util_mem_avail(trident->tlb.memhdr));
3328                 }
3329         }
3330 }
3331 
3332 static void __devinit snd_trident_proc_init(struct snd_trident * trident)
3333 {
3334         struct snd_info_entry *entry;
3335         const char *s = "trident";
3336         
3337         if (trident->device == TRIDENT_DEVICE_ID_SI7018)
3338                 s = "sis7018";
3339         if (! snd_card_proc_new(trident->card, s, &entry))
3340                 snd_info_set_text_ops(entry, trident, snd_trident_proc_read);
3341 }
3342 
3343 static int snd_trident_dev_free(struct snd_device *device)
3344 {
3345         struct snd_trident *trident = device->device_data;
3346         return snd_trident_free(trident);
3347 }
3348 
3349 /*---------------------------------------------------------------------------
3350    snd_trident_tlb_alloc
3351   
3352    Description: Allocate and set up the TLB page table on 4D NX.
3353                 Each entry has 4 bytes (physical PCI address).
3354                 
3355    Parameters:  trident - pointer to target device class for 4DWave.
3356 
3357    Returns:     0 or negative error code
3358   
3359   ---------------------------------------------------------------------------*/
3360 
3361 static int __devinit snd_trident_tlb_alloc(struct snd_trident *trident)
3362 {
3363         int i;
3364 
3365         /* TLB array must be aligned to 16kB !!! so we allocate
3366            32kB region and correct offset when necessary */
3367 
3368         if (snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, snd_dma_pci_data(trident->pci),
3369                                 2 * SNDRV_TRIDENT_MAX_PAGES * 4, &trident->tlb.buffer) < 0) {
3370                 snd_printk(KERN_ERR "trident: unable to allocate TLB buffer\n");
3371                 return -ENOMEM;
3372         }
3373         trident->tlb.entries = (unsigned int*)ALIGN((unsigned long)trident->tlb.buffer.area, SNDRV_TRIDENT_MAX_PAGES * 4);
3374         trident->tlb.entries_dmaaddr = ALIGN(trident->tlb.buffer.addr, SNDRV_TRIDENT_MAX_PAGES * 4);
3375         /* allocate shadow TLB page table (virtual addresses) */
3376         trident->tlb.shadow_entries = vmalloc(SNDRV_TRIDENT_MAX_PAGES*sizeof(unsigned long));
3377         if (trident->tlb.shadow_entries == NULL) {
3378                 snd_printk(KERN_ERR "trident: unable to allocate shadow TLB entries\n");
3379                 return -ENOMEM;
3380         }
3381         /* allocate and setup silent page and initialise TLB entries */
3382         if (snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, snd_dma_pci_data(trident->pci),
3383                                 SNDRV_TRIDENT_PAGE_SIZE, &trident->tlb.silent_page) < 0) {
3384                 snd_printk(KERN_ERR "trident: unable to allocate silent page\n");
3385                 return -ENOMEM;
3386         }
3387         memset(trident->tlb.silent_page.area, 0, SNDRV_TRIDENT_PAGE_SIZE);
3388         for (i = 0; i < SNDRV_TRIDENT_MAX_PAGES; i++) {
3389                 trident->tlb.entries[i] = cpu_to_le32(trident->tlb.silent_page.addr & ~(SNDRV_TRIDENT_PAGE_SIZE-1));
3390                 trident->tlb.shadow_entries[i] = (unsigned long)trident->tlb.silent_page.area;
3391         }
3392 
3393         /* use emu memory block manager code to manage tlb page allocation */
3394         trident->tlb.memhdr = snd_util_memhdr_new(SNDRV_TRIDENT_PAGE_SIZE * SNDRV_TRIDENT_MAX_PAGES);
3395         if (trident->tlb.memhdr == NULL)
3396                 return -ENOMEM;
3397 
3398         trident->tlb.memhdr->block_extra_size = sizeof(struct snd_trident_memblk_arg);
3399         return 0;
3400 }
3401 
3402 /*
3403  * initialize 4D DX chip
3404  */
3405 
3406 static void snd_trident_stop_all_voices(struct snd_trident *trident)
3407 {
3408         outl(0xffffffff, TRID_REG(trident, T4D_STOP_A));
3409         outl(0xffffffff, TRID_REG(trident, T4D_STOP_B));
3410         outl(0, TRID_REG(trident, T4D_AINTEN_A));
3411         outl(0, TRID_REG(trident, T4D_AINTEN_B));
3412 }
3413 
3414 static int snd_trident_4d_dx_init(struct snd_trident *trident)
3415 {
3416         struct pci_dev *pci = trident->pci;
3417         unsigned long end_time;
3418 
3419         /* reset the legacy configuration and whole audio/wavetable block */
3420         pci_write_config_dword(pci, 0x40, 0);   /* DDMA */
3421         pci_write_config_byte(pci, 0x44, 0);    /* ports */
3422         pci_write_config_byte(pci, 0x45, 0);    /* Legacy DMA */
3423         pci_write_config_byte(pci, 0x46, 4); /* reset */
3424         udelay(100);
3425         pci_write_config_byte(pci, 0x46, 0); /* release reset */
3426         udelay(100);
3427         
3428         /* warm reset of the AC'97 codec */
3429         outl(0x00000001, TRID_REG(trident, DX_ACR2_AC97_COM_STAT));
3430         udelay(100);
3431         outl(0x00000000, TRID_REG(trident, DX_ACR2_AC97_COM_STAT));
3432         /* DAC on, disable SB IRQ and try to force ADC valid signal */
3433         trident->ac97_ctrl = 0x0000004a;
3434         outl(trident->ac97_ctrl, TRID_REG(trident, DX_ACR2_AC97_COM_STAT));
3435         /* wait, until the codec is ready */
3436         end_time = (jiffies + (HZ * 3) / 4) + 1;
3437         do {
3438                 if ((inl(TRID_REG(trident, DX_ACR2_AC97_COM_STAT)) & 0x0010) != 0)
3439                         goto __dx_ok;
3440                 do_delay(trident);
3441         } while (time_after_eq(end_time, jiffies));
3442         snd_printk(KERN_ERR "AC'97 codec ready error\n");
3443         return -EIO;
3444 
3445  __dx_ok:
3446         snd_trident_stop_all_voices(trident);
3447 
3448         return 0;
3449 }
3450 
3451 /*
3452  * initialize 4D NX chip
3453  */
3454 static int snd_trident_4d_nx_init(struct snd_trident *trident)
3455 {
3456         struct pci_dev *pci = trident->pci;
3457         unsigned long end_time;
3458 
3459         /* reset the legacy configuration and whole audio/wavetable block */
3460         pci_write_config_dword(pci, 0x40, 0);   /* DDMA */
3461         pci_write_config_byte(pci, 0x44, 0);    /* ports */
3462         pci_write_config_byte(pci, 0x45, 0);    /* Legacy DMA */
3463 
3464         pci_write_config_byte(pci, 0x46, 1); /* reset */
3465         udelay(100);
3466         pci_write_config_byte(pci, 0x46, 0); /* release reset */
3467         udelay(100);
3468 
3469         /* warm reset of the AC'97 codec */
3470         outl(0x00000001, TRID_REG(trident, NX_ACR0_AC97_COM_STAT));
3471         udelay(100);
3472         outl(0x00000000, TRID_REG(trident, NX_ACR0_AC97_COM_STAT));
3473         /* wait, until the codec is ready */
3474         end_time = (jiffies + (HZ * 3) / 4) + 1;
3475         do {
3476                 if ((inl(TRID_REG(trident, NX_ACR0_AC97_COM_STAT)) & 0x0008) != 0)
3477                         goto __nx_ok;
3478                 do_delay(trident);
3479         } while (time_after_eq(end_time, jiffies));
3480         snd_printk(KERN_ERR "AC'97 codec ready error [0x%x]\n", inl(TRID_REG(trident, NX_ACR0_AC97_COM_STAT)));
3481         return -EIO;
3482 
3483  __nx_ok:
3484         /* DAC on */
3485         trident->ac97_ctrl = 0x00000002;
3486         outl(trident->ac97_ctrl, TRID_REG(trident, NX_ACR0_AC97_COM_STAT));
3487         /* disable SB IRQ */
3488         outl(NX_SB_IRQ_DISABLE, TRID_REG(trident, T4D_MISCINT));
3489 
3490         snd_trident_stop_all_voices(trident);
3491 
3492         if (trident->tlb.entries != NULL) {
3493                 unsigned int i;
3494                 /* enable virtual addressing via TLB */
3495                 i = trident->tlb.entries_dmaaddr;
3496                 i |= 0x00000001;
3497                 outl(i, TRID_REG(trident, NX_TLBC));
3498         } else {
3499                 outl(0, TRID_REG(trident, NX_TLBC));
3500         }
3501         /* initialize S/PDIF */
3502         outl(trident->spdif_bits, TRID_REG(trident, NX_SPCSTATUS));
3503         outb(trident->spdif_ctrl, TRID_REG(trident, NX_SPCTRL_SPCSO + 3));
3504 
3505         return 0;
3506 }
3507 
3508 /*
3509  * initialize sis7018 chip
3510  */
3511 static int snd_trident_sis_init(struct snd_trident *trident)
3512 {
3513         int err;
3514 
3515         if ((err = snd_trident_sis_reset(trident)) < 0)
3516                 return err;
3517 
3518         snd_trident_stop_all_voices(trident);
3519 
3520         /* initialize S/PDIF */
3521         outl(trident->spdif_bits, TRID_REG(trident, SI_SPDIF_CS));
3522 
3523         return 0;
3524 }
3525 
3526 /*---------------------------------------------------------------------------
3527    snd_trident_create
3528   
3529    Description: This routine will create the device specific class for
3530                 the 4DWave card. It will also perform basic initialization.
3531                 
3532    Parameters:  card  - which card to create
3533                 pci   - interface to PCI bus resource info
3534                 dma1ptr - playback dma buffer
3535                 dma2ptr - capture dma buffer
3536                 irqptr  -  interrupt resource info
3537 
3538    Returns:     4DWave device class private data
3539   
3540   ---------------------------------------------------------------------------*/
3541 
3542 int __devinit snd_trident_create(struct snd_card *card,
3543                        struct pci_dev *pci,
3544                        int pcm_streams,
3545                        int pcm_spdif_device,
3546                        int max_wavetable_size,
3547                        struct snd_trident ** rtrident)
3548 {
3549         struct snd_trident *trident;
3550         int i, err;
3551         struct snd_trident_voice *voice;
3552         struct snd_trident_pcm_mixer *tmix;
3553         static struct snd_device_ops ops = {
3554                 .dev_free =     snd_trident_dev_free,
3555         };
3556 
3557         *rtrident = NULL;
3558 
3559         /* enable PCI device */
3560         if ((err = pci_enable_device(pci)) < 0)
3561                 return err;
3562         /* check, if we can restrict PCI DMA transfers to 30 bits */
3563         if (pci_set_dma_mask(pci, DMA_BIT_MASK(30)) < 0 ||
3564             pci_set_consistent_dma_mask(pci, DMA_BIT_MASK(30)) < 0) {
3565                 snd_printk(KERN_ERR "architecture does not support 30bit PCI busmaster DMA\n");
3566                 pci_disable_device(pci);
3567                 return -ENXIO;
3568         }
3569         
3570         trident = kzalloc(sizeof(*trident), GFP_KERNEL);
3571         if (trident == NULL) {
3572                 pci_disable_device(pci);
3573                 return -ENOMEM;
3574         }
3575         trident->device = (pci->vendor << 16) | pci->device;
3576         trident->card = card;
3577         trident->pci = pci;
3578         spin_lock_init(&trident->reg_lock);
3579         spin_lock_init(&trident->event_lock);
3580         spin_lock_init(&trident->voice_alloc);
3581         if (pcm_streams < 1)
3582                 pcm_streams = 1;
3583         if (pcm_streams > 32)
3584                 pcm_streams = 32;
3585         trident->ChanPCM = pcm_streams;
3586         if (max_wavetable_size < 0 )
3587                 max_wavetable_size = 0;
3588         trident->synth.max_size = max_wavetable_size * 1024;
3589         trident->irq = -1;
3590 
3591         trident->midi_port = TRID_REG(trident, T4D_MPU401_BASE);
3592         pci_set_master(pci);
3593 
3594         if ((err = pci_request_regions(pci, "Trident Audio")) < 0) {
3595                 kfree(trident);
3596                 pci_disable_device(pci);
3597                 return err;
3598         }
3599         trident->port = pci_resource_start(pci, 0);
3600 
3601         if (request_irq(pci->irq, snd_trident_interrupt, IRQF_SHARED,
3602                         KBUILD_MODNAME, trident)) {
3603                 snd_printk(KERN_ERR "unable to grab IRQ %d\n", pci->irq);
3604                 snd_trident_free(trident);
3605                 return -EBUSY;
3606         }
3607         trident->irq = pci->irq;
3608 
3609         /* allocate 16k-aligned TLB for NX cards */
3610         trident->tlb.entries = NULL;
3611         trident->tlb.buffer.area = NULL;
3612         if (trident->device == TRIDENT_DEVICE_ID_NX) {
3613                 if ((err = snd_trident_tlb_alloc(trident)) < 0) {
3614                         snd_trident_free(trident);
3615                         return err;
3616                 }
3617         }
3618 
3619         trident->spdif_bits = trident->spdif_pcm_bits = SNDRV_PCM_DEFAULT_CON_SPDIF;
3620 
3621         /* initialize chip */
3622         switch (trident->device) {
3623         case TRIDENT_DEVICE_ID_DX:
3624                 err = snd_trident_4d_dx_init(trident);
3625                 break;
3626         case TRIDENT_DEVICE_ID_NX:
3627                 err = snd_trident_4d_nx_init(trident);
3628                 break;
3629         case TRIDENT_DEVICE_ID_SI7018:
3630                 err = snd_trident_sis_init(trident);
3631                 break;
3632         default:
3633                 snd_BUG();
3634                 break;
3635         }
3636         if (err < 0) {
3637                 snd_trident_free(trident);
3638                 return err;
3639         }
3640 
3641         if ((err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, trident, &ops)) < 0) {
3642                 snd_trident_free(trident);
3643                 return err;
3644         }
3645 
3646         if ((err = snd_trident_mixer(trident, pcm_spdif_device)) < 0)
3647                 return err;
3648         
3649         /* initialise synth voices */
3650         for (i = 0; i < 64; i++) {
3651                 voice = &trident->synth.voices[i];
3652                 voice->number = i;
3653                 voice->trident = trident;
3654         }
3655         /* initialize pcm mixer entries */
3656         for (i = 0; i < 32; i++) {
3657                 tmix = &trident->pcm_mixer[i];
3658                 tmix->vol = T4D_DEFAULT_PCM_VOL;
3659                 tmix->pan = T4D_DEFAULT_PCM_PAN;
3660                 tmix->rvol = T4D_DEFAULT_PCM_RVOL;
3661                 tmix->cvol = T4D_DEFAULT_PCM_CVOL;
3662         }
3663 
3664         snd_trident_enable_eso(trident);
3665 
3666         snd_trident_proc_init(trident);
3667         snd_card_set_dev(card, &pci->dev);
3668         *rtrident = trident;
3669         return 0;
3670 }
3671 
3672 /*---------------------------------------------------------------------------
3673    snd_trident_free
3674   
3675    Description: This routine will free the device specific class for
3676                 the 4DWave card. 
3677                 
3678    Parameters:  trident  - device specific private data for 4DWave card
3679 
3680    Returns:     None.
3681   
3682   ---------------------------------------------------------------------------*/
3683 
3684 static int snd_trident_free(struct snd_trident *trident)
3685 {
3686         snd_trident_free_gameport(trident);
3687         snd_trident_disable_eso(trident);
3688         // Disable S/PDIF out
3689         if (trident->device == TRIDENT_DEVICE_ID_NX)
3690                 outb(0x00, TRID_REG(trident, NX_SPCTRL_SPCSO + 3));
3691         else if (trident->device == TRIDENT_DEVICE_ID_SI7018) {
3692                 outl(0, TRID_REG(trident, SI_SERIAL_INTF_CTRL));
3693         }
3694         if (trident->irq >= 0)
3695                 free_irq(trident->irq, trident);
3696         if (trident->tlb.buffer.area) {
3697                 outl(0, TRID_REG(trident, NX_TLBC));
3698                 if (trident->tlb.memhdr)
3699                         snd_util_memhdr_free(trident->tlb.memhdr);
3700                 if (trident->tlb.silent_page.area)
3701                         snd_dma_free_pages(&trident->tlb.silent_page);
3702                 vfree(trident->tlb.shadow_entries);
3703                 snd_dma_free_pages(&trident->tlb.buffer);
3704         }
3705         pci_release_regions(trident->pci);
3706         pci_disable_device(trident->pci);
3707         kfree(trident);
3708         return 0;
3709 }
3710 
3711 /*---------------------------------------------------------------------------
3712    snd_trident_interrupt
3713   
3714    Description: ISR for Trident 4DWave device
3715                 
3716    Parameters:  trident  - device specific private data for 4DWave card
3717 
3718    Problems:    It seems that Trident chips generates interrupts more than
3719                 one time in special cases. The spurious interrupts are
3720                 detected via sample timer (T4D_STIMER) and computing
3721                 corresponding delta value. The limits are detected with
3722                 the method try & fail so it is possible that it won't
3723                 work on all computers. [jaroslav]
3724 
3725    Returns:     None.
3726   
3727   ---------------------------------------------------------------------------*/
3728 
3729 static irqreturn_t snd_trident_interrupt(int irq, void *dev_id)
3730 {
3731         struct snd_trident *trident = dev_id;
3732         unsigned int audio_int, chn_int, stimer, channel, mask, tmp;
3733         int delta;
3734         struct snd_trident_voice *voice;
3735 
3736         audio_int = inl(TRID_REG(trident, T4D_MISCINT));
3737         if ((audio_int & (ADDRESS_IRQ|MPU401_IRQ)) == 0)
3738                 return IRQ_NONE;
3739         if (audio_int & ADDRESS_IRQ) {
3740                 // get interrupt status for all channels
3741                 spin_lock(&trident->reg_lock);
3742                 stimer = inl(TRID_REG(trident, T4D_STIMER)) & 0x00ffffff;
3743                 chn_int = inl(TRID_REG(trident, T4D_AINT_A));
3744                 if (chn_int == 0)
3745                         goto __skip1;
3746                 outl(chn_int, TRID_REG(trident, T4D_AINT_A));   /* ack */
3747               __skip1:
3748                 chn_int = inl(TRID_REG(trident, T4D_AINT_B));
3749                 if (chn_int == 0)
3750                         goto __skip2;
3751                 for (channel = 63; channel >= 32; channel--) {
3752                         mask = 1 << (channel&0x1f);
3753                         if ((chn_int & mask) == 0)
3754                                 continue;
3755                         voice = &trident->synth.voices[channel];
3756                         if (!voice->pcm || voice->substream == NULL) {
3757                                 outl(mask, TRID_REG(trident, T4D_STOP_B));
3758                                 continue;
3759                         }
3760                         delta = (int)stimer - (int)voice->stimer;
3761                         if (delta < 0)
3762                                 delta = -delta;
3763                         if ((unsigned int)delta < voice->spurious_threshold) {
3764                                 /* do some statistics here */
3765                                 trident->spurious_irq_count++;
3766                                 if (trident->spurious_irq_max_delta < (unsigned int)delta)
3767                                         trident->spurious_irq_max_delta = delta;
3768                                 continue;
3769                         }
3770                         voice->stimer = stimer;
3771                         if (voice->isync) {
3772                                 if (!voice->isync3) {
3773                                         tmp = inw(TRID_REG(trident, T4D_SBBL_SBCL));
3774                                         if (trident->bDMAStart & 0x40)
3775                                                 tmp >>= 1;
3776                                         if (tmp > 0)
3777                                                 tmp = voice->isync_max - tmp;
3778                                 } else {
3779                                         tmp = inl(TRID_REG(trident, NX_SPCTRL_SPCSO)) & 0x00ffffff;
3780                                 }
3781                                 if (tmp < voice->isync_mark) {
3782                                         if (tmp > 0x10)
3783                                                 tmp = voice->isync_ESO - 7;
3784                                         else
3785                                                 tmp = voice->isync_ESO + 2;
3786                                         /* update ESO for IRQ voice to preserve sync */
3787                                         snd_trident_stop_voice(trident, voice->number);
3788                                         snd_trident_write_eso_reg(trident, voice, tmp);
3789                                         snd_trident_start_voice(trident, voice->number);
3790                                 }
3791                         } else if (voice->isync2) {
3792                                 voice->isync2 = 0;
3793                                 /* write original ESO and update CSO for IRQ voice to preserve sync */
3794                                 snd_trident_stop_voice(trident, voice->number);
3795                                 snd_trident_write_cso_reg(trident, voice, voice->isync_mark);
3796                                 snd_trident_write_eso_reg(trident, voice, voice->ESO);
3797                                 snd_trident_start_voice(trident, voice->number);
3798                         }
3799 #if 0
3800                         if (voice->extra) {
3801                                 /* update CSO for extra voice to preserve sync */
3802                                 snd_trident_stop_voice(trident, voice->extra->number);
3803                                 snd_trident_write_cso_reg(trident, voice->extra, 0);
3804                                 snd_trident_start_voice(trident, voice->extra->number);
3805                         }
3806 #endif
3807                         spin_unlock(&trident->reg_lock);
3808                         snd_pcm_period_elapsed(voice->substream);
3809                         spin_lock(&trident->reg_lock);
3810                 }
3811                 outl(chn_int, TRID_REG(trident, T4D_AINT_B));   /* ack */
3812               __skip2:
3813                 spin_unlock(&trident->reg_lock);
3814         }
3815         if (audio_int & MPU401_IRQ) {
3816                 if (trident->rmidi) {
3817                         snd_mpu401_uart_interrupt(irq, trident->rmidi->private_data);
3818                 } else {
3819                         inb(TRID_REG(trident, T4D_MPUR0));
3820                 }
3821         }
3822         // outl((ST_TARGET_REACHED | MIXER_OVERFLOW | MIXER_UNDERFLOW), TRID_REG(trident, T4D_MISCINT));
3823         return IRQ_HANDLED;
3824 }
3825 
3826 struct snd_trident_voice *snd_trident_alloc_voice(struct snd_trident * trident, int type, int client, int port)
3827 {
3828         struct snd_trident_voice *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 EXPORT_SYMBOL(snd_trident_alloc_voice);
3871 
3872 void snd_trident_free_voice(struct snd_trident * trident, struct snd_trident_voice *voice)
3873 {
3874         unsigned long flags;
3875         void (*private_free)(struct snd_trident_voice *);
3876         void *private_data;
3877 
3878         if (voice == NULL || !voice->use)
3879                 return;
3880         snd_trident_clear_voices(trident, voice->number, voice->number);
3881         spin_lock_irqsave(&trident->voice_alloc, flags);
3882         private_free = voice->private_free;
3883         private_data = voice->private_data;
3884         voice->private_free = NULL;
3885         voice->private_data = NULL;
3886         if (voice->pcm)
3887                 snd_trident_free_pcm_channel(trident, voice->number);
3888         if (voice->synth)
3889                 snd_trident_free_synth_channel(trident, voice->number);
3890         voice->use = voice->pcm = voice->synth = voice->midi = 0;
3891         voice->capture = voice->spdif = 0;
3892         voice->sample_ops = NULL;
3893         voice->substream = NULL;
3894         voice->extra = NULL;
3895         spin_unlock_irqrestore(&trident->voice_alloc, flags);
3896         if (private_free)
3897                 private_free(voice);
3898 }
3899 
3900 EXPORT_SYMBOL(snd_trident_free_voice);
3901 
3902 static void snd_trident_clear_voices(struct snd_trident * trident, unsigned short v_min, unsigned short v_max)
3903 {
3904         unsigned int i, val, mask[2] = { 0, 0 };
3905 
3906         if (snd_BUG_ON(v_min > 63 || v_max > 63))
3907                 return;
3908         for (i = v_min; i <= v_max; i++)
3909                 mask[i >> 5] |= 1 << (i & 0x1f);
3910         if (mask[0]) {
3911                 outl(mask[0], TRID_REG(trident, T4D_STOP_A));
3912                 val = inl(TRID_REG(trident, T4D_AINTEN_A));
3913                 outl(val & ~mask[0], TRID_REG(trident, T4D_AINTEN_A));
3914         }
3915         if (mask[1]) {
3916                 outl(mask[1], TRID_REG(trident, T4D_STOP_B));
3917                 val = inl(TRID_REG(trident, T4D_AINTEN_B));
3918                 outl(val & ~mask[1], TRID_REG(trident, T4D_AINTEN_B));
3919         }
3920 }
3921 
3922 #ifdef CONFIG_PM
3923 int snd_trident_suspend(struct pci_dev *pci, pm_message_t state)
3924 {
3925         struct snd_card *card = pci_get_drvdata(pci);
3926         struct snd_trident *trident = card->private_data;
3927 
3928         trident->in_suspend = 1;
3929         snd_power_change_state(card, SNDRV_CTL_POWER_D3hot);
3930         snd_pcm_suspend_all(trident->pcm);
3931         snd_pcm_suspend_all(trident->foldback);
3932         snd_pcm_suspend_all(trident->spdif);
3933 
3934         snd_ac97_suspend(trident->ac97);
3935         snd_ac97_suspend(trident->ac97_sec);
3936 
3937         pci_disable_device(pci);
3938         pci_save_state(pci);
3939         pci_set_power_state(pci, pci_choose_state(pci, state));
3940         return 0;
3941 }
3942 
3943 int snd_trident_resume(struct pci_dev *pci)
3944 {
3945         struct snd_card *card = pci_get_drvdata(pci);
3946         struct snd_trident *trident = card->private_data;
3947 
3948         pci_set_power_state(pci, PCI_D0);
3949         pci_restore_state(pci);
3950         if (pci_enable_device(pci) < 0) {
3951                 printk(KERN_ERR "trident: pci_enable_device failed, "
3952                        "disabling device\n");
3953                 snd_card_disconnect(card);
3954                 return -EIO;
3955         }
3956         pci_set_master(pci);
3957 
3958         switch (trident->device) {
3959         case TRIDENT_DEVICE_ID_DX:
3960                 snd_trident_4d_dx_init(trident);
3961                 break;
3962         case TRIDENT_DEVICE_ID_NX:
3963                 snd_trident_4d_nx_init(trident);
3964                 break;
3965         case TRIDENT_DEVICE_ID_SI7018:
3966                 snd_trident_sis_init(trident);
3967                 break;
3968         }
3969 
3970         snd_ac97_resume(trident->ac97);
3971         snd_ac97_resume(trident->ac97_sec);
3972 
3973         /* restore some registers */
3974         outl(trident->musicvol_wavevol, TRID_REG(trident, T4D_MUSICVOL_WAVEVOL));
3975 
3976         snd_trident_enable_eso(trident);
3977 
3978         snd_power_change_state(card, SNDRV_CTL_POWER_D0);
3979         trident->in_suspend = 0;
3980         return 0;
3981 }
3982 #endif /* CONFIG_PM */
3983 

~ [ 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