2 * Maintained by Jaroslav Kysela <perex@suse.cz>
3 * Originated by audio@tridentmicro.com
4 * Fri Feb 19 15:55:28 MST 1999
5 * Routines for control of Trident 4DWave (DX and NX) chip
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.
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.
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
27 * SiS7018 S/PDIF support by Thomas Winischhofer <thomas@winischhofer.net>
30 #include <sound/driver.h>
31 #include <linux/delay.h>
32 #include <linux/init.h>
33 #include <linux/interrupt.h>
34 #include <linux/pci.h>
35 #include <linux/slab.h>
36 #include <linux/vmalloc.h>
37 #include <linux/gameport.h>
38 #include <linux/dma-mapping.h>
40 #include <sound/core.h>
41 #include <sound/info.h>
42 #include <sound/control.h>
43 #include <sound/trident.h>
44 #include <sound/asoundef.h>
48 static int snd_trident_pcm_mixer_build(struct snd_trident
*trident
,
49 struct snd_trident_voice
* voice
,
50 struct snd_pcm_substream
*substream
);
51 static int snd_trident_pcm_mixer_free(struct snd_trident
*trident
,
52 struct snd_trident_voice
* voice
,
53 struct snd_pcm_substream
*substream
);
54 static irqreturn_t
snd_trident_interrupt(int irq
, void *dev_id
,
55 struct pt_regs
*regs
);
56 static int snd_trident_sis_reset(struct snd_trident
*trident
);
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
);
68 static void snd_trident_print_voice_regs(struct snd_trident
*trident
, int voice
)
70 unsigned int val
, tmp
;
72 printk("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("LBA: 0x%x\n", val
);
76 val
= inl(TRID_REG(trident
, CH_GVSEL_PAN_VOL_CTRL_EC
));
77 printk("GVSel: %i\n", val
>> 31);
78 printk("Pan: 0x%x\n", (val
>> 24) & 0x7f);
79 printk("Vol: 0x%x\n", (val
>> 16) & 0xff);
80 printk("CTRL: 0x%x\n", (val
>> 12) & 0x0f);
81 printk("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("CSO: 0x%x\n", val
>> 16);
85 printk("Alpha: 0x%x\n", (val
>> 4) & 0x0fff);
86 printk("FMS: 0x%x\n", val
& 0x0f);
87 val
= inl(TRID_REG(trident
, CH_DX_ESO_DELTA
));
88 printk("ESO: 0x%x\n", val
>> 16);
89 printk("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("CSO: 0x%x\n", val
& 0x00ffffff);
95 val
= inl(TRID_REG(trident
, CH_NX_DELTA_ESO
));
96 tmp
|= (val
>> 16) & 0xff00;
97 printk("Delta: 0x%x\n", tmp
);
98 printk("ESO: 0x%x\n", val
& 0x00ffffff);
99 val
= inl(TRID_REG(trident
, CH_NX_ALPHA_FMS_FMC_RVOL_CVOL
));
100 printk("Alpha: 0x%x\n", val
>> 20);
101 printk("FMS: 0x%x\n", (val
>> 16) & 0x0f);
103 printk("FMC: 0x%x\n", (val
>> 14) & 3);
104 printk("RVol: 0x%x\n", (val
>> 7) & 0x7f);
105 printk("CVol: 0x%x\n", val
& 0x7f);
109 /*---------------------------------------------------------------------------
110 unsigned short snd_trident_codec_read(struct snd_ac97 *ac97, unsigned short reg)
112 Description: This routine will do all of the reading from the external
115 Parameters: ac97 - ac97 codec structure
116 reg - CODEC register index, from AC97 Hal.
118 returns: 16 bit value read from the AC97.
120 ---------------------------------------------------------------------------*/
121 static unsigned short snd_trident_codec_read(struct snd_ac97
*ac97
, unsigned short reg
)
123 unsigned int data
= 0, treg
;
124 unsigned short count
= 0xffff;
126 struct snd_trident
*trident
= ac97
->private_data
;
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
));
133 data
= inl(TRID_REG(trident
, DX_ACR1_AC97_R
));
134 if ((data
& DX_AC97_BUSY_READ
) == 0)
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
));
142 data
= inl(TRID_REG(trident
, treg
));
143 if ((data
& 0x00000C00) == 0)
146 } else if (trident
->device
== TRIDENT_DEVICE_ID_SI7018
) {
147 data
= SI_AC97_BUSY_READ
| SI_AC97_AUDIO_BUSY
| (reg
& 0x000000ff);
149 data
|= SI_AC97_SECONDARY
;
150 outl(data
, TRID_REG(trident
, SI_AC97_READ
));
152 data
= inl(TRID_REG(trident
, SI_AC97_READ
));
153 if ((data
& (SI_AC97_BUSY_READ
)) == 0)
158 if (count
== 0 && !trident
->ac97_detect
) {
159 snd_printk(KERN_ERR
"ac97 codec read TIMEOUT [0x%x/0x%x]!!!\n",
164 spin_unlock_irqrestore(&trident
->reg_lock
, flags
);
165 return ((unsigned short) (data
>> 16));
168 /*---------------------------------------------------------------------------
169 void snd_trident_codec_write(struct snd_ac97 *ac97, unsigned short reg,
170 unsigned short wdata)
172 Description: This routine will do all of the writing to the external
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.
179 returns: TRUE if everything went ok, else FALSE.
181 ---------------------------------------------------------------------------*/
182 static void snd_trident_codec_write(struct snd_ac97
*ac97
, unsigned short reg
,
183 unsigned short wdata
)
185 unsigned int address
, data
;
186 unsigned short count
= 0xffff;
188 struct snd_trident
*trident
= ac97
->private_data
;
190 data
= ((unsigned long) wdata
) << 16;
192 spin_lock_irqsave(&trident
->reg_lock
, flags
);
193 if (trident
->device
== TRIDENT_DEVICE_ID_DX
) {
194 address
= DX_ACR0_AC97_W
;
196 /* read AC-97 write register status */
198 if ((inw(TRID_REG(trident
, address
)) & DX_AC97_BUSY_WRITE
) == 0)
202 data
|= (DX_AC97_BUSY_WRITE
| (reg
& 0x000000ff));
203 } else if (trident
->device
== TRIDENT_DEVICE_ID_NX
) {
204 address
= NX_ACR1_AC97_W
;
206 /* read AC-97 write register status */
208 if ((inw(TRID_REG(trident
, address
)) & NX_AC97_BUSY_WRITE
) == 0)
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
;
216 /* read AC-97 write register status */
218 if ((inw(TRID_REG(trident
, address
)) & (SI_AC97_BUSY_WRITE
)) == 0)
222 data
|= SI_AC97_BUSY_WRITE
| SI_AC97_AUDIO_BUSY
| (reg
& 0x000000ff);
224 data
|= SI_AC97_SECONDARY
;
226 address
= 0; /* keep GCC happy */
227 count
= 0; /* return */
231 spin_unlock_irqrestore(&trident
->reg_lock
, flags
);
234 outl(data
, TRID_REG(trident
, address
));
235 spin_unlock_irqrestore(&trident
->reg_lock
, flags
);
238 /*---------------------------------------------------------------------------
239 void snd_trident_enable_eso(struct snd_trident *trident)
241 Description: This routine will enable end of loop interrupts.
242 End of loop interrupts will occur when a running
244 Also enables middle of loop interrupts.
246 Parameters: trident - pointer to target device class for 4DWave.
248 ---------------------------------------------------------------------------*/
250 static void snd_trident_enable_eso(struct snd_trident
* trident
)
254 val
= inl(TRID_REG(trident
, T4D_LFO_GC_CIR
));
257 if (trident
->device
== TRIDENT_DEVICE_ID_SI7018
)
259 outl(val
, TRID_REG(trident
, T4D_LFO_GC_CIR
));
262 /*---------------------------------------------------------------------------
263 void snd_trident_disable_eso(struct snd_trident *trident)
265 Description: This routine will disable end of loop interrupts.
266 End of loop interrupts will occur when a running
268 Also disables middle of loop interrupts.
271 trident - pointer to target device class for 4DWave.
273 returns: TRUE if everything went ok, else FALSE.
275 ---------------------------------------------------------------------------*/
277 static void snd_trident_disable_eso(struct snd_trident
* trident
)
281 tmp
= inl(TRID_REG(trident
, T4D_LFO_GC_CIR
));
284 outl(tmp
, TRID_REG(trident
, T4D_LFO_GC_CIR
));
287 /*---------------------------------------------------------------------------
288 void snd_trident_start_voice(struct snd_trident * trident, unsigned int voice)
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.
294 Parameters : voice - Voice number 0 thru n.
295 trident - pointer to target device class for 4DWave.
299 ---------------------------------------------------------------------------*/
301 void snd_trident_start_voice(struct snd_trident
* trident
, unsigned int voice
)
303 unsigned int mask
= 1 << (voice
& 0x1f);
304 unsigned int reg
= (voice
& 0x20) ? T4D_START_B
: T4D_START_A
;
306 outl(mask
, TRID_REG(trident
, reg
));
309 /*---------------------------------------------------------------------------
310 void snd_trident_stop_voice(struct snd_trident * trident, unsigned int voice)
312 Description: Stop a voice, any channel 0 thru 63.
313 This routine automatically handles the fact that there are
314 more than 32 channels available.
316 Parameters : voice - Voice number 0 thru n.
317 trident - pointer to target device class for 4DWave.
321 ---------------------------------------------------------------------------*/
323 void snd_trident_stop_voice(struct snd_trident
* trident
, unsigned int voice
)
325 unsigned int mask
= 1 << (voice
& 0x1f);
326 unsigned int reg
= (voice
& 0x20) ? T4D_STOP_B
: T4D_STOP_A
;
328 outl(mask
, TRID_REG(trident
, reg
));
331 /*---------------------------------------------------------------------------
332 int snd_trident_allocate_pcm_channel(struct snd_trident *trident)
334 Description: Allocate hardware channel in Bank B (32-63).
336 Parameters : trident - pointer to target device class for 4DWave.
338 Return Value: hardware channel - 32-63 or -1 when no channel is available
340 ---------------------------------------------------------------------------*/
342 static int snd_trident_allocate_pcm_channel(struct snd_trident
* trident
)
346 if (trident
->ChanPCMcnt
>= trident
->ChanPCM
)
348 for (idx
= 31; idx
>= 0; idx
--) {
349 if (!(trident
->ChanMap
[T4D_BANK_B
] & (1 << idx
))) {
350 trident
->ChanMap
[T4D_BANK_B
] |= 1 << idx
;
351 trident
->ChanPCMcnt
++;
358 /*---------------------------------------------------------------------------
359 void snd_trident_free_pcm_channel(int channel)
361 Description: Free hardware channel in Bank B (32-63)
363 Parameters : trident - pointer to target device class for 4DWave.
364 channel - hardware channel number 0-63
368 ---------------------------------------------------------------------------*/
370 static void snd_trident_free_pcm_channel(struct snd_trident
*trident
, int channel
)
372 if (channel
< 32 || channel
> 63)
375 if (trident
->ChanMap
[T4D_BANK_B
] & (1 << channel
)) {
376 trident
->ChanMap
[T4D_BANK_B
] &= ~(1 << channel
);
377 trident
->ChanPCMcnt
--;
381 /*---------------------------------------------------------------------------
382 unsigned int snd_trident_allocate_synth_channel(void)
384 Description: Allocate hardware channel in Bank A (0-31).
386 Parameters : trident - pointer to target device class for 4DWave.
388 Return Value: hardware channel - 0-31 or -1 when no channel is available
390 ---------------------------------------------------------------------------*/
392 static int snd_trident_allocate_synth_channel(struct snd_trident
* trident
)
396 for (idx
= 31; idx
>= 0; idx
--) {
397 if (!(trident
->ChanMap
[T4D_BANK_A
] & (1 << idx
))) {
398 trident
->ChanMap
[T4D_BANK_A
] |= 1 << idx
;
399 trident
->synth
.ChanSynthCount
++;
406 /*---------------------------------------------------------------------------
407 void snd_trident_free_synth_channel( int channel )
409 Description: Free hardware channel in Bank B (0-31).
411 Parameters : trident - pointer to target device class for 4DWave.
412 channel - hardware channel number 0-63
416 ---------------------------------------------------------------------------*/
418 static void snd_trident_free_synth_channel(struct snd_trident
*trident
, int channel
)
420 if (channel
< 0 || channel
> 31)
423 if (trident
->ChanMap
[T4D_BANK_A
] & (1 << channel
)) {
424 trident
->ChanMap
[T4D_BANK_A
] &= ~(1 << channel
);
425 trident
->synth
.ChanSynthCount
--;
429 /*---------------------------------------------------------------------------
430 snd_trident_write_voice_regs
432 Description: This routine will complete and write the 5 hardware channel
433 registers to hardware.
435 Paramters: trident - pointer to target device class for 4DWave.
436 voice - synthesizer voice structure
439 ---------------------------------------------------------------------------*/
441 void snd_trident_write_voice_regs(struct snd_trident
* trident
,
442 struct snd_trident_voice
* voice
)
444 unsigned int FmcRvolCvol
;
445 unsigned int regs
[5];
447 regs
[1] = voice
->LBA
;
448 regs
[4] = (voice
->GVSel
<< 31) |
449 ((voice
->Pan
& 0x0000007f) << 24) |
450 ((voice
->CTRL
& 0x0000000f) << 12);
451 FmcRvolCvol
= ((voice
->FMC
& 3) << 14) |
452 ((voice
->RVol
& 0x7f) << 7) |
453 (voice
->CVol
& 0x7f);
455 switch (trident
->device
) {
456 case TRIDENT_DEVICE_ID_SI7018
:
457 regs
[4] |= voice
->number
> 31 ?
458 (voice
->Vol
& 0x000003ff) :
459 ((voice
->Vol
& 0x00003fc) << (16-2)) |
460 (voice
->EC
& 0x00000fff);
461 regs
[0] = (voice
->CSO
<< 16) | ((voice
->Alpha
& 0x00000fff) << 4) |
462 (voice
->FMS
& 0x0000000f);
463 regs
[2] = (voice
->ESO
<< 16) | (voice
->Delta
& 0x0ffff);
464 regs
[3] = (voice
->Attribute
<< 16) | FmcRvolCvol
;
466 case TRIDENT_DEVICE_ID_DX
:
467 regs
[4] |= ((voice
->Vol
& 0x000003fc) << (16-2)) |
468 (voice
->EC
& 0x00000fff);
469 regs
[0] = (voice
->CSO
<< 16) | ((voice
->Alpha
& 0x00000fff) << 4) |
470 (voice
->FMS
& 0x0000000f);
471 regs
[2] = (voice
->ESO
<< 16) | (voice
->Delta
& 0x0ffff);
472 regs
[3] = FmcRvolCvol
;
474 case TRIDENT_DEVICE_ID_NX
:
475 regs
[4] |= ((voice
->Vol
& 0x000003fc) << (16-2)) |
476 (voice
->EC
& 0x00000fff);
477 regs
[0] = (voice
->Delta
<< 24) | (voice
->CSO
& 0x00ffffff);
478 regs
[2] = ((voice
->Delta
<< 16) & 0xff000000) |
479 (voice
->ESO
& 0x00ffffff);
480 regs
[3] = (voice
->Alpha
<< 20) |
481 ((voice
->FMS
& 0x0000000f) << 16) | FmcRvolCvol
;
488 outb(voice
->number
, TRID_REG(trident
, T4D_LFO_GC_CIR
));
489 outl(regs
[0], TRID_REG(trident
, CH_START
+ 0));
490 outl(regs
[1], TRID_REG(trident
, CH_START
+ 4));
491 outl(regs
[2], TRID_REG(trident
, CH_START
+ 8));
492 outl(regs
[3], TRID_REG(trident
, CH_START
+ 12));
493 outl(regs
[4], TRID_REG(trident
, CH_START
+ 16));
496 printk("written %i channel:\n", voice
->number
);
497 printk(" regs[0] = 0x%x/0x%x\n", regs
[0], inl(TRID_REG(trident
, CH_START
+ 0)));
498 printk(" regs[1] = 0x%x/0x%x\n", regs
[1], inl(TRID_REG(trident
, CH_START
+ 4)));
499 printk(" regs[2] = 0x%x/0x%x\n", regs
[2], inl(TRID_REG(trident
, CH_START
+ 8)));
500 printk(" regs[3] = 0x%x/0x%x\n", regs
[3], inl(TRID_REG(trident
, CH_START
+ 12)));
501 printk(" regs[4] = 0x%x/0x%x\n", regs
[4], inl(TRID_REG(trident
, CH_START
+ 16)));
505 /*---------------------------------------------------------------------------
506 snd_trident_write_cso_reg
508 Description: This routine will write the new CSO offset
509 register to hardware.
511 Paramters: trident - pointer to target device class for 4DWave.
512 voice - synthesizer voice structure
515 ---------------------------------------------------------------------------*/
517 static void snd_trident_write_cso_reg(struct snd_trident
* trident
,
518 struct snd_trident_voice
* voice
,
522 outb(voice
->number
, TRID_REG(trident
, T4D_LFO_GC_CIR
));
523 if (trident
->device
!= TRIDENT_DEVICE_ID_NX
) {
524 outw(voice
->CSO
, TRID_REG(trident
, CH_DX_CSO_ALPHA_FMS
) + 2);
526 outl((voice
->Delta
<< 24) |
527 (voice
->CSO
& 0x00ffffff), TRID_REG(trident
, CH_NX_DELTA_CSO
));
531 /*---------------------------------------------------------------------------
532 snd_trident_write_eso_reg
534 Description: This routine will write the new ESO offset
535 register to hardware.
537 Paramters: trident - pointer to target device class for 4DWave.
538 voice - synthesizer voice structure
541 ---------------------------------------------------------------------------*/
543 static void snd_trident_write_eso_reg(struct snd_trident
* trident
,
544 struct snd_trident_voice
* voice
,
548 outb(voice
->number
, TRID_REG(trident
, T4D_LFO_GC_CIR
));
549 if (trident
->device
!= TRIDENT_DEVICE_ID_NX
) {
550 outw(voice
->ESO
, TRID_REG(trident
, CH_DX_ESO_DELTA
) + 2);
552 outl(((voice
->Delta
<< 16) & 0xff000000) | (voice
->ESO
& 0x00ffffff),
553 TRID_REG(trident
, CH_NX_DELTA_ESO
));
557 /*---------------------------------------------------------------------------
558 snd_trident_write_vol_reg
560 Description: This routine will write the new voice volume
561 register to hardware.
563 Paramters: trident - pointer to target device class for 4DWave.
564 voice - synthesizer voice structure
565 Vol - new voice volume
567 ---------------------------------------------------------------------------*/
569 static void snd_trident_write_vol_reg(struct snd_trident
* trident
,
570 struct snd_trident_voice
* voice
,
574 outb(voice
->number
, TRID_REG(trident
, T4D_LFO_GC_CIR
));
575 switch (trident
->device
) {
576 case TRIDENT_DEVICE_ID_DX
:
577 case TRIDENT_DEVICE_ID_NX
:
578 outb(voice
->Vol
>> 2, TRID_REG(trident
, CH_GVSEL_PAN_VOL_CTRL_EC
+ 2));
580 case TRIDENT_DEVICE_ID_SI7018
:
581 // printk("voice->Vol = 0x%x\n", voice->Vol);
582 outw((voice
->CTRL
<< 12) | voice
->Vol
,
583 TRID_REG(trident
, CH_GVSEL_PAN_VOL_CTRL_EC
));
588 /*---------------------------------------------------------------------------
589 snd_trident_write_pan_reg
591 Description: This routine will write the new voice pan
592 register to hardware.
594 Paramters: trident - pointer to target device class for 4DWave.
595 voice - synthesizer voice structure
598 ---------------------------------------------------------------------------*/
600 static void snd_trident_write_pan_reg(struct snd_trident
* trident
,
601 struct snd_trident_voice
* voice
,
605 outb(voice
->number
, TRID_REG(trident
, T4D_LFO_GC_CIR
));
606 outb(((voice
->GVSel
& 0x01) << 7) | (voice
->Pan
& 0x7f),
607 TRID_REG(trident
, CH_GVSEL_PAN_VOL_CTRL_EC
+ 3));
610 /*---------------------------------------------------------------------------
611 snd_trident_write_rvol_reg
613 Description: This routine will write the new reverb volume
614 register to hardware.
616 Paramters: trident - pointer to target device class for 4DWave.
617 voice - synthesizer voice structure
618 RVol - new reverb volume
620 ---------------------------------------------------------------------------*/
622 static void snd_trident_write_rvol_reg(struct snd_trident
* trident
,
623 struct snd_trident_voice
* voice
,
627 outb(voice
->number
, TRID_REG(trident
, T4D_LFO_GC_CIR
));
628 outw(((voice
->FMC
& 0x0003) << 14) | ((voice
->RVol
& 0x007f) << 7) |
629 (voice
->CVol
& 0x007f),
630 TRID_REG(trident
, trident
->device
== TRIDENT_DEVICE_ID_NX
?
631 CH_NX_ALPHA_FMS_FMC_RVOL_CVOL
: CH_DX_FMC_RVOL_CVOL
));
634 /*---------------------------------------------------------------------------
635 snd_trident_write_cvol_reg
637 Description: This routine will write the new chorus volume
638 register to hardware.
640 Paramters: trident - pointer to target device class for 4DWave.
641 voice - synthesizer voice structure
642 CVol - new chorus volume
644 ---------------------------------------------------------------------------*/
646 static void snd_trident_write_cvol_reg(struct snd_trident
* trident
,
647 struct snd_trident_voice
* voice
,
651 outb(voice
->number
, TRID_REG(trident
, T4D_LFO_GC_CIR
));
652 outw(((voice
->FMC
& 0x0003) << 14) | ((voice
->RVol
& 0x007f) << 7) |
653 (voice
->CVol
& 0x007f),
654 TRID_REG(trident
, trident
->device
== TRIDENT_DEVICE_ID_NX
?
655 CH_NX_ALPHA_FMS_FMC_RVOL_CVOL
: CH_DX_FMC_RVOL_CVOL
));
658 /*---------------------------------------------------------------------------
659 snd_trident_convert_rate
661 Description: This routine converts rate in HZ to hardware delta value.
663 Paramters: trident - pointer to target device class for 4DWave.
664 rate - Real or Virtual channel number.
666 Returns: Delta value.
668 ---------------------------------------------------------------------------*/
669 static unsigned int snd_trident_convert_rate(unsigned int rate
)
673 // We special case 44100 and 8000 since rounding with the equation
674 // does not give us an accurate enough value. For 11025 and 22050
675 // the equation gives us the best answer. All other frequencies will
676 // also use the equation. JDW
679 else if (rate
== 8000)
681 else if (rate
== 48000)
684 delta
= (((rate
<< 12) + 24000) / 48000) & 0x0000ffff;
688 /*---------------------------------------------------------------------------
689 snd_trident_convert_adc_rate
691 Description: This routine converts rate in HZ to hardware delta value.
693 Paramters: trident - pointer to target device class for 4DWave.
694 rate - Real or Virtual channel number.
696 Returns: Delta value.
698 ---------------------------------------------------------------------------*/
699 static unsigned int snd_trident_convert_adc_rate(unsigned int rate
)
703 // We special case 44100 and 8000 since rounding with the equation
704 // does not give us an accurate enough value. For 11025 and 22050
705 // the equation gives us the best answer. All other frequencies will
706 // also use the equation. JDW
709 else if (rate
== 8000)
711 else if (rate
== 48000)
714 delta
= ((48000 << 12) / rate
) & 0x0000ffff;
718 /*---------------------------------------------------------------------------
719 snd_trident_spurious_threshold
721 Description: This routine converts rate in HZ to spurious threshold.
723 Paramters: trident - pointer to target device class for 4DWave.
724 rate - Real or Virtual channel number.
726 Returns: Delta value.
728 ---------------------------------------------------------------------------*/
729 static unsigned int snd_trident_spurious_threshold(unsigned int rate
,
730 unsigned int period_size
)
732 unsigned int res
= (rate
* period_size
) / 48000;
740 /*---------------------------------------------------------------------------
741 snd_trident_control_mode
743 Description: This routine returns a control mode for a PCM channel.
745 Paramters: trident - pointer to target device class for 4DWave.
746 substream - PCM substream
748 Returns: Control value.
750 ---------------------------------------------------------------------------*/
751 static unsigned int snd_trident_control_mode(struct snd_pcm_substream
*substream
)
754 struct snd_pcm_runtime
*runtime
= substream
->runtime
;
757 CTRL default: 8-bit (unsigned) mono, loop mode enabled
760 if (snd_pcm_format_width(runtime
->format
) == 16)
761 CTRL
|= 0x00000008; // 16-bit data
762 if (snd_pcm_format_signed(runtime
->format
))
763 CTRL
|= 0x00000002; // signed data
764 if (runtime
->channels
> 1)
765 CTRL
|= 0x00000004; // stereo data
773 /*---------------------------------------------------------------------------
776 Description: Device I/O control handler for playback/capture parameters.
778 Paramters: substream - PCM substream class
779 cmd - what ioctl message to process
780 arg - additional message infoarg
782 Returns: Error status
784 ---------------------------------------------------------------------------*/
786 static int snd_trident_ioctl(struct snd_pcm_substream
*substream
,
790 /* FIXME: it seems that with small periods the behaviour of
791 trident hardware is unpredictable and interrupt generator
793 return snd_pcm_lib_ioctl(substream
, cmd
, arg
);
796 /*---------------------------------------------------------------------------
797 snd_trident_allocate_pcm_mem
799 Description: Allocate PCM ring buffer for given substream
801 Parameters: substream - PCM substream class
802 hw_params - hardware parameters
804 Returns: Error status
806 ---------------------------------------------------------------------------*/
808 static int snd_trident_allocate_pcm_mem(struct snd_pcm_substream
*substream
,
809 struct snd_pcm_hw_params
*hw_params
)
811 struct snd_trident
*trident
= snd_pcm_substream_chip(substream
);
812 struct snd_pcm_runtime
*runtime
= substream
->runtime
;
813 struct snd_trident_voice
*voice
= runtime
->private_data
;
816 if ((err
= snd_pcm_lib_malloc_pages(substream
, params_buffer_bytes(hw_params
))) < 0)
818 if (trident
->tlb
.entries
) {
819 if (err
> 0) { /* change */
821 snd_trident_free_pages(trident
, voice
->memblk
);
822 voice
->memblk
= snd_trident_alloc_pages(trident
, substream
);
823 if (voice
->memblk
== NULL
)
830 /*---------------------------------------------------------------------------
831 snd_trident_allocate_evoice
833 Description: Allocate extra voice as interrupt generator
835 Parameters: substream - PCM substream class
836 hw_params - hardware parameters
838 Returns: Error status
840 ---------------------------------------------------------------------------*/
842 static int snd_trident_allocate_evoice(struct snd_pcm_substream
*substream
,
843 struct snd_pcm_hw_params
*hw_params
)
845 struct snd_trident
*trident
= snd_pcm_substream_chip(substream
);
846 struct snd_pcm_runtime
*runtime
= substream
->runtime
;
847 struct snd_trident_voice
*voice
= runtime
->private_data
;
848 struct snd_trident_voice
*evoice
= voice
->extra
;
850 /* voice management */
852 if (params_buffer_size(hw_params
) / 2 != params_period_size(hw_params
)) {
853 if (evoice
== NULL
) {
854 evoice
= snd_trident_alloc_voice(trident
, SNDRV_TRIDENT_VOICE_TYPE_PCM
, 0, 0);
857 voice
->extra
= evoice
;
858 evoice
->substream
= substream
;
861 if (evoice
!= NULL
) {
862 snd_trident_free_voice(trident
, evoice
);
863 voice
->extra
= evoice
= NULL
;
870 /*---------------------------------------------------------------------------
871 snd_trident_hw_params
873 Description: Set the hardware parameters for the playback device.
875 Parameters: substream - PCM substream class
876 hw_params - hardware parameters
878 Returns: Error status
880 ---------------------------------------------------------------------------*/
882 static int snd_trident_hw_params(struct snd_pcm_substream
*substream
,
883 struct snd_pcm_hw_params
*hw_params
)
887 err
= snd_trident_allocate_pcm_mem(substream
, hw_params
);
889 err
= snd_trident_allocate_evoice(substream
, hw_params
);
893 /*---------------------------------------------------------------------------
894 snd_trident_playback_hw_free
896 Description: Release the hardware resources for the playback device.
898 Parameters: substream - PCM substream class
900 Returns: Error status
902 ---------------------------------------------------------------------------*/
904 static int snd_trident_hw_free(struct snd_pcm_substream
*substream
)
906 struct snd_trident
*trident
= snd_pcm_substream_chip(substream
);
907 struct snd_pcm_runtime
*runtime
= substream
->runtime
;
908 struct snd_trident_voice
*voice
= runtime
->private_data
;
909 struct snd_trident_voice
*evoice
= voice
? voice
->extra
: NULL
;
911 if (trident
->tlb
.entries
) {
912 if (voice
&& voice
->memblk
) {
913 snd_trident_free_pages(trident
, voice
->memblk
);
914 voice
->memblk
= NULL
;
917 snd_pcm_lib_free_pages(substream
);
918 if (evoice
!= NULL
) {
919 snd_trident_free_voice(trident
, evoice
);
925 /*---------------------------------------------------------------------------
926 snd_trident_playback_prepare
928 Description: Prepare playback device for playback.
930 Parameters: substream - PCM substream class
932 Returns: Error status
934 ---------------------------------------------------------------------------*/
936 static int snd_trident_playback_prepare(struct snd_pcm_substream
*substream
)
938 struct snd_trident
*trident
= snd_pcm_substream_chip(substream
);
939 struct snd_pcm_runtime
*runtime
= substream
->runtime
;
940 struct snd_trident_voice
*voice
= runtime
->private_data
;
941 struct snd_trident_voice
*evoice
= voice
->extra
;
942 struct snd_trident_pcm_mixer
*mix
= &trident
->pcm_mixer
[substream
->number
];
944 spin_lock_irq(&trident
->reg_lock
);
946 /* set delta (rate) value */
947 voice
->Delta
= snd_trident_convert_rate(runtime
->rate
);
948 voice
->spurious_threshold
= snd_trident_spurious_threshold(runtime
->rate
, runtime
->period_size
);
950 /* set Loop Begin Address */
952 voice
->LBA
= voice
->memblk
->offset
;
954 voice
->LBA
= runtime
->dma_addr
;
957 voice
->ESO
= runtime
->buffer_size
- 1; /* in samples */
958 voice
->CTRL
= snd_trident_control_mode(substream
);
964 voice
->Vol
= mix
->vol
;
965 voice
->RVol
= mix
->rvol
;
966 voice
->CVol
= mix
->cvol
;
967 voice
->Pan
= mix
->pan
;
968 voice
->Attribute
= 0;
970 voice
->Attribute
= (1<<(30-16))|(2<<(26-16))|
971 (0<<(24-16))|(0x1f<<(19-16));
973 voice
->Attribute
= 0;
976 snd_trident_write_voice_regs(trident
, voice
);
978 if (evoice
!= NULL
) {
979 evoice
->Delta
= voice
->Delta
;
980 evoice
->spurious_threshold
= voice
->spurious_threshold
;
981 evoice
->LBA
= voice
->LBA
;
983 evoice
->ESO
= (runtime
->period_size
* 2) + 4 - 1; /* in samples */
984 evoice
->CTRL
= voice
->CTRL
;
986 evoice
->GVSel
= trident
->device
== TRIDENT_DEVICE_ID_SI7018
? 0 : 1;
990 evoice
->Vol
= 0x3ff; /* mute */
991 evoice
->RVol
= evoice
->CVol
= 0x7f; /* mute */
992 evoice
->Pan
= 0x7f; /* mute */
994 evoice
->Attribute
= (1<<(30-16))|(2<<(26-16))|
995 (0<<(24-16))|(0x1f<<(19-16));
997 evoice
->Attribute
= 0;
999 snd_trident_write_voice_regs(trident
, evoice
);
1001 evoice
->isync_mark
= runtime
->period_size
;
1002 evoice
->ESO
= (runtime
->period_size
* 2) - 1;
1005 spin_unlock_irq(&trident
->reg_lock
);
1010 /*---------------------------------------------------------------------------
1011 snd_trident_capture_hw_params
1013 Description: Set the hardware parameters for the capture device.
1015 Parameters: substream - PCM substream class
1016 hw_params - hardware parameters
1018 Returns: Error status
1020 ---------------------------------------------------------------------------*/
1022 static int snd_trident_capture_hw_params(struct snd_pcm_substream
*substream
,
1023 struct snd_pcm_hw_params
*hw_params
)
1025 return snd_trident_allocate_pcm_mem(substream
, hw_params
);
1028 /*---------------------------------------------------------------------------
1029 snd_trident_capture_prepare
1031 Description: Prepare capture device for playback.
1033 Parameters: substream - PCM substream class
1035 Returns: Error status
1037 ---------------------------------------------------------------------------*/
1039 static int snd_trident_capture_prepare(struct snd_pcm_substream
*substream
)
1041 struct snd_trident
*trident
= snd_pcm_substream_chip(substream
);
1042 struct snd_pcm_runtime
*runtime
= substream
->runtime
;
1043 struct snd_trident_voice
*voice
= runtime
->private_data
;
1044 unsigned int val
, ESO_bytes
;
1046 spin_lock_irq(&trident
->reg_lock
);
1048 // Initilize the channel and set channel Mode
1049 outb(0, TRID_REG(trident
, LEGACY_DMAR15
));
1051 // Set DMA channel operation mode register
1052 outb(0x54, TRID_REG(trident
, LEGACY_DMAR11
));
1054 // Set channel buffer Address, DMAR0 expects contiguous PCI memory area
1055 voice
->LBA
= runtime
->dma_addr
;
1056 outl(voice
->LBA
, TRID_REG(trident
, LEGACY_DMAR0
));
1058 voice
->LBA
= voice
->memblk
->offset
;
1061 ESO_bytes
= snd_pcm_lib_buffer_bytes(substream
) - 1;
1062 outb((ESO_bytes
& 0x00ff0000) >> 16, TRID_REG(trident
, LEGACY_DMAR6
));
1063 outw((ESO_bytes
& 0x0000ffff), TRID_REG(trident
, LEGACY_DMAR4
));
1066 // Set channel sample rate, 4.12 format
1067 val
= (((unsigned int) 48000L << 12) + (runtime
->rate
/2)) / runtime
->rate
;
1068 outw(val
, TRID_REG(trident
, T4D_SBDELTA_DELTA_R
));
1070 // Set channel interrupt blk length
1071 if (snd_pcm_format_width(runtime
->format
) == 16) {
1072 val
= (unsigned short) ((ESO_bytes
>> 1) - 1);
1074 val
= (unsigned short) (ESO_bytes
- 1);
1077 outl((val
<< 16) | val
, TRID_REG(trident
, T4D_SBBL_SBCL
));
1079 // Right now, set format and start to run captureing,
1080 // continuous run loop enable.
1081 trident
->bDMAStart
= 0x19; // 0001 1001b
1083 if (snd_pcm_format_width(runtime
->format
) == 16)
1084 trident
->bDMAStart
|= 0x80;
1085 if (snd_pcm_format_signed(runtime
->format
))
1086 trident
->bDMAStart
|= 0x20;
1087 if (runtime
->channels
> 1)
1088 trident
->bDMAStart
|= 0x40;
1090 // Prepare capture intr channel
1092 voice
->Delta
= snd_trident_convert_rate(runtime
->rate
);
1093 voice
->spurious_threshold
= snd_trident_spurious_threshold(runtime
->rate
, runtime
->period_size
);
1095 voice
->isync_mark
= runtime
->period_size
;
1096 voice
->isync_max
= runtime
->buffer_size
;
1098 // Set voice parameters
1100 voice
->ESO
= voice
->isync_ESO
= (runtime
->period_size
* 2) + 6 - 1;
1101 voice
->CTRL
= snd_trident_control_mode(substream
);
1106 voice
->Pan
= 0x7f; /* mute */
1107 voice
->Vol
= 0x3ff; /* mute */
1111 voice
->Attribute
= 0;
1113 snd_trident_write_voice_regs(trident
, voice
);
1115 spin_unlock_irq(&trident
->reg_lock
);
1119 /*---------------------------------------------------------------------------
1120 snd_trident_si7018_capture_hw_params
1122 Description: Set the hardware parameters for the capture device.
1124 Parameters: substream - PCM substream class
1125 hw_params - hardware parameters
1127 Returns: Error status
1129 ---------------------------------------------------------------------------*/
1131 static int snd_trident_si7018_capture_hw_params(struct snd_pcm_substream
*substream
,
1132 struct snd_pcm_hw_params
*hw_params
)
1136 if ((err
= snd_pcm_lib_malloc_pages(substream
, params_buffer_bytes(hw_params
))) < 0)
1139 return snd_trident_allocate_evoice(substream
, hw_params
);
1142 /*---------------------------------------------------------------------------
1143 snd_trident_si7018_capture_hw_free
1145 Description: Release the hardware resources for the capture device.
1147 Parameters: substream - PCM substream class
1149 Returns: Error status
1151 ---------------------------------------------------------------------------*/
1153 static int snd_trident_si7018_capture_hw_free(struct snd_pcm_substream
*substream
)
1155 struct snd_trident
*trident
= snd_pcm_substream_chip(substream
);
1156 struct snd_pcm_runtime
*runtime
= substream
->runtime
;
1157 struct snd_trident_voice
*voice
= runtime
->private_data
;
1158 struct snd_trident_voice
*evoice
= voice
? voice
->extra
: NULL
;
1160 snd_pcm_lib_free_pages(substream
);
1161 if (evoice
!= NULL
) {
1162 snd_trident_free_voice(trident
, evoice
);
1163 voice
->extra
= NULL
;
1168 /*---------------------------------------------------------------------------
1169 snd_trident_si7018_capture_prepare
1171 Description: Prepare capture device for playback.
1173 Parameters: substream - PCM substream class
1175 Returns: Error status
1177 ---------------------------------------------------------------------------*/
1179 static int snd_trident_si7018_capture_prepare(struct snd_pcm_substream
*substream
)
1181 struct snd_trident
*trident
= snd_pcm_substream_chip(substream
);
1182 struct snd_pcm_runtime
*runtime
= substream
->runtime
;
1183 struct snd_trident_voice
*voice
= runtime
->private_data
;
1184 struct snd_trident_voice
*evoice
= voice
->extra
;
1186 spin_lock_irq(&trident
->reg_lock
);
1188 voice
->LBA
= runtime
->dma_addr
;
1189 voice
->Delta
= snd_trident_convert_adc_rate(runtime
->rate
);
1190 voice
->spurious_threshold
= snd_trident_spurious_threshold(runtime
->rate
, runtime
->period_size
);
1192 // Set voice parameters
1194 voice
->ESO
= runtime
->buffer_size
- 1; /* in samples */
1195 voice
->CTRL
= snd_trident_control_mode(substream
);
1200 voice
->Pan
= T4D_DEFAULT_PCM_PAN
;
1206 voice
->Attribute
= (2 << (30-16)) |
1211 snd_trident_write_voice_regs(trident
, voice
);
1213 if (evoice
!= NULL
) {
1214 evoice
->Delta
= snd_trident_convert_rate(runtime
->rate
);
1215 evoice
->spurious_threshold
= voice
->spurious_threshold
;
1216 evoice
->LBA
= voice
->LBA
;
1218 evoice
->ESO
= (runtime
->period_size
* 2) + 20 - 1; /* in samples, 20 means correction */
1219 evoice
->CTRL
= voice
->CTRL
;
1225 evoice
->Vol
= 0x3ff; /* mute */
1226 evoice
->RVol
= evoice
->CVol
= 0x7f; /* mute */
1227 evoice
->Pan
= 0x7f; /* mute */
1228 evoice
->Attribute
= 0;
1229 snd_trident_write_voice_regs(trident
, evoice
);
1231 evoice
->isync_mark
= runtime
->period_size
;
1232 evoice
->ESO
= (runtime
->period_size
* 2) - 1;
1235 spin_unlock_irq(&trident
->reg_lock
);
1239 /*---------------------------------------------------------------------------
1240 snd_trident_foldback_prepare
1242 Description: Prepare foldback capture device for playback.
1244 Parameters: substream - PCM substream class
1246 Returns: Error status
1248 ---------------------------------------------------------------------------*/
1250 static int snd_trident_foldback_prepare(struct snd_pcm_substream
*substream
)
1252 struct snd_trident
*trident
= snd_pcm_substream_chip(substream
);
1253 struct snd_pcm_runtime
*runtime
= substream
->runtime
;
1254 struct snd_trident_voice
*voice
= runtime
->private_data
;
1255 struct snd_trident_voice
*evoice
= voice
->extra
;
1257 spin_lock_irq(&trident
->reg_lock
);
1259 /* Set channel buffer Address */
1261 voice
->LBA
= voice
->memblk
->offset
;
1263 voice
->LBA
= runtime
->dma_addr
;
1265 /* set target ESO for channel */
1266 voice
->ESO
= runtime
->buffer_size
- 1; /* in samples */
1268 /* set sample rate */
1269 voice
->Delta
= 0x1000;
1270 voice
->spurious_threshold
= snd_trident_spurious_threshold(48000, runtime
->period_size
);
1273 voice
->CTRL
= snd_trident_control_mode(substream
);
1278 voice
->Pan
= 0x7f; /* mute */
1279 voice
->Vol
= 0x3ff; /* mute */
1283 voice
->Attribute
= 0;
1285 /* set up capture channel */
1286 outb(((voice
->number
& 0x3f) | 0x80), TRID_REG(trident
, T4D_RCI
+ voice
->foldback_chan
));
1288 snd_trident_write_voice_regs(trident
, voice
);
1290 if (evoice
!= NULL
) {
1291 evoice
->Delta
= voice
->Delta
;
1292 evoice
->spurious_threshold
= voice
->spurious_threshold
;
1293 evoice
->LBA
= voice
->LBA
;
1295 evoice
->ESO
= (runtime
->period_size
* 2) + 4 - 1; /* in samples */
1296 evoice
->CTRL
= voice
->CTRL
;
1298 evoice
->GVSel
= trident
->device
== TRIDENT_DEVICE_ID_SI7018
? 0 : 1;
1302 evoice
->Vol
= 0x3ff; /* mute */
1303 evoice
->RVol
= evoice
->CVol
= 0x7f; /* mute */
1304 evoice
->Pan
= 0x7f; /* mute */
1305 evoice
->Attribute
= 0;
1306 snd_trident_write_voice_regs(trident
, evoice
);
1308 evoice
->isync_mark
= runtime
->period_size
;
1309 evoice
->ESO
= (runtime
->period_size
* 2) - 1;
1312 spin_unlock_irq(&trident
->reg_lock
);
1316 /*---------------------------------------------------------------------------
1317 snd_trident_spdif_hw_params
1319 Description: Set the hardware parameters for the spdif device.
1321 Parameters: substream - PCM substream class
1322 hw_params - hardware parameters
1324 Returns: Error status
1326 ---------------------------------------------------------------------------*/
1328 static int snd_trident_spdif_hw_params(struct snd_pcm_substream
*substream
,
1329 struct snd_pcm_hw_params
*hw_params
)
1331 struct snd_trident
*trident
= snd_pcm_substream_chip(substream
);
1332 unsigned int old_bits
= 0, change
= 0;
1335 err
= snd_trident_allocate_pcm_mem(substream
, hw_params
);
1339 if (trident
->device
== TRIDENT_DEVICE_ID_SI7018
) {
1340 err
= snd_trident_allocate_evoice(substream
, hw_params
);
1345 /* prepare SPDIF channel */
1346 spin_lock_irq(&trident
->reg_lock
);
1347 old_bits
= trident
->spdif_pcm_bits
;
1348 if (old_bits
& IEC958_AES0_PROFESSIONAL
)
1349 trident
->spdif_pcm_bits
&= ~IEC958_AES0_PRO_FS
;
1351 trident
->spdif_pcm_bits
&= ~(IEC958_AES3_CON_FS
<< 24);
1352 if (params_rate(hw_params
) >= 48000) {
1353 trident
->spdif_pcm_ctrl
= 0x3c; // 48000 Hz
1354 trident
->spdif_pcm_bits
|=
1355 trident
->spdif_bits
& IEC958_AES0_PROFESSIONAL
?
1356 IEC958_AES0_PRO_FS_48000
:
1357 (IEC958_AES3_CON_FS_48000
<< 24);
1359 else if (params_rate(hw_params
) >= 44100) {
1360 trident
->spdif_pcm_ctrl
= 0x3e; // 44100 Hz
1361 trident
->spdif_pcm_bits
|=
1362 trident
->spdif_bits
& IEC958_AES0_PROFESSIONAL
?
1363 IEC958_AES0_PRO_FS_44100
:
1364 (IEC958_AES3_CON_FS_44100
<< 24);
1367 trident
->spdif_pcm_ctrl
= 0x3d; // 32000 Hz
1368 trident
->spdif_pcm_bits
|=
1369 trident
->spdif_bits
& IEC958_AES0_PROFESSIONAL
?
1370 IEC958_AES0_PRO_FS_32000
:
1371 (IEC958_AES3_CON_FS_32000
<< 24);
1373 change
= old_bits
!= trident
->spdif_pcm_bits
;
1374 spin_unlock_irq(&trident
->reg_lock
);
1377 snd_ctl_notify(trident
->card
, SNDRV_CTL_EVENT_MASK_VALUE
, &trident
->spdif_pcm_ctl
->id
);
1382 /*---------------------------------------------------------------------------
1383 snd_trident_spdif_prepare
1385 Description: Prepare SPDIF device for playback.
1387 Parameters: substream - PCM substream class
1389 Returns: Error status
1391 ---------------------------------------------------------------------------*/
1393 static int snd_trident_spdif_prepare(struct snd_pcm_substream
*substream
)
1395 struct snd_trident
*trident
= snd_pcm_substream_chip(substream
);
1396 struct snd_pcm_runtime
*runtime
= substream
->runtime
;
1397 struct snd_trident_voice
*voice
= runtime
->private_data
;
1398 struct snd_trident_voice
*evoice
= voice
->extra
;
1399 struct snd_trident_pcm_mixer
*mix
= &trident
->pcm_mixer
[substream
->number
];
1400 unsigned int RESO
, LBAO
;
1403 spin_lock_irq(&trident
->reg_lock
);
1405 if (trident
->device
!= TRIDENT_DEVICE_ID_SI7018
) {
1407 /* set delta (rate) value */
1408 voice
->Delta
= snd_trident_convert_rate(runtime
->rate
);
1409 voice
->spurious_threshold
= snd_trident_spurious_threshold(runtime
->rate
, runtime
->period_size
);
1411 /* set Loop Back Address */
1412 LBAO
= runtime
->dma_addr
;
1414 voice
->LBA
= voice
->memblk
->offset
;
1420 voice
->isync_mark
= runtime
->period_size
;
1421 voice
->isync_max
= runtime
->buffer_size
;
1423 /* set target ESO for channel */
1424 RESO
= runtime
->buffer_size
- 1;
1425 voice
->ESO
= voice
->isync_ESO
= (runtime
->period_size
* 2) + 6 - 1;
1428 voice
->CTRL
= snd_trident_control_mode(substream
);
1440 voice
->Attribute
= 0;
1442 /* prepare surrogate IRQ channel */
1443 snd_trident_write_voice_regs(trident
, voice
);
1445 outw((RESO
& 0xffff), TRID_REG(trident
, NX_SPESO
));
1446 outb((RESO
>> 16), TRID_REG(trident
, NX_SPESO
+ 2));
1447 outl((LBAO
& 0xfffffffc), TRID_REG(trident
, NX_SPLBA
));
1448 outw((voice
->CSO
& 0xffff), TRID_REG(trident
, NX_SPCTRL_SPCSO
));
1449 outb((voice
->CSO
>> 16), TRID_REG(trident
, NX_SPCTRL_SPCSO
+ 2));
1451 /* set SPDIF setting */
1452 outb(trident
->spdif_pcm_ctrl
, TRID_REG(trident
, NX_SPCTRL_SPCSO
+ 3));
1453 outl(trident
->spdif_pcm_bits
, TRID_REG(trident
, NX_SPCSTATUS
));
1457 /* set delta (rate) value */
1458 voice
->Delta
= 0x800;
1459 voice
->spurious_threshold
= snd_trident_spurious_threshold(48000, runtime
->period_size
);
1461 /* set Loop Begin Address */
1463 voice
->LBA
= voice
->memblk
->offset
;
1465 voice
->LBA
= runtime
->dma_addr
;
1468 voice
->ESO
= runtime
->buffer_size
- 1; /* in samples */
1469 voice
->CTRL
= snd_trident_control_mode(substream
);
1475 voice
->Vol
= mix
->vol
;
1476 voice
->RVol
= mix
->rvol
;
1477 voice
->CVol
= mix
->cvol
;
1478 voice
->Pan
= mix
->pan
;
1479 voice
->Attribute
= (1<<(30-16))|(7<<(26-16))|
1480 (0<<(24-16))|(0<<(19-16));
1482 snd_trident_write_voice_regs(trident
, voice
);
1484 if (evoice
!= NULL
) {
1485 evoice
->Delta
= voice
->Delta
;
1486 evoice
->spurious_threshold
= voice
->spurious_threshold
;
1487 evoice
->LBA
= voice
->LBA
;
1489 evoice
->ESO
= (runtime
->period_size
* 2) + 4 - 1; /* in samples */
1490 evoice
->CTRL
= voice
->CTRL
;
1492 evoice
->GVSel
= trident
->device
== TRIDENT_DEVICE_ID_SI7018
? 0 : 1;
1496 evoice
->Vol
= 0x3ff; /* mute */
1497 evoice
->RVol
= evoice
->CVol
= 0x7f; /* mute */
1498 evoice
->Pan
= 0x7f; /* mute */
1499 evoice
->Attribute
= 0;
1500 snd_trident_write_voice_regs(trident
, evoice
);
1502 evoice
->isync_mark
= runtime
->period_size
;
1503 evoice
->ESO
= (runtime
->period_size
* 2) - 1;
1506 outl(trident
->spdif_pcm_bits
, TRID_REG(trident
, SI_SPDIF_CS
));
1507 temp
= inl(TRID_REG(trident
, T4D_LFO_GC_CIR
));
1509 outl(temp
, TRID_REG(trident
, T4D_LFO_GC_CIR
));
1510 temp
= inl(TRID_REG(trident
, SI_SERIAL_INTF_CTRL
));
1512 outl(temp
, TRID_REG(trident
, SI_SERIAL_INTF_CTRL
));
1515 spin_unlock_irq(&trident
->reg_lock
);
1520 /*---------------------------------------------------------------------------
1523 Description: Start/stop devices
1525 Parameters: substream - PCM substream class
1526 cmd - trigger command (STOP, GO)
1528 Returns: Error status
1530 ---------------------------------------------------------------------------*/
1532 static int snd_trident_trigger(struct snd_pcm_substream
*substream
,
1536 struct snd_trident
*trident
= snd_pcm_substream_chip(substream
);
1537 struct list_head
*pos
;
1538 struct snd_pcm_substream
*s
;
1539 unsigned int what
, whati
, capture_flag
, spdif_flag
;
1540 struct snd_trident_voice
*voice
, *evoice
;
1541 unsigned int val
, go
;
1544 case SNDRV_PCM_TRIGGER_START
:
1545 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE
:
1546 case SNDRV_PCM_TRIGGER_RESUME
:
1549 case SNDRV_PCM_TRIGGER_STOP
:
1550 case SNDRV_PCM_TRIGGER_PAUSE_PUSH
:
1551 case SNDRV_PCM_TRIGGER_SUSPEND
:
1557 what
= whati
= capture_flag
= spdif_flag
= 0;
1558 spin_lock(&trident
->reg_lock
);
1559 val
= inl(TRID_REG(trident
, T4D_STIMER
)) & 0x00ffffff;
1560 snd_pcm_group_for_each(pos
, substream
) {
1561 s
= snd_pcm_group_substream_entry(pos
);
1562 if ((struct snd_trident
*) snd_pcm_substream_chip(s
) == trident
) {
1563 voice
= s
->runtime
->private_data
;
1564 evoice
= voice
->extra
;
1565 what
|= 1 << (voice
->number
& 0x1f);
1566 if (evoice
== NULL
) {
1567 whati
|= 1 << (voice
->number
& 0x1f);
1569 what
|= 1 << (evoice
->number
& 0x1f);
1570 whati
|= 1 << (evoice
->number
& 0x1f);
1572 evoice
->stimer
= val
;
1576 voice
->stimer
= val
;
1580 snd_pcm_trigger_done(s
, substream
);
1588 if (trident
->device
!= TRIDENT_DEVICE_ID_SI7018
) {
1589 outl(trident
->spdif_pcm_bits
, TRID_REG(trident
, NX_SPCSTATUS
));
1590 outb(trident
->spdif_pcm_ctrl
, TRID_REG(trident
, NX_SPCTRL_SPCSO
+ 3));
1592 outl(trident
->spdif_pcm_bits
, TRID_REG(trident
, SI_SPDIF_CS
));
1593 val
= inl(TRID_REG(trident
, SI_SERIAL_INTF_CTRL
)) | SPDIF_EN
;
1594 outl(val
, TRID_REG(trident
, SI_SERIAL_INTF_CTRL
));
1598 outl(what
, TRID_REG(trident
, T4D_STOP_B
));
1599 val
= inl(TRID_REG(trident
, T4D_AINTEN_B
));
1605 outl(val
, TRID_REG(trident
, T4D_AINTEN_B
));
1607 outl(what
, TRID_REG(trident
, T4D_START_B
));
1609 if (capture_flag
&& trident
->device
!= TRIDENT_DEVICE_ID_SI7018
)
1610 outb(trident
->bDMAStart
, TRID_REG(trident
, T4D_SBCTRL_SBE2R_SBDD
));
1612 if (capture_flag
&& trident
->device
!= TRIDENT_DEVICE_ID_SI7018
)
1613 outb(0x00, TRID_REG(trident
, T4D_SBCTRL_SBE2R_SBDD
));
1615 spin_unlock(&trident
->reg_lock
);
1619 /*---------------------------------------------------------------------------
1620 snd_trident_playback_pointer
1622 Description: This routine return the playback position
1624 Parameters: substream - PCM substream class
1626 Returns: position of buffer
1628 ---------------------------------------------------------------------------*/
1630 static snd_pcm_uframes_t
snd_trident_playback_pointer(struct snd_pcm_substream
*substream
)
1632 struct snd_trident
*trident
= snd_pcm_substream_chip(substream
);
1633 struct snd_pcm_runtime
*runtime
= substream
->runtime
;
1634 struct snd_trident_voice
*voice
= runtime
->private_data
;
1637 if (!voice
->running
)
1640 spin_lock(&trident
->reg_lock
);
1642 outb(voice
->number
, TRID_REG(trident
, T4D_LFO_GC_CIR
));
1644 if (trident
->device
!= TRIDENT_DEVICE_ID_NX
) {
1645 cso
= inw(TRID_REG(trident
, CH_DX_CSO_ALPHA_FMS
+ 2));
1646 } else { // ID_4DWAVE_NX
1647 cso
= (unsigned int) inl(TRID_REG(trident
, CH_NX_DELTA_CSO
)) & 0x00ffffff;
1650 spin_unlock(&trident
->reg_lock
);
1652 if (cso
>= runtime
->buffer_size
)
1658 /*---------------------------------------------------------------------------
1659 snd_trident_capture_pointer
1661 Description: This routine return the capture position
1663 Paramters: pcm1 - PCM device class
1665 Returns: position of buffer
1667 ---------------------------------------------------------------------------*/
1669 static snd_pcm_uframes_t
snd_trident_capture_pointer(struct snd_pcm_substream
*substream
)
1671 struct snd_trident
*trident
= snd_pcm_substream_chip(substream
);
1672 struct snd_pcm_runtime
*runtime
= substream
->runtime
;
1673 struct snd_trident_voice
*voice
= runtime
->private_data
;
1674 unsigned int result
;
1676 if (!voice
->running
)
1679 result
= inw(TRID_REG(trident
, T4D_SBBL_SBCL
));
1680 if (runtime
->channels
> 1)
1683 result
= runtime
->buffer_size
- result
;
1688 /*---------------------------------------------------------------------------
1689 snd_trident_spdif_pointer
1691 Description: This routine return the SPDIF playback position
1693 Parameters: substream - PCM substream class
1695 Returns: position of buffer
1697 ---------------------------------------------------------------------------*/
1699 static snd_pcm_uframes_t
snd_trident_spdif_pointer(struct snd_pcm_substream
*substream
)
1701 struct snd_trident
*trident
= snd_pcm_substream_chip(substream
);
1702 struct snd_pcm_runtime
*runtime
= substream
->runtime
;
1703 struct snd_trident_voice
*voice
= runtime
->private_data
;
1704 unsigned int result
;
1706 if (!voice
->running
)
1709 result
= inl(TRID_REG(trident
, NX_SPCTRL_SPCSO
)) & 0x00ffffff;
1715 * Playback support device description
1718 static struct snd_pcm_hardware snd_trident_playback
=
1720 .info
= (SNDRV_PCM_INFO_MMAP
| SNDRV_PCM_INFO_INTERLEAVED
|
1721 SNDRV_PCM_INFO_BLOCK_TRANSFER
|
1722 SNDRV_PCM_INFO_MMAP_VALID
| SNDRV_PCM_INFO_SYNC_START
|
1723 SNDRV_PCM_INFO_PAUSE
/* | SNDRV_PCM_INFO_RESUME */),
1724 .formats
= (SNDRV_PCM_FMTBIT_U8
| SNDRV_PCM_FMTBIT_S16_LE
|
1725 SNDRV_PCM_FMTBIT_S8
| SNDRV_PCM_FMTBIT_U16_LE
),
1726 .rates
= SNDRV_PCM_RATE_CONTINUOUS
| SNDRV_PCM_RATE_8000_48000
,
1731 .buffer_bytes_max
= (256*1024),
1732 .period_bytes_min
= 64,
1733 .period_bytes_max
= (256*1024),
1735 .periods_max
= 1024,
1740 * Capture support device description
1743 static struct snd_pcm_hardware snd_trident_capture
=
1745 .info
= (SNDRV_PCM_INFO_MMAP
| SNDRV_PCM_INFO_INTERLEAVED
|
1746 SNDRV_PCM_INFO_BLOCK_TRANSFER
|
1747 SNDRV_PCM_INFO_MMAP_VALID
| SNDRV_PCM_INFO_SYNC_START
|
1748 SNDRV_PCM_INFO_PAUSE
/* | SNDRV_PCM_INFO_RESUME */),
1749 .formats
= (SNDRV_PCM_FMTBIT_U8
| SNDRV_PCM_FMTBIT_S16_LE
|
1750 SNDRV_PCM_FMTBIT_S8
| SNDRV_PCM_FMTBIT_U16_LE
),
1751 .rates
= SNDRV_PCM_RATE_CONTINUOUS
| SNDRV_PCM_RATE_8000_48000
,
1756 .buffer_bytes_max
= (128*1024),
1757 .period_bytes_min
= 64,
1758 .period_bytes_max
= (128*1024),
1760 .periods_max
= 1024,
1765 * Foldback capture support device description
1768 static struct snd_pcm_hardware snd_trident_foldback
=
1770 .info
= (SNDRV_PCM_INFO_MMAP
| SNDRV_PCM_INFO_INTERLEAVED
|
1771 SNDRV_PCM_INFO_BLOCK_TRANSFER
|
1772 SNDRV_PCM_INFO_MMAP_VALID
| SNDRV_PCM_INFO_SYNC_START
|
1773 SNDRV_PCM_INFO_PAUSE
/* | SNDRV_PCM_INFO_RESUME */),
1774 .formats
= SNDRV_PCM_FMTBIT_S16_LE
,
1775 .rates
= SNDRV_PCM_RATE_48000
,
1780 .buffer_bytes_max
= (128*1024),
1781 .period_bytes_min
= 64,
1782 .period_bytes_max
= (128*1024),
1784 .periods_max
= 1024,
1789 * SPDIF playback support device description
1792 static struct snd_pcm_hardware snd_trident_spdif
=
1794 .info
= (SNDRV_PCM_INFO_MMAP
| SNDRV_PCM_INFO_INTERLEAVED
|
1795 SNDRV_PCM_INFO_BLOCK_TRANSFER
|
1796 SNDRV_PCM_INFO_MMAP_VALID
| SNDRV_PCM_INFO_SYNC_START
|
1797 SNDRV_PCM_INFO_PAUSE
/* | SNDRV_PCM_INFO_RESUME */),
1798 .formats
= SNDRV_PCM_FMTBIT_S16_LE
,
1799 .rates
= (SNDRV_PCM_RATE_32000
| SNDRV_PCM_RATE_44100
|
1800 SNDRV_PCM_RATE_48000
),
1805 .buffer_bytes_max
= (128*1024),
1806 .period_bytes_min
= 64,
1807 .period_bytes_max
= (128*1024),
1809 .periods_max
= 1024,
1813 static struct snd_pcm_hardware snd_trident_spdif_7018
=
1815 .info
= (SNDRV_PCM_INFO_MMAP
| SNDRV_PCM_INFO_INTERLEAVED
|
1816 SNDRV_PCM_INFO_BLOCK_TRANSFER
|
1817 SNDRV_PCM_INFO_MMAP_VALID
| SNDRV_PCM_INFO_SYNC_START
|
1818 SNDRV_PCM_INFO_PAUSE
/* | SNDRV_PCM_INFO_RESUME */),
1819 .formats
= SNDRV_PCM_FMTBIT_S16_LE
,
1820 .rates
= SNDRV_PCM_RATE_48000
,
1825 .buffer_bytes_max
= (128*1024),
1826 .period_bytes_min
= 64,
1827 .period_bytes_max
= (128*1024),
1829 .periods_max
= 1024,
1833 static void snd_trident_pcm_free_substream(struct snd_pcm_runtime
*runtime
)
1835 struct snd_trident_voice
*voice
= runtime
->private_data
;
1836 struct snd_trident
*trident
;
1839 trident
= voice
->trident
;
1840 snd_trident_free_voice(trident
, voice
);
1844 static int snd_trident_playback_open(struct snd_pcm_substream
*substream
)
1846 struct snd_trident
*trident
= snd_pcm_substream_chip(substream
);
1847 struct snd_pcm_runtime
*runtime
= substream
->runtime
;
1848 struct snd_trident_voice
*voice
;
1850 voice
= snd_trident_alloc_voice(trident
, SNDRV_TRIDENT_VOICE_TYPE_PCM
, 0, 0);
1853 snd_trident_pcm_mixer_build(trident
, voice
, substream
);
1854 voice
->substream
= substream
;
1855 runtime
->private_data
= voice
;
1856 runtime
->private_free
= snd_trident_pcm_free_substream
;
1857 runtime
->hw
= snd_trident_playback
;
1858 snd_pcm_set_sync(substream
);
1859 snd_pcm_hw_constraint_minmax(runtime
, SNDRV_PCM_HW_PARAM_BUFFER_SIZE
, 0, 64*1024);
1863 /*---------------------------------------------------------------------------
1864 snd_trident_playback_close
1866 Description: This routine will close the 4DWave playback device. For now
1867 we will simply free the dma transfer buffer.
1869 Parameters: substream - PCM substream class
1871 ---------------------------------------------------------------------------*/
1872 static int snd_trident_playback_close(struct snd_pcm_substream
*substream
)
1874 struct snd_trident
*trident
= snd_pcm_substream_chip(substream
);
1875 struct snd_pcm_runtime
*runtime
= substream
->runtime
;
1876 struct snd_trident_voice
*voice
= runtime
->private_data
;
1878 snd_trident_pcm_mixer_free(trident
, voice
, substream
);
1882 /*---------------------------------------------------------------------------
1883 snd_trident_spdif_open
1885 Description: This routine will open the 4DWave SPDIF device.
1887 Parameters: substream - PCM substream class
1889 Returns: status - success or failure flag
1891 ---------------------------------------------------------------------------*/
1893 static int snd_trident_spdif_open(struct snd_pcm_substream
*substream
)
1895 struct snd_trident
*trident
= snd_pcm_substream_chip(substream
);
1896 struct snd_trident_voice
*voice
;
1897 struct snd_pcm_runtime
*runtime
= substream
->runtime
;
1899 voice
= snd_trident_alloc_voice(trident
, SNDRV_TRIDENT_VOICE_TYPE_PCM
, 0, 0);
1903 voice
->substream
= substream
;
1904 spin_lock_irq(&trident
->reg_lock
);
1905 trident
->spdif_pcm_bits
= trident
->spdif_bits
;
1906 spin_unlock_irq(&trident
->reg_lock
);
1908 runtime
->private_data
= voice
;
1909 runtime
->private_free
= snd_trident_pcm_free_substream
;
1910 if (trident
->device
== TRIDENT_DEVICE_ID_SI7018
) {
1911 runtime
->hw
= snd_trident_spdif
;
1913 runtime
->hw
= snd_trident_spdif_7018
;
1916 trident
->spdif_pcm_ctl
->vd
[0].access
&= ~SNDRV_CTL_ELEM_ACCESS_INACTIVE
;
1917 snd_ctl_notify(trident
->card
, SNDRV_CTL_EVENT_MASK_VALUE
|
1918 SNDRV_CTL_EVENT_MASK_INFO
, &trident
->spdif_pcm_ctl
->id
);
1920 snd_pcm_hw_constraint_minmax(runtime
, SNDRV_PCM_HW_PARAM_BUFFER_SIZE
, 0, 64*1024);
1925 /*---------------------------------------------------------------------------
1926 snd_trident_spdif_close
1928 Description: This routine will close the 4DWave SPDIF device.
1930 Parameters: substream - PCM substream class
1932 ---------------------------------------------------------------------------*/
1934 static int snd_trident_spdif_close(struct snd_pcm_substream
*substream
)
1936 struct snd_trident
*trident
= snd_pcm_substream_chip(substream
);
1939 spin_lock_irq(&trident
->reg_lock
);
1940 // restore default SPDIF setting
1941 if (trident
->device
!= TRIDENT_DEVICE_ID_SI7018
) {
1942 outb(trident
->spdif_ctrl
, TRID_REG(trident
, NX_SPCTRL_SPCSO
+ 3));
1943 outl(trident
->spdif_bits
, TRID_REG(trident
, NX_SPCSTATUS
));
1945 outl(trident
->spdif_bits
, TRID_REG(trident
, SI_SPDIF_CS
));
1946 temp
= inl(TRID_REG(trident
, SI_SERIAL_INTF_CTRL
));
1947 if (trident
->spdif_ctrl
) {
1952 outl(temp
, TRID_REG(trident
, SI_SERIAL_INTF_CTRL
));
1954 spin_unlock_irq(&trident
->reg_lock
);
1955 trident
->spdif_pcm_ctl
->vd
[0].access
|= SNDRV_CTL_ELEM_ACCESS_INACTIVE
;
1956 snd_ctl_notify(trident
->card
, SNDRV_CTL_EVENT_MASK_VALUE
|
1957 SNDRV_CTL_EVENT_MASK_INFO
, &trident
->spdif_pcm_ctl
->id
);
1961 /*---------------------------------------------------------------------------
1962 snd_trident_capture_open
1964 Description: This routine will open the 4DWave capture device.
1966 Parameters: substream - PCM substream class
1968 Returns: status - success or failure flag
1970 ---------------------------------------------------------------------------*/
1972 static int snd_trident_capture_open(struct snd_pcm_substream
*substream
)
1974 struct snd_trident
*trident
= snd_pcm_substream_chip(substream
);
1975 struct snd_trident_voice
*voice
;
1976 struct snd_pcm_runtime
*runtime
= substream
->runtime
;
1978 voice
= snd_trident_alloc_voice(trident
, SNDRV_TRIDENT_VOICE_TYPE_PCM
, 0, 0);
1982 voice
->substream
= substream
;
1983 runtime
->private_data
= voice
;
1984 runtime
->private_free
= snd_trident_pcm_free_substream
;
1985 runtime
->hw
= snd_trident_capture
;
1986 snd_pcm_set_sync(substream
);
1987 snd_pcm_hw_constraint_minmax(runtime
, SNDRV_PCM_HW_PARAM_BUFFER_SIZE
, 0, 64*1024);
1991 /*---------------------------------------------------------------------------
1992 snd_trident_capture_close
1994 Description: This routine will close the 4DWave capture device. For now
1995 we will simply free the dma transfer buffer.
1997 Parameters: substream - PCM substream class
1999 ---------------------------------------------------------------------------*/
2000 static int snd_trident_capture_close(struct snd_pcm_substream
*substream
)
2005 /*---------------------------------------------------------------------------
2006 snd_trident_foldback_open
2008 Description: This routine will open the 4DWave foldback capture device.
2010 Parameters: substream - PCM substream class
2012 Returns: status - success or failure flag
2014 ---------------------------------------------------------------------------*/
2016 static int snd_trident_foldback_open(struct snd_pcm_substream
*substream
)
2018 struct snd_trident
*trident
= snd_pcm_substream_chip(substream
);
2019 struct snd_trident_voice
*voice
;
2020 struct snd_pcm_runtime
*runtime
= substream
->runtime
;
2022 voice
= snd_trident_alloc_voice(trident
, SNDRV_TRIDENT_VOICE_TYPE_PCM
, 0, 0);
2025 voice
->foldback_chan
= substream
->number
;
2026 voice
->substream
= substream
;
2027 runtime
->private_data
= voice
;
2028 runtime
->private_free
= snd_trident_pcm_free_substream
;
2029 runtime
->hw
= snd_trident_foldback
;
2030 snd_pcm_hw_constraint_minmax(runtime
, SNDRV_PCM_HW_PARAM_BUFFER_SIZE
, 0, 64*1024);
2034 /*---------------------------------------------------------------------------
2035 snd_trident_foldback_close
2037 Description: This routine will close the 4DWave foldback capture device.
2038 For now we will simply free the dma transfer buffer.
2040 Parameters: substream - PCM substream class
2042 ---------------------------------------------------------------------------*/
2043 static int snd_trident_foldback_close(struct snd_pcm_substream
*substream
)
2045 struct snd_trident
*trident
= snd_pcm_substream_chip(substream
);
2046 struct snd_trident_voice
*voice
;
2047 struct snd_pcm_runtime
*runtime
= substream
->runtime
;
2048 voice
= runtime
->private_data
;
2050 /* stop capture channel */
2051 spin_lock_irq(&trident
->reg_lock
);
2052 outb(0x00, TRID_REG(trident
, T4D_RCI
+ voice
->foldback_chan
));
2053 spin_unlock_irq(&trident
->reg_lock
);
2057 /*---------------------------------------------------------------------------
2059 ---------------------------------------------------------------------------*/
2061 static struct snd_pcm_ops snd_trident_playback_ops
= {
2062 .open
= snd_trident_playback_open
,
2063 .close
= snd_trident_playback_close
,
2064 .ioctl
= snd_trident_ioctl
,
2065 .hw_params
= snd_trident_hw_params
,
2066 .hw_free
= snd_trident_hw_free
,
2067 .prepare
= snd_trident_playback_prepare
,
2068 .trigger
= snd_trident_trigger
,
2069 .pointer
= snd_trident_playback_pointer
,
2072 static struct snd_pcm_ops snd_trident_nx_playback_ops
= {
2073 .open
= snd_trident_playback_open
,
2074 .close
= snd_trident_playback_close
,
2075 .ioctl
= snd_trident_ioctl
,
2076 .hw_params
= snd_trident_hw_params
,
2077 .hw_free
= snd_trident_hw_free
,
2078 .prepare
= snd_trident_playback_prepare
,
2079 .trigger
= snd_trident_trigger
,
2080 .pointer
= snd_trident_playback_pointer
,
2081 .page
= snd_pcm_sgbuf_ops_page
,
2084 static struct snd_pcm_ops snd_trident_capture_ops
= {
2085 .open
= snd_trident_capture_open
,
2086 .close
= snd_trident_capture_close
,
2087 .ioctl
= snd_trident_ioctl
,
2088 .hw_params
= snd_trident_capture_hw_params
,
2089 .hw_free
= snd_trident_hw_free
,
2090 .prepare
= snd_trident_capture_prepare
,
2091 .trigger
= snd_trident_trigger
,
2092 .pointer
= snd_trident_capture_pointer
,
2095 static struct snd_pcm_ops snd_trident_si7018_capture_ops
= {
2096 .open
= snd_trident_capture_open
,
2097 .close
= snd_trident_capture_close
,
2098 .ioctl
= snd_trident_ioctl
,
2099 .hw_params
= snd_trident_si7018_capture_hw_params
,
2100 .hw_free
= snd_trident_si7018_capture_hw_free
,
2101 .prepare
= snd_trident_si7018_capture_prepare
,
2102 .trigger
= snd_trident_trigger
,
2103 .pointer
= snd_trident_playback_pointer
,
2106 static struct snd_pcm_ops snd_trident_foldback_ops
= {
2107 .open
= snd_trident_foldback_open
,
2108 .close
= snd_trident_foldback_close
,
2109 .ioctl
= snd_trident_ioctl
,
2110 .hw_params
= snd_trident_hw_params
,
2111 .hw_free
= snd_trident_hw_free
,
2112 .prepare
= snd_trident_foldback_prepare
,
2113 .trigger
= snd_trident_trigger
,
2114 .pointer
= snd_trident_playback_pointer
,
2117 static struct snd_pcm_ops snd_trident_nx_foldback_ops
= {
2118 .open
= snd_trident_foldback_open
,
2119 .close
= snd_trident_foldback_close
,
2120 .ioctl
= snd_trident_ioctl
,
2121 .hw_params
= snd_trident_hw_params
,
2122 .hw_free
= snd_trident_hw_free
,
2123 .prepare
= snd_trident_foldback_prepare
,
2124 .trigger
= snd_trident_trigger
,
2125 .pointer
= snd_trident_playback_pointer
,
2126 .page
= snd_pcm_sgbuf_ops_page
,
2129 static struct snd_pcm_ops snd_trident_spdif_ops
= {
2130 .open
= snd_trident_spdif_open
,
2131 .close
= snd_trident_spdif_close
,
2132 .ioctl
= snd_trident_ioctl
,
2133 .hw_params
= snd_trident_spdif_hw_params
,
2134 .hw_free
= snd_trident_hw_free
,
2135 .prepare
= snd_trident_spdif_prepare
,
2136 .trigger
= snd_trident_trigger
,
2137 .pointer
= snd_trident_spdif_pointer
,
2140 static struct snd_pcm_ops snd_trident_spdif_7018_ops
= {
2141 .open
= snd_trident_spdif_open
,
2142 .close
= snd_trident_spdif_close
,
2143 .ioctl
= snd_trident_ioctl
,
2144 .hw_params
= snd_trident_spdif_hw_params
,
2145 .hw_free
= snd_trident_hw_free
,
2146 .prepare
= snd_trident_spdif_prepare
,
2147 .trigger
= snd_trident_trigger
,
2148 .pointer
= snd_trident_playback_pointer
,
2151 /*---------------------------------------------------------------------------
2154 Description: This routine registers the 4DWave device for PCM support.
2156 Paramters: trident - pointer to target device class for 4DWave.
2160 ---------------------------------------------------------------------------*/
2162 int __devinit
snd_trident_pcm(struct snd_trident
* trident
,
2163 int device
, struct snd_pcm
** rpcm
)
2165 struct snd_pcm
*pcm
;
2170 if ((err
= snd_pcm_new(trident
->card
, "trident_dx_nx", device
, trident
->ChanPCM
, 1, &pcm
)) < 0)
2173 pcm
->private_data
= trident
;
2175 if (trident
->tlb
.entries
) {
2176 snd_pcm_set_ops(pcm
, SNDRV_PCM_STREAM_PLAYBACK
, &snd_trident_nx_playback_ops
);
2178 snd_pcm_set_ops(pcm
, SNDRV_PCM_STREAM_PLAYBACK
, &snd_trident_playback_ops
);
2180 snd_pcm_set_ops(pcm
, SNDRV_PCM_STREAM_CAPTURE
,
2181 trident
->device
!= TRIDENT_DEVICE_ID_SI7018
?
2182 &snd_trident_capture_ops
:
2183 &snd_trident_si7018_capture_ops
);
2185 pcm
->info_flags
= 0;
2186 pcm
->dev_subclass
= SNDRV_PCM_SUBCLASS_GENERIC_MIX
;
2187 strcpy(pcm
->name
, "Trident 4DWave");
2190 if (trident
->tlb
.entries
) {
2191 struct snd_pcm_substream
*substream
;
2192 for (substream
= pcm
->streams
[SNDRV_PCM_STREAM_PLAYBACK
].substream
; substream
; substream
= substream
->next
)
2193 snd_pcm_lib_preallocate_pages(substream
, SNDRV_DMA_TYPE_DEV_SG
,
2194 snd_dma_pci_data(trident
->pci
),
2196 snd_pcm_lib_preallocate_pages(pcm
->streams
[SNDRV_PCM_STREAM_CAPTURE
].substream
,
2197 SNDRV_DMA_TYPE_DEV
, snd_dma_pci_data(trident
->pci
),
2200 snd_pcm_lib_preallocate_pages_for_all(pcm
, SNDRV_DMA_TYPE_DEV
,
2201 snd_dma_pci_data(trident
->pci
), 64*1024, 128*1024);
2209 /*---------------------------------------------------------------------------
2210 snd_trident_foldback_pcm
2212 Description: This routine registers the 4DWave device for foldback PCM support.
2214 Paramters: trident - pointer to target device class for 4DWave.
2218 ---------------------------------------------------------------------------*/
2220 int __devinit
snd_trident_foldback_pcm(struct snd_trident
* trident
,
2221 int device
, struct snd_pcm
** rpcm
)
2223 struct snd_pcm
*foldback
;
2226 struct snd_pcm_substream
*substream
;
2230 if (trident
->device
== TRIDENT_DEVICE_ID_NX
)
2232 if ((err
= snd_pcm_new(trident
->card
, "trident_dx_nx", device
, 0, num_chan
, &foldback
)) < 0)
2235 foldback
->private_data
= trident
;
2236 if (trident
->tlb
.entries
)
2237 snd_pcm_set_ops(foldback
, SNDRV_PCM_STREAM_CAPTURE
, &snd_trident_nx_foldback_ops
);
2239 snd_pcm_set_ops(foldback
, SNDRV_PCM_STREAM_CAPTURE
, &snd_trident_foldback_ops
);
2240 foldback
->info_flags
= 0;
2241 strcpy(foldback
->name
, "Trident 4DWave");
2242 substream
= foldback
->streams
[SNDRV_PCM_STREAM_CAPTURE
].substream
;
2243 strcpy(substream
->name
, "Front Mixer");
2244 substream
= substream
->next
;
2245 strcpy(substream
->name
, "Reverb Mixer");
2246 substream
= substream
->next
;
2247 strcpy(substream
->name
, "Chorus Mixer");
2248 if (num_chan
== 4) {
2249 substream
= substream
->next
;
2250 strcpy(substream
->name
, "Second AC'97 ADC");
2252 trident
->foldback
= foldback
;
2254 if (trident
->tlb
.entries
)
2255 snd_pcm_lib_preallocate_pages_for_all(foldback
, SNDRV_DMA_TYPE_DEV_SG
,
2256 snd_dma_pci_data(trident
->pci
), 0, 128*1024);
2258 snd_pcm_lib_preallocate_pages_for_all(foldback
, SNDRV_DMA_TYPE_DEV
,
2259 snd_dma_pci_data(trident
->pci
), 64*1024, 128*1024);
2266 /*---------------------------------------------------------------------------
2269 Description: This routine registers the 4DWave-NX device for SPDIF support.
2271 Paramters: trident - pointer to target device class for 4DWave-NX.
2275 ---------------------------------------------------------------------------*/
2277 int __devinit
snd_trident_spdif_pcm(struct snd_trident
* trident
,
2278 int device
, struct snd_pcm
** rpcm
)
2280 struct snd_pcm
*spdif
;
2285 if ((err
= snd_pcm_new(trident
->card
, "trident_dx_nx IEC958", device
, 1, 0, &spdif
)) < 0)
2288 spdif
->private_data
= trident
;
2289 if (trident
->device
!= TRIDENT_DEVICE_ID_SI7018
) {
2290 snd_pcm_set_ops(spdif
, SNDRV_PCM_STREAM_PLAYBACK
, &snd_trident_spdif_ops
);
2292 snd_pcm_set_ops(spdif
, SNDRV_PCM_STREAM_PLAYBACK
, &snd_trident_spdif_7018_ops
);
2294 spdif
->info_flags
= 0;
2295 strcpy(spdif
->name
, "Trident 4DWave IEC958");
2296 trident
->spdif
= spdif
;
2298 snd_pcm_lib_preallocate_pages_for_all(spdif
, SNDRV_DMA_TYPE_DEV
, snd_dma_pci_data(trident
->pci
), 64*1024, 128*1024);
2310 /*---------------------------------------------------------------------------
2311 snd_trident_spdif_control
2313 Description: enable/disable S/PDIF out from ac97 mixer
2314 ---------------------------------------------------------------------------*/
2316 static int snd_trident_spdif_control_info(struct snd_kcontrol
*kcontrol
,
2317 struct snd_ctl_elem_info
*uinfo
)
2319 uinfo
->type
= SNDRV_CTL_ELEM_TYPE_BOOLEAN
;
2321 uinfo
->value
.integer
.min
= 0;
2322 uinfo
->value
.integer
.max
= 1;
2326 static int snd_trident_spdif_control_get(struct snd_kcontrol
*kcontrol
,
2327 struct snd_ctl_elem_value
*ucontrol
)
2329 struct snd_trident
*trident
= snd_kcontrol_chip(kcontrol
);
2332 spin_lock_irq(&trident
->reg_lock
);
2333 val
= trident
->spdif_ctrl
;
2334 ucontrol
->value
.integer
.value
[0] = val
== kcontrol
->private_value
;
2335 spin_unlock_irq(&trident
->reg_lock
);
2339 static int snd_trident_spdif_control_put(struct snd_kcontrol
*kcontrol
,
2340 struct snd_ctl_elem_value
*ucontrol
)
2342 struct snd_trident
*trident
= snd_kcontrol_chip(kcontrol
);
2346 val
= ucontrol
->value
.integer
.value
[0] ? (unsigned char) kcontrol
->private_value
: 0x00;
2347 spin_lock_irq(&trident
->reg_lock
);
2348 /* S/PDIF C Channel bits 0-31 : 48khz, SCMS disabled */
2349 change
= trident
->spdif_ctrl
!= val
;
2350 trident
->spdif_ctrl
= val
;
2351 if (trident
->device
!= TRIDENT_DEVICE_ID_SI7018
) {
2352 if ((inb(TRID_REG(trident
, NX_SPCTRL_SPCSO
+ 3)) & 0x10) == 0) {
2353 outl(trident
->spdif_bits
, TRID_REG(trident
, NX_SPCSTATUS
));
2354 outb(trident
->spdif_ctrl
, TRID_REG(trident
, NX_SPCTRL_SPCSO
+ 3));
2357 if (trident
->spdif
== NULL
) {
2359 outl(trident
->spdif_bits
, TRID_REG(trident
, SI_SPDIF_CS
));
2360 temp
= inl(TRID_REG(trident
, SI_SERIAL_INTF_CTRL
)) & ~SPDIF_EN
;
2363 outl(temp
, TRID_REG(trident
, SI_SERIAL_INTF_CTRL
));
2366 spin_unlock_irq(&trident
->reg_lock
);
2370 static struct snd_kcontrol_new snd_trident_spdif_control __devinitdata
=
2372 .iface
= SNDRV_CTL_ELEM_IFACE_MIXER
,
2373 .name
= SNDRV_CTL_NAME_IEC958("",PLAYBACK
,SWITCH
),
2374 .info
= snd_trident_spdif_control_info
,
2375 .get
= snd_trident_spdif_control_get
,
2376 .put
= snd_trident_spdif_control_put
,
2377 .private_value
= 0x28,
2380 /*---------------------------------------------------------------------------
2381 snd_trident_spdif_default
2383 Description: put/get the S/PDIF default settings
2384 ---------------------------------------------------------------------------*/
2386 static int snd_trident_spdif_default_info(struct snd_kcontrol
*kcontrol
,
2387 struct snd_ctl_elem_info
*uinfo
)
2389 uinfo
->type
= SNDRV_CTL_ELEM_TYPE_IEC958
;
2394 static int snd_trident_spdif_default_get(struct snd_kcontrol
*kcontrol
,
2395 struct snd_ctl_elem_value
*ucontrol
)
2397 struct snd_trident
*trident
= snd_kcontrol_chip(kcontrol
);
2399 spin_lock_irq(&trident
->reg_lock
);
2400 ucontrol
->value
.iec958
.status
[0] = (trident
->spdif_bits
>> 0) & 0xff;
2401 ucontrol
->value
.iec958
.status
[1] = (trident
->spdif_bits
>> 8) & 0xff;
2402 ucontrol
->value
.iec958
.status
[2] = (trident
->spdif_bits
>> 16) & 0xff;
2403 ucontrol
->value
.iec958
.status
[3] = (trident
->spdif_bits
>> 24) & 0xff;
2404 spin_unlock_irq(&trident
->reg_lock
);
2408 static int snd_trident_spdif_default_put(struct snd_kcontrol
*kcontrol
,
2409 struct snd_ctl_elem_value
*ucontrol
)
2411 struct snd_trident
*trident
= snd_kcontrol_chip(kcontrol
);
2415 val
= (ucontrol
->value
.iec958
.status
[0] << 0) |
2416 (ucontrol
->value
.iec958
.status
[1] << 8) |
2417 (ucontrol
->value
.iec958
.status
[2] << 16) |
2418 (ucontrol
->value
.iec958
.status
[3] << 24);
2419 spin_lock_irq(&trident
->reg_lock
);
2420 change
= trident
->spdif_bits
!= val
;
2421 trident
->spdif_bits
= val
;
2422 if (trident
->device
!= TRIDENT_DEVICE_ID_SI7018
) {
2423 if ((inb(TRID_REG(trident
, NX_SPCTRL_SPCSO
+ 3)) & 0x10) == 0)
2424 outl(trident
->spdif_bits
, TRID_REG(trident
, NX_SPCSTATUS
));
2426 if (trident
->spdif
== NULL
)
2427 outl(trident
->spdif_bits
, TRID_REG(trident
, SI_SPDIF_CS
));
2429 spin_unlock_irq(&trident
->reg_lock
);
2433 static struct snd_kcontrol_new snd_trident_spdif_default __devinitdata
=
2435 .iface
= SNDRV_CTL_ELEM_IFACE_PCM
,
2436 .name
= SNDRV_CTL_NAME_IEC958("",PLAYBACK
,DEFAULT
),
2437 .info
= snd_trident_spdif_default_info
,
2438 .get
= snd_trident_spdif_default_get
,
2439 .put
= snd_trident_spdif_default_put
2442 /*---------------------------------------------------------------------------
2443 snd_trident_spdif_mask
2445 Description: put/get the S/PDIF mask
2446 ---------------------------------------------------------------------------*/
2448 static int snd_trident_spdif_mask_info(struct snd_kcontrol
*kcontrol
,
2449 struct snd_ctl_elem_info
*uinfo
)
2451 uinfo
->type
= SNDRV_CTL_ELEM_TYPE_IEC958
;
2456 static int snd_trident_spdif_mask_get(struct snd_kcontrol
*kcontrol
,
2457 struct snd_ctl_elem_value
*ucontrol
)
2459 ucontrol
->value
.iec958
.status
[0] = 0xff;
2460 ucontrol
->value
.iec958
.status
[1] = 0xff;
2461 ucontrol
->value
.iec958
.status
[2] = 0xff;
2462 ucontrol
->value
.iec958
.status
[3] = 0xff;
2466 static struct snd_kcontrol_new snd_trident_spdif_mask __devinitdata
=
2468 .access
= SNDRV_CTL_ELEM_ACCESS_READ
,
2469 .iface
= SNDRV_CTL_ELEM_IFACE_PCM
,
2470 .name
= SNDRV_CTL_NAME_IEC958("",PLAYBACK
,MASK
),
2471 .info
= snd_trident_spdif_mask_info
,
2472 .get
= snd_trident_spdif_mask_get
,
2475 /*---------------------------------------------------------------------------
2476 snd_trident_spdif_stream
2478 Description: put/get the S/PDIF stream settings
2479 ---------------------------------------------------------------------------*/
2481 static int snd_trident_spdif_stream_info(struct snd_kcontrol
*kcontrol
,
2482 struct snd_ctl_elem_info
*uinfo
)
2484 uinfo
->type
= SNDRV_CTL_ELEM_TYPE_IEC958
;
2489 static int snd_trident_spdif_stream_get(struct snd_kcontrol
*kcontrol
,
2490 struct snd_ctl_elem_value
*ucontrol
)
2492 struct snd_trident
*trident
= snd_kcontrol_chip(kcontrol
);
2494 spin_lock_irq(&trident
->reg_lock
);
2495 ucontrol
->value
.iec958
.status
[0] = (trident
->spdif_pcm_bits
>> 0) & 0xff;
2496 ucontrol
->value
.iec958
.status
[1] = (trident
->spdif_pcm_bits
>> 8) & 0xff;
2497 ucontrol
->value
.iec958
.status
[2] = (trident
->spdif_pcm_bits
>> 16) & 0xff;
2498 ucontrol
->value
.iec958
.status
[3] = (trident
->spdif_pcm_bits
>> 24) & 0xff;
2499 spin_unlock_irq(&trident
->reg_lock
);
2503 static int snd_trident_spdif_stream_put(struct snd_kcontrol
*kcontrol
,
2504 struct snd_ctl_elem_value
*ucontrol
)
2506 struct snd_trident
*trident
= snd_kcontrol_chip(kcontrol
);
2510 val
= (ucontrol
->value
.iec958
.status
[0] << 0) |
2511 (ucontrol
->value
.iec958
.status
[1] << 8) |
2512 (ucontrol
->value
.iec958
.status
[2] << 16) |
2513 (ucontrol
->value
.iec958
.status
[3] << 24);
2514 spin_lock_irq(&trident
->reg_lock
);
2515 change
= trident
->spdif_pcm_bits
!= val
;
2516 trident
->spdif_pcm_bits
= val
;
2517 if (trident
->spdif
!= NULL
) {
2518 if (trident
->device
!= TRIDENT_DEVICE_ID_SI7018
) {
2519 outl(trident
->spdif_pcm_bits
, TRID_REG(trident
, NX_SPCSTATUS
));
2521 outl(trident
->spdif_bits
, TRID_REG(trident
, SI_SPDIF_CS
));
2524 spin_unlock_irq(&trident
->reg_lock
);
2528 static struct snd_kcontrol_new snd_trident_spdif_stream __devinitdata
=
2530 .access
= SNDRV_CTL_ELEM_ACCESS_READWRITE
| SNDRV_CTL_ELEM_ACCESS_INACTIVE
,
2531 .iface
= SNDRV_CTL_ELEM_IFACE_PCM
,
2532 .name
= SNDRV_CTL_NAME_IEC958("",PLAYBACK
,PCM_STREAM
),
2533 .info
= snd_trident_spdif_stream_info
,
2534 .get
= snd_trident_spdif_stream_get
,
2535 .put
= snd_trident_spdif_stream_put
2538 /*---------------------------------------------------------------------------
2539 snd_trident_ac97_control
2541 Description: enable/disable rear path for ac97
2542 ---------------------------------------------------------------------------*/
2544 static int snd_trident_ac97_control_info(struct snd_kcontrol
*kcontrol
,
2545 struct snd_ctl_elem_info
*uinfo
)
2547 uinfo
->type
= SNDRV_CTL_ELEM_TYPE_BOOLEAN
;
2549 uinfo
->value
.integer
.min
= 0;
2550 uinfo
->value
.integer
.max
= 1;
2554 static int snd_trident_ac97_control_get(struct snd_kcontrol
*kcontrol
,
2555 struct snd_ctl_elem_value
*ucontrol
)
2557 struct snd_trident
*trident
= snd_kcontrol_chip(kcontrol
);
2560 spin_lock_irq(&trident
->reg_lock
);
2561 val
= trident
->ac97_ctrl
= inl(TRID_REG(trident
, NX_ACR0_AC97_COM_STAT
));
2562 ucontrol
->value
.integer
.value
[0] = (val
& (1 << kcontrol
->private_value
)) ? 1 : 0;
2563 spin_unlock_irq(&trident
->reg_lock
);
2567 static int snd_trident_ac97_control_put(struct snd_kcontrol
*kcontrol
,
2568 struct snd_ctl_elem_value
*ucontrol
)
2570 struct snd_trident
*trident
= snd_kcontrol_chip(kcontrol
);
2574 spin_lock_irq(&trident
->reg_lock
);
2575 val
= trident
->ac97_ctrl
= inl(TRID_REG(trident
, NX_ACR0_AC97_COM_STAT
));
2576 val
&= ~(1 << kcontrol
->private_value
);
2577 if (ucontrol
->value
.integer
.value
[0])
2578 val
|= 1 << kcontrol
->private_value
;
2579 change
= val
!= trident
->ac97_ctrl
;
2580 trident
->ac97_ctrl
= val
;
2581 outl(trident
->ac97_ctrl
= val
, TRID_REG(trident
, NX_ACR0_AC97_COM_STAT
));
2582 spin_unlock_irq(&trident
->reg_lock
);
2586 static struct snd_kcontrol_new snd_trident_ac97_rear_control __devinitdata
=
2588 .iface
= SNDRV_CTL_ELEM_IFACE_MIXER
,
2589 .name
= "Rear Path",
2590 .info
= snd_trident_ac97_control_info
,
2591 .get
= snd_trident_ac97_control_get
,
2592 .put
= snd_trident_ac97_control_put
,
2596 /*---------------------------------------------------------------------------
2597 snd_trident_vol_control
2599 Description: wave & music volume control
2600 ---------------------------------------------------------------------------*/
2602 static int snd_trident_vol_control_info(struct snd_kcontrol
*kcontrol
,
2603 struct snd_ctl_elem_info
*uinfo
)
2605 uinfo
->type
= SNDRV_CTL_ELEM_TYPE_INTEGER
;
2607 uinfo
->value
.integer
.min
= 0;
2608 uinfo
->value
.integer
.max
= 255;
2612 static int snd_trident_vol_control_get(struct snd_kcontrol
*kcontrol
,
2613 struct snd_ctl_elem_value
*ucontrol
)
2615 struct snd_trident
*trident
= snd_kcontrol_chip(kcontrol
);
2618 val
= trident
->musicvol_wavevol
;
2619 ucontrol
->value
.integer
.value
[0] = 255 - ((val
>> kcontrol
->private_value
) & 0xff);
2620 ucontrol
->value
.integer
.value
[1] = 255 - ((val
>> (kcontrol
->private_value
+ 8)) & 0xff);
2624 static int snd_trident_vol_control_put(struct snd_kcontrol
*kcontrol
,
2625 struct snd_ctl_elem_value
*ucontrol
)
2627 struct snd_trident
*trident
= snd_kcontrol_chip(kcontrol
);
2631 spin_lock_irq(&trident
->reg_lock
);
2632 val
= trident
->musicvol_wavevol
;
2633 val
&= ~(0xffff << kcontrol
->private_value
);
2634 val
|= ((255 - (ucontrol
->value
.integer
.value
[0] & 0xff)) |
2635 ((255 - (ucontrol
->value
.integer
.value
[1] & 0xff)) << 8)) << kcontrol
->private_value
;
2636 change
= val
!= trident
->musicvol_wavevol
;
2637 outl(trident
->musicvol_wavevol
= val
, TRID_REG(trident
, T4D_MUSICVOL_WAVEVOL
));
2638 spin_unlock_irq(&trident
->reg_lock
);
2642 static struct snd_kcontrol_new snd_trident_vol_music_control __devinitdata
=
2644 .iface
= SNDRV_CTL_ELEM_IFACE_MIXER
,
2645 .name
= "Music Playback Volume",
2646 .info
= snd_trident_vol_control_info
,
2647 .get
= snd_trident_vol_control_get
,
2648 .put
= snd_trident_vol_control_put
,
2649 .private_value
= 16,
2652 static struct snd_kcontrol_new snd_trident_vol_wave_control __devinitdata
=
2654 .iface
= SNDRV_CTL_ELEM_IFACE_MIXER
,
2655 .name
= "Wave Playback Volume",
2656 .info
= snd_trident_vol_control_info
,
2657 .get
= snd_trident_vol_control_get
,
2658 .put
= snd_trident_vol_control_put
,
2662 /*---------------------------------------------------------------------------
2663 snd_trident_pcm_vol_control
2665 Description: PCM front volume control
2666 ---------------------------------------------------------------------------*/
2668 static int snd_trident_pcm_vol_control_info(struct snd_kcontrol
*kcontrol
,
2669 struct snd_ctl_elem_info
*uinfo
)
2671 struct snd_trident
*trident
= snd_kcontrol_chip(kcontrol
);
2673 uinfo
->type
= SNDRV_CTL_ELEM_TYPE_INTEGER
;
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;
2682 static int snd_trident_pcm_vol_control_get(struct snd_kcontrol
*kcontrol
,
2683 struct snd_ctl_elem_value
*ucontrol
)
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
)];
2688 if (trident
->device
== TRIDENT_DEVICE_ID_SI7018
) {
2689 ucontrol
->value
.integer
.value
[0] = 1023 - mix
->vol
;
2691 ucontrol
->value
.integer
.value
[0] = 255 - (mix
->vol
>>2);
2696 static int snd_trident_pcm_vol_control_put(struct snd_kcontrol
*kcontrol
,
2697 struct snd_ctl_elem_value
*ucontrol
)
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
)];
2704 if (trident
->device
== TRIDENT_DEVICE_ID_SI7018
) {
2705 val
= 1023 - (ucontrol
->value
.integer
.value
[0] & 1023);
2707 val
= (255 - (ucontrol
->value
.integer
.value
[0] & 255)) << 2;
2709 spin_lock_irq(&trident
->reg_lock
);
2710 change
= val
!= mix
->vol
;
2712 if (mix
->voice
!= NULL
)
2713 snd_trident_write_vol_reg(trident
, mix
->voice
, val
);
2714 spin_unlock_irq(&trident
->reg_lock
);
2718 static struct snd_kcontrol_new snd_trident_pcm_vol_control __devinitdata
=
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
,
2724 .info
= snd_trident_pcm_vol_control_info
,
2725 .get
= snd_trident_pcm_vol_control_get
,
2726 .put
= snd_trident_pcm_vol_control_put
,
2729 /*---------------------------------------------------------------------------
2730 snd_trident_pcm_pan_control
2732 Description: PCM front pan control
2733 ---------------------------------------------------------------------------*/
2735 static int snd_trident_pcm_pan_control_info(struct snd_kcontrol
*kcontrol
,
2736 struct snd_ctl_elem_info
*uinfo
)
2738 uinfo
->type
= SNDRV_CTL_ELEM_TYPE_INTEGER
;
2740 uinfo
->value
.integer
.min
= 0;
2741 uinfo
->value
.integer
.max
= 127;
2745 static int snd_trident_pcm_pan_control_get(struct snd_kcontrol
*kcontrol
,
2746 struct snd_ctl_elem_value
*ucontrol
)
2748 struct snd_trident
*trident
= snd_kcontrol_chip(kcontrol
);
2749 struct snd_trident_pcm_mixer
*mix
= &trident
->pcm_mixer
[snd_ctl_get_ioffnum(kcontrol
, &ucontrol
->id
)];
2751 ucontrol
->value
.integer
.value
[0] = mix
->pan
;
2752 if (ucontrol
->value
.integer
.value
[0] & 0x40) {
2753 ucontrol
->value
.integer
.value
[0] = (0x3f - (ucontrol
->value
.integer
.value
[0] & 0x3f));
2755 ucontrol
->value
.integer
.value
[0] |= 0x40;
2760 static int snd_trident_pcm_pan_control_put(struct snd_kcontrol
*kcontrol
,
2761 struct snd_ctl_elem_value
*ucontrol
)
2763 struct snd_trident
*trident
= snd_kcontrol_chip(kcontrol
);
2764 struct snd_trident_pcm_mixer
*mix
= &trident
->pcm_mixer
[snd_ctl_get_ioffnum(kcontrol
, &ucontrol
->id
)];
2768 if (ucontrol
->value
.integer
.value
[0] & 0x40)
2769 val
= ucontrol
->value
.integer
.value
[0] & 0x3f;
2771 val
= (0x3f - (ucontrol
->value
.integer
.value
[0] & 0x3f)) | 0x40;
2772 spin_lock_irq(&trident
->reg_lock
);
2773 change
= val
!= mix
->pan
;
2775 if (mix
->voice
!= NULL
)
2776 snd_trident_write_pan_reg(trident
, mix
->voice
, val
);
2777 spin_unlock_irq(&trident
->reg_lock
);
2781 static struct snd_kcontrol_new snd_trident_pcm_pan_control __devinitdata
=
2783 .iface
= SNDRV_CTL_ELEM_IFACE_MIXER
,
2784 .name
= "PCM Pan Playback Control",
2785 .access
= SNDRV_CTL_ELEM_ACCESS_READWRITE
| SNDRV_CTL_ELEM_ACCESS_INACTIVE
,
2787 .info
= snd_trident_pcm_pan_control_info
,
2788 .get
= snd_trident_pcm_pan_control_get
,
2789 .put
= snd_trident_pcm_pan_control_put
,
2792 /*---------------------------------------------------------------------------
2793 snd_trident_pcm_rvol_control
2795 Description: PCM reverb volume control
2796 ---------------------------------------------------------------------------*/
2798 static int snd_trident_pcm_rvol_control_info(struct snd_kcontrol
*kcontrol
,
2799 struct snd_ctl_elem_info
*uinfo
)
2801 uinfo
->type
= SNDRV_CTL_ELEM_TYPE_INTEGER
;
2803 uinfo
->value
.integer
.min
= 0;
2804 uinfo
->value
.integer
.max
= 127;
2808 static int snd_trident_pcm_rvol_control_get(struct snd_kcontrol
*kcontrol
,
2809 struct snd_ctl_elem_value
*ucontrol
)
2811 struct snd_trident
*trident
= snd_kcontrol_chip(kcontrol
);
2812 struct snd_trident_pcm_mixer
*mix
= &trident
->pcm_mixer
[snd_ctl_get_ioffnum(kcontrol
, &ucontrol
->id
)];
2814 ucontrol
->value
.integer
.value
[0] = 127 - mix
->rvol
;
2818 static int snd_trident_pcm_rvol_control_put(struct snd_kcontrol
*kcontrol
,
2819 struct snd_ctl_elem_value
*ucontrol
)
2821 struct snd_trident
*trident
= snd_kcontrol_chip(kcontrol
);
2822 struct snd_trident_pcm_mixer
*mix
= &trident
->pcm_mixer
[snd_ctl_get_ioffnum(kcontrol
, &ucontrol
->id
)];
2826 val
= 0x7f - (ucontrol
->value
.integer
.value
[0] & 0x7f);
2827 spin_lock_irq(&trident
->reg_lock
);
2828 change
= val
!= mix
->rvol
;
2830 if (mix
->voice
!= NULL
)
2831 snd_trident_write_rvol_reg(trident
, mix
->voice
, val
);
2832 spin_unlock_irq(&trident
->reg_lock
);
2836 static struct snd_kcontrol_new snd_trident_pcm_rvol_control __devinitdata
=
2838 .iface
= SNDRV_CTL_ELEM_IFACE_MIXER
,
2839 .name
= "PCM Reverb Playback Volume",
2840 .access
= SNDRV_CTL_ELEM_ACCESS_READWRITE
| SNDRV_CTL_ELEM_ACCESS_INACTIVE
,
2842 .info
= snd_trident_pcm_rvol_control_info
,
2843 .get
= snd_trident_pcm_rvol_control_get
,
2844 .put
= snd_trident_pcm_rvol_control_put
,
2847 /*---------------------------------------------------------------------------
2848 snd_trident_pcm_cvol_control
2850 Description: PCM chorus volume control
2851 ---------------------------------------------------------------------------*/
2853 static int snd_trident_pcm_cvol_control_info(struct snd_kcontrol
*kcontrol
,
2854 struct snd_ctl_elem_info
*uinfo
)
2856 uinfo
->type
= SNDRV_CTL_ELEM_TYPE_INTEGER
;
2858 uinfo
->value
.integer
.min
= 0;
2859 uinfo
->value
.integer
.max
= 127;
2863 static int snd_trident_pcm_cvol_control_get(struct snd_kcontrol
*kcontrol
,
2864 struct snd_ctl_elem_value
*ucontrol
)
2866 struct snd_trident
*trident
= snd_kcontrol_chip(kcontrol
);
2867 struct snd_trident_pcm_mixer
*mix
= &trident
->pcm_mixer
[snd_ctl_get_ioffnum(kcontrol
, &ucontrol
->id
)];
2869 ucontrol
->value
.integer
.value
[0] = 127 - mix
->cvol
;
2873 static int snd_trident_pcm_cvol_control_put(struct snd_kcontrol
*kcontrol
,
2874 struct snd_ctl_elem_value
*ucontrol
)
2876 struct snd_trident
*trident
= snd_kcontrol_chip(kcontrol
);
2877 struct snd_trident_pcm_mixer
*mix
= &trident
->pcm_mixer
[snd_ctl_get_ioffnum(kcontrol
, &ucontrol
->id
)];
2881 val
= 0x7f - (ucontrol
->value
.integer
.value
[0] & 0x7f);
2882 spin_lock_irq(&trident
->reg_lock
);
2883 change
= val
!= mix
->cvol
;
2885 if (mix
->voice
!= NULL
)
2886 snd_trident_write_cvol_reg(trident
, mix
->voice
, val
);
2887 spin_unlock_irq(&trident
->reg_lock
);
2891 static struct snd_kcontrol_new snd_trident_pcm_cvol_control __devinitdata
=
2893 .iface
= SNDRV_CTL_ELEM_IFACE_MIXER
,
2894 .name
= "PCM Chorus Playback Volume",
2895 .access
= SNDRV_CTL_ELEM_ACCESS_READWRITE
| SNDRV_CTL_ELEM_ACCESS_INACTIVE
,
2897 .info
= snd_trident_pcm_cvol_control_info
,
2898 .get
= snd_trident_pcm_cvol_control_get
,
2899 .put
= snd_trident_pcm_cvol_control_put
,
2902 static void snd_trident_notify_pcm_change1(struct snd_card
*card
,
2903 struct snd_kcontrol
*kctl
,
2904 int num
, int activate
)
2906 struct snd_ctl_elem_id id
;
2911 kctl
->vd
[num
].access
&= ~SNDRV_CTL_ELEM_ACCESS_INACTIVE
;
2913 kctl
->vd
[num
].access
|= SNDRV_CTL_ELEM_ACCESS_INACTIVE
;
2914 snd_ctl_notify(card
, SNDRV_CTL_EVENT_MASK_VALUE
|
2915 SNDRV_CTL_EVENT_MASK_INFO
,
2916 snd_ctl_build_ioff(&id
, kctl
, num
));
2919 static void snd_trident_notify_pcm_change(struct snd_trident
*trident
,
2920 struct snd_trident_pcm_mixer
*tmix
,
2921 int num
, int activate
)
2923 snd_trident_notify_pcm_change1(trident
->card
, trident
->ctl_vol
, num
, activate
);
2924 snd_trident_notify_pcm_change1(trident
->card
, trident
->ctl_pan
, num
, activate
);
2925 snd_trident_notify_pcm_change1(trident
->card
, trident
->ctl_rvol
, num
, activate
);
2926 snd_trident_notify_pcm_change1(trident
->card
, trident
->ctl_cvol
, num
, activate
);
2929 static int snd_trident_pcm_mixer_build(struct snd_trident
*trident
,
2930 struct snd_trident_voice
*voice
,
2931 struct snd_pcm_substream
*substream
)
2933 struct snd_trident_pcm_mixer
*tmix
;
2935 snd_assert(trident
!= NULL
&& voice
!= NULL
&& substream
!= NULL
, return -EINVAL
);
2936 tmix
= &trident
->pcm_mixer
[substream
->number
];
2937 tmix
->voice
= voice
;
2938 tmix
->vol
= T4D_DEFAULT_PCM_VOL
;
2939 tmix
->pan
= T4D_DEFAULT_PCM_PAN
;
2940 tmix
->rvol
= T4D_DEFAULT_PCM_RVOL
;
2941 tmix
->cvol
= T4D_DEFAULT_PCM_CVOL
;
2942 snd_trident_notify_pcm_change(trident
, tmix
, substream
->number
, 1);
2946 static int snd_trident_pcm_mixer_free(struct snd_trident
*trident
, struct snd_trident_voice
*voice
, struct snd_pcm_substream
*substream
)
2948 struct snd_trident_pcm_mixer
*tmix
;
2950 snd_assert(trident
!= NULL
&& substream
!= NULL
, return -EINVAL
);
2951 tmix
= &trident
->pcm_mixer
[substream
->number
];
2953 snd_trident_notify_pcm_change(trident
, tmix
, substream
->number
, 0);
2957 /*---------------------------------------------------------------------------
2960 Description: This routine registers the 4DWave device for mixer support.
2962 Paramters: trident - pointer to target device class for 4DWave.
2966 ---------------------------------------------------------------------------*/
2968 static int __devinit
snd_trident_mixer(struct snd_trident
* trident
, int pcm_spdif_device
)
2970 struct snd_ac97_template _ac97
;
2971 struct snd_card
*card
= trident
->card
;
2972 struct snd_kcontrol
*kctl
;
2973 struct snd_ctl_elem_value
*uctl
;
2974 int idx
, err
, retries
= 2;
2975 static struct snd_ac97_bus_ops ops
= {
2976 .write
= snd_trident_codec_write
,
2977 .read
= snd_trident_codec_read
,
2980 uctl
= kzalloc(sizeof(*uctl
), GFP_KERNEL
);
2984 if ((err
= snd_ac97_bus(trident
->card
, 0, &ops
, NULL
, &trident
->ac97_bus
)) < 0)
2987 memset(&_ac97
, 0, sizeof(_ac97
));
2988 _ac97
.private_data
= trident
;
2989 trident
->ac97_detect
= 1;
2992 if ((err
= snd_ac97_mixer(trident
->ac97_bus
, &_ac97
, &trident
->ac97
)) < 0) {
2993 if (trident
->device
== TRIDENT_DEVICE_ID_SI7018
) {
2994 if ((err
= snd_trident_sis_reset(trident
)) < 0)
3003 /* secondary codec? */
3004 if (trident
->device
== TRIDENT_DEVICE_ID_SI7018
&&
3005 (inl(TRID_REG(trident
, SI_SERIAL_INTF_CTRL
)) & SI_AC97_PRIMARY_READY
) != 0) {
3007 err
= snd_ac97_mixer(trident
->ac97_bus
, &_ac97
, &trident
->ac97_sec
);
3009 snd_printk(KERN_ERR
"SI7018: the secondary codec - invalid access\n");
3010 #if 0 // only for my testing purpose --jk
3012 struct snd_ac97
*mc97
;
3013 err
= snd_ac97_modem(trident
->card
, &_ac97
, &mc97
);
3015 snd_printk(KERN_ERR
"snd_ac97_modem returned error %i\n", err
);
3020 trident
->ac97_detect
= 0;
3022 if (trident
->device
!= TRIDENT_DEVICE_ID_SI7018
) {
3023 if ((err
= snd_ctl_add(card
, kctl
= snd_ctl_new1(&snd_trident_vol_wave_control
, trident
))) < 0)
3025 kctl
->put(kctl
, uctl
);
3026 if ((err
= snd_ctl_add(card
, kctl
= snd_ctl_new1(&snd_trident_vol_music_control
, trident
))) < 0)
3028 kctl
->put(kctl
, uctl
);
3029 outl(trident
->musicvol_wavevol
= 0x00000000, TRID_REG(trident
, T4D_MUSICVOL_WAVEVOL
));
3031 outl(trident
->musicvol_wavevol
= 0xffff0000, TRID_REG(trident
, T4D_MUSICVOL_WAVEVOL
));
3034 for (idx
= 0; idx
< 32; idx
++) {
3035 struct snd_trident_pcm_mixer
*tmix
;
3037 tmix
= &trident
->pcm_mixer
[idx
];
3040 if ((trident
->ctl_vol
= snd_ctl_new1(&snd_trident_pcm_vol_control
, trident
)) == NULL
)
3042 if ((err
= snd_ctl_add(card
, trident
->ctl_vol
)))
3045 if ((trident
->ctl_pan
= snd_ctl_new1(&snd_trident_pcm_pan_control
, trident
)) == NULL
)
3047 if ((err
= snd_ctl_add(card
, trident
->ctl_pan
)))
3050 if ((trident
->ctl_rvol
= snd_ctl_new1(&snd_trident_pcm_rvol_control
, trident
)) == NULL
)
3052 if ((err
= snd_ctl_add(card
, trident
->ctl_rvol
)))
3055 if ((trident
->ctl_cvol
= snd_ctl_new1(&snd_trident_pcm_cvol_control
, trident
)) == NULL
)
3057 if ((err
= snd_ctl_add(card
, trident
->ctl_cvol
)))
3060 if (trident
->device
== TRIDENT_DEVICE_ID_NX
) {
3061 if ((err
= snd_ctl_add(card
, kctl
= snd_ctl_new1(&snd_trident_ac97_rear_control
, trident
))) < 0)
3063 kctl
->put(kctl
, uctl
);
3065 if (trident
->device
== TRIDENT_DEVICE_ID_NX
|| trident
->device
== TRIDENT_DEVICE_ID_SI7018
) {
3067 kctl
= snd_ctl_new1(&snd_trident_spdif_control
, trident
);
3072 if (trident
->ac97
->ext_id
& AC97_EI_SPDIF
)
3074 if (trident
->ac97_sec
&& (trident
->ac97_sec
->ext_id
& AC97_EI_SPDIF
))
3076 idx
= kctl
->id
.index
;
3077 if ((err
= snd_ctl_add(card
, kctl
)) < 0)
3079 kctl
->put(kctl
, uctl
);
3081 kctl
= snd_ctl_new1(&snd_trident_spdif_default
, trident
);
3086 kctl
->id
.index
= idx
;
3087 kctl
->id
.device
= pcm_spdif_device
;
3088 if ((err
= snd_ctl_add(card
, kctl
)) < 0)
3091 kctl
= snd_ctl_new1(&snd_trident_spdif_mask
, trident
);
3096 kctl
->id
.index
= idx
;
3097 kctl
->id
.device
= pcm_spdif_device
;
3098 if ((err
= snd_ctl_add(card
, kctl
)) < 0)
3101 kctl
= snd_ctl_new1(&snd_trident_spdif_stream
, trident
);
3106 kctl
->id
.index
= idx
;
3107 kctl
->id
.device
= pcm_spdif_device
;
3108 if ((err
= snd_ctl_add(card
, kctl
)) < 0)
3110 trident
->spdif_pcm_ctl
= kctl
;
3126 * gameport interface
3129 #if defined(CONFIG_GAMEPORT) || (defined(MODULE) && defined(CONFIG_GAMEPORT_MODULE))
3131 static unsigned char snd_trident_gameport_read(struct gameport
*gameport
)
3133 struct snd_trident
*chip
= gameport_get_port_data(gameport
);
3135 snd_assert(chip
, return 0);
3136 return inb(TRID_REG(chip
, GAMEPORT_LEGACY
));
3139 static void snd_trident_gameport_trigger(struct gameport
*gameport
)
3141 struct snd_trident
*chip
= gameport_get_port_data(gameport
);
3143 snd_assert(chip
, return);
3144 outb(0xff, TRID_REG(chip
, GAMEPORT_LEGACY
));
3147 static int snd_trident_gameport_cooked_read(struct gameport
*gameport
, int *axes
, int *buttons
)
3149 struct snd_trident
*chip
= gameport_get_port_data(gameport
);
3152 snd_assert(chip
, return 0);
3154 *buttons
= (~inb(TRID_REG(chip
, GAMEPORT_LEGACY
)) >> 4) & 0xf;
3156 for (i
= 0; i
< 4; i
++) {
3157 axes
[i
] = inw(TRID_REG(chip
, GAMEPORT_AXES
+ i
* 2));
3158 if (axes
[i
] == 0xffff) axes
[i
] = -1;
3164 static int snd_trident_gameport_open(struct gameport
*gameport
, int mode
)
3166 struct snd_trident
*chip
= gameport_get_port_data(gameport
);
3168 snd_assert(chip
, return 0);
3171 case GAMEPORT_MODE_COOKED
:
3172 outb(GAMEPORT_MODE_ADC
, TRID_REG(chip
, GAMEPORT_GCR
));
3175 case GAMEPORT_MODE_RAW
:
3176 outb(0, TRID_REG(chip
, GAMEPORT_GCR
));
3183 int __devinit
snd_trident_create_gameport(struct snd_trident
*chip
)
3185 struct gameport
*gp
;
3187 chip
->gameport
= gp
= gameport_allocate_port();
3189 printk(KERN_ERR
"trident: cannot allocate memory for gameport\n");
3193 gameport_set_name(gp
, "Trident 4DWave");
3194 gameport_set_phys(gp
, "pci%s/gameport0", pci_name(chip
->pci
));
3195 gameport_set_dev_parent(gp
, &chip
->pci
->dev
);
3197 gameport_set_port_data(gp
, chip
);
3199 gp
->read
= snd_trident_gameport_read
;
3200 gp
->trigger
= snd_trident_gameport_trigger
;
3201 gp
->cooked_read
= snd_trident_gameport_cooked_read
;
3202 gp
->open
= snd_trident_gameport_open
;
3204 gameport_register_port(gp
);
3209 static inline void snd_trident_free_gameport(struct snd_trident
*chip
)
3211 if (chip
->gameport
) {
3212 gameport_unregister_port(chip
->gameport
);
3213 chip
->gameport
= NULL
;
3217 int __devinit
snd_trident_create_gameport(struct snd_trident
*chip
) { return -ENOSYS
; }
3218 static inline void snd_trident_free_gameport(struct snd_trident
*chip
) { }
3219 #endif /* CONFIG_GAMEPORT */
3224 static inline void do_delay(struct snd_trident
*chip
)
3226 schedule_timeout_uninterruptible(1);
3233 static int snd_trident_sis_reset(struct snd_trident
*trident
)
3235 unsigned long end_time
;
3239 r
= trident
->in_suspend
? 0 : 2; /* count of retries */
3241 pci_write_config_byte(trident
->pci
, 0x46, 0x04); /* SOFTWARE RESET */
3243 pci_write_config_byte(trident
->pci
, 0x46, 0x00);
3245 /* disable AC97 GPIO interrupt */
3246 outb(0x00, TRID_REG(trident
, SI_AC97_GPIO
));
3247 /* initialize serial interface, force cold reset */
3248 i
= PCMOUT
|SURROUT
|CENTEROUT
|LFEOUT
|SECONDARY_ID
|COLD_RESET
;
3249 outl(i
, TRID_REG(trident
, SI_SERIAL_INTF_CTRL
));
3251 /* remove cold reset */
3253 outl(i
, TRID_REG(trident
, SI_SERIAL_INTF_CTRL
));
3255 /* wait, until the codec is ready */
3256 end_time
= (jiffies
+ (HZ
* 3) / 4) + 1;
3258 if ((inl(TRID_REG(trident
, SI_SERIAL_INTF_CTRL
)) & SI_AC97_PRIMARY_READY
) != 0)
3261 } while (time_after_eq(end_time
, jiffies
));
3262 snd_printk(KERN_ERR
"AC'97 codec ready error [0x%x]\n", inl(TRID_REG(trident
, SI_SERIAL_INTF_CTRL
)));
3264 end_time
= jiffies
+ HZ
;
3267 } while (time_after_eq(end_time
, jiffies
));
3268 goto __si7018_retry
;
3271 /* wait for the second codec */
3273 if ((inl(TRID_REG(trident
, SI_SERIAL_INTF_CTRL
)) & SI_AC97_SECONDARY_READY
) != 0)
3276 } while (time_after_eq(end_time
, jiffies
));
3277 /* enable 64 channel mode */
3278 outl(BANK_B_EN
, TRID_REG(trident
, T4D_LFO_GC_CIR
));
3286 static void snd_trident_proc_read(struct snd_info_entry
*entry
,
3287 struct snd_info_buffer
*buffer
)
3289 struct snd_trident
*trident
= entry
->private_data
;
3292 switch (trident
->device
) {
3293 case TRIDENT_DEVICE_ID_SI7018
:
3294 s
= "SiS 7018 Audio";
3296 case TRIDENT_DEVICE_ID_DX
:
3297 s
= "Trident 4DWave PCI DX";
3299 case TRIDENT_DEVICE_ID_NX
:
3300 s
= "Trident 4DWave PCI NX";
3305 snd_iprintf(buffer
, "%s\n\n", s
);
3306 snd_iprintf(buffer
, "Spurious IRQs : %d\n", trident
->spurious_irq_count
);
3307 snd_iprintf(buffer
, "Spurious IRQ dlta: %d\n", trident
->spurious_irq_max_delta
);
3308 if (trident
->device
== TRIDENT_DEVICE_ID_NX
|| trident
->device
== TRIDENT_DEVICE_ID_SI7018
)
3309 snd_iprintf(buffer
, "IEC958 Mixer Out : %s\n", trident
->spdif_ctrl
== 0x28 ? "on" : "off");
3310 if (trident
->device
== TRIDENT_DEVICE_ID_NX
) {
3311 snd_iprintf(buffer
, "Rear Speakers : %s\n", trident
->ac97_ctrl
& 0x00000010 ? "on" : "off");
3312 if (trident
->tlb
.entries
) {
3313 snd_iprintf(buffer
,"\nVirtual Memory\n");
3314 snd_iprintf(buffer
, "Memory Maximum : %d\n", trident
->tlb
.memhdr
->size
);
3315 snd_iprintf(buffer
, "Memory Used : %d\n", trident
->tlb
.memhdr
->used
);
3316 snd_iprintf(buffer
, "Memory Free : %d\n", snd_util_mem_avail(trident
->tlb
.memhdr
));
3319 #if defined(CONFIG_SND_SEQUENCER) || (defined(MODULE) && defined(CONFIG_SND_SEQUENCER_MODULE))
3320 snd_iprintf(buffer
,"\nWavetable Synth\n");
3321 snd_iprintf(buffer
, "Memory Maximum : %d\n", trident
->synth
.max_size
);
3322 snd_iprintf(buffer
, "Memory Used : %d\n", trident
->synth
.current_size
);
3323 snd_iprintf(buffer
, "Memory Free : %d\n", (trident
->synth
.max_size
-trident
->synth
.current_size
));
3327 static void __devinit
snd_trident_proc_init(struct snd_trident
* trident
)
3329 struct snd_info_entry
*entry
;
3330 const char *s
= "trident";
3332 if (trident
->device
== TRIDENT_DEVICE_ID_SI7018
)
3334 if (! snd_card_proc_new(trident
->card
, s
, &entry
))
3335 snd_info_set_text_ops(entry
, trident
, 1024, snd_trident_proc_read
);
3338 static int snd_trident_dev_free(struct snd_device
*device
)
3340 struct snd_trident
*trident
= device
->device_data
;
3341 return snd_trident_free(trident
);
3344 /*---------------------------------------------------------------------------
3345 snd_trident_tlb_alloc
3347 Description: Allocate and set up the TLB page table on 4D NX.
3348 Each entry has 4 bytes (physical PCI address).
3350 Paramters: trident - pointer to target device class for 4DWave.
3352 Returns: 0 or negative error code
3354 ---------------------------------------------------------------------------*/
3356 static int __devinit
snd_trident_tlb_alloc(struct snd_trident
*trident
)
3360 /* TLB array must be aligned to 16kB !!! so we allocate
3361 32kB region and correct offset when necessary */
3363 if (snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV
, snd_dma_pci_data(trident
->pci
),
3364 2 * SNDRV_TRIDENT_MAX_PAGES
* 4, &trident
->tlb
.buffer
) < 0) {
3365 snd_printk(KERN_ERR
"trident: unable to allocate TLB buffer\n");
3368 trident
->tlb
.entries
= (unsigned int*)(((unsigned long)trident
->tlb
.buffer
.area
+ SNDRV_TRIDENT_MAX_PAGES
* 4 - 1) & ~(SNDRV_TRIDENT_MAX_PAGES
* 4 - 1));
3369 trident
->tlb
.entries_dmaaddr
= (trident
->tlb
.buffer
.addr
+ SNDRV_TRIDENT_MAX_PAGES
* 4 - 1) & ~(SNDRV_TRIDENT_MAX_PAGES
* 4 - 1);
3370 /* allocate shadow TLB page table (virtual addresses) */
3371 trident
->tlb
.shadow_entries
= vmalloc(SNDRV_TRIDENT_MAX_PAGES
*sizeof(unsigned long));
3372 if (trident
->tlb
.shadow_entries
== NULL
) {
3373 snd_printk(KERN_ERR
"trident: unable to allocate shadow TLB entries\n");
3376 /* allocate and setup silent page and initialise TLB entries */
3377 if (snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV
, snd_dma_pci_data(trident
->pci
),
3378 SNDRV_TRIDENT_PAGE_SIZE
, &trident
->tlb
.silent_page
) < 0) {
3379 snd_printk(KERN_ERR
"trident: unable to allocate silent page\n");
3382 memset(trident
->tlb
.silent_page
.area
, 0, SNDRV_TRIDENT_PAGE_SIZE
);
3383 for (i
= 0; i
< SNDRV_TRIDENT_MAX_PAGES
; i
++) {
3384 trident
->tlb
.entries
[i
] = cpu_to_le32(trident
->tlb
.silent_page
.addr
& ~(SNDRV_TRIDENT_PAGE_SIZE
-1));
3385 trident
->tlb
.shadow_entries
[i
] = (unsigned long)trident
->tlb
.silent_page
.area
;
3388 /* use emu memory block manager code to manage tlb page allocation */
3389 trident
->tlb
.memhdr
= snd_util_memhdr_new(SNDRV_TRIDENT_PAGE_SIZE
* SNDRV_TRIDENT_MAX_PAGES
);
3390 if (trident
->tlb
.memhdr
== NULL
)
3393 trident
->tlb
.memhdr
->block_extra_size
= sizeof(struct snd_trident_memblk_arg
);
3398 * initialize 4D DX chip
3401 static void snd_trident_stop_all_voices(struct snd_trident
*trident
)
3403 outl(0xffffffff, TRID_REG(trident
, T4D_STOP_A
));
3404 outl(0xffffffff, TRID_REG(trident
, T4D_STOP_B
));
3405 outl(0, TRID_REG(trident
, T4D_AINTEN_A
));
3406 outl(0, TRID_REG(trident
, T4D_AINTEN_B
));
3409 static int snd_trident_4d_dx_init(struct snd_trident
*trident
)
3411 struct pci_dev
*pci
= trident
->pci
;
3412 unsigned long end_time
;
3414 /* reset the legacy configuration and whole audio/wavetable block */
3415 pci_write_config_dword(pci
, 0x40, 0); /* DDMA */
3416 pci_write_config_byte(pci
, 0x44, 0); /* ports */
3417 pci_write_config_byte(pci
, 0x45, 0); /* Legacy DMA */
3418 pci_write_config_byte(pci
, 0x46, 4); /* reset */
3420 pci_write_config_byte(pci
, 0x46, 0); /* release reset */
3423 /* warm reset of the AC'97 codec */
3424 outl(0x00000001, TRID_REG(trident
, DX_ACR2_AC97_COM_STAT
));
3426 outl(0x00000000, TRID_REG(trident
, DX_ACR2_AC97_COM_STAT
));
3427 /* DAC on, disable SB IRQ and try to force ADC valid signal */
3428 trident
->ac97_ctrl
= 0x0000004a;
3429 outl(trident
->ac97_ctrl
, TRID_REG(trident
, DX_ACR2_AC97_COM_STAT
));
3430 /* wait, until the codec is ready */
3431 end_time
= (jiffies
+ (HZ
* 3) / 4) + 1;
3433 if ((inl(TRID_REG(trident
, DX_ACR2_AC97_COM_STAT
)) & 0x0010) != 0)
3436 } while (time_after_eq(end_time
, jiffies
));
3437 snd_printk(KERN_ERR
"AC'97 codec ready error\n");
3441 snd_trident_stop_all_voices(trident
);
3447 * initialize 4D NX chip
3449 static int snd_trident_4d_nx_init(struct snd_trident
*trident
)
3451 struct pci_dev
*pci
= trident
->pci
;
3452 unsigned long end_time
;
3454 /* reset the legacy configuration and whole audio/wavetable block */
3455 pci_write_config_dword(pci
, 0x40, 0); /* DDMA */
3456 pci_write_config_byte(pci
, 0x44, 0); /* ports */
3457 pci_write_config_byte(pci
, 0x45, 0); /* Legacy DMA */
3459 pci_write_config_byte(pci
, 0x46, 1); /* reset */
3461 pci_write_config_byte(pci
, 0x46, 0); /* release reset */
3464 /* warm reset of the AC'97 codec */
3465 outl(0x00000001, TRID_REG(trident
, NX_ACR0_AC97_COM_STAT
));
3467 outl(0x00000000, TRID_REG(trident
, NX_ACR0_AC97_COM_STAT
));
3468 /* wait, until the codec is ready */
3469 end_time
= (jiffies
+ (HZ
* 3) / 4) + 1;
3471 if ((inl(TRID_REG(trident
, NX_ACR0_AC97_COM_STAT
)) & 0x0008) != 0)
3474 } while (time_after_eq(end_time
, jiffies
));
3475 snd_printk(KERN_ERR
"AC'97 codec ready error [0x%x]\n", inl(TRID_REG(trident
, NX_ACR0_AC97_COM_STAT
)));
3480 trident
->ac97_ctrl
= 0x00000002;
3481 outl(trident
->ac97_ctrl
, TRID_REG(trident
, NX_ACR0_AC97_COM_STAT
));
3482 /* disable SB IRQ */
3483 outl(NX_SB_IRQ_DISABLE
, TRID_REG(trident
, T4D_MISCINT
));
3485 snd_trident_stop_all_voices(trident
);
3487 if (trident
->tlb
.entries
!= NULL
) {
3489 /* enable virtual addressing via TLB */
3490 i
= trident
->tlb
.entries_dmaaddr
;
3492 outl(i
, TRID_REG(trident
, NX_TLBC
));
3494 outl(0, TRID_REG(trident
, NX_TLBC
));
3496 /* initialize S/PDIF */
3497 outl(trident
->spdif_bits
, TRID_REG(trident
, NX_SPCSTATUS
));
3498 outb(trident
->spdif_ctrl
, TRID_REG(trident
, NX_SPCTRL_SPCSO
+ 3));
3504 * initialize sis7018 chip
3506 static int snd_trident_sis_init(struct snd_trident
*trident
)
3510 if ((err
= snd_trident_sis_reset(trident
)) < 0)
3513 snd_trident_stop_all_voices(trident
);
3515 /* initialize S/PDIF */
3516 outl(trident
->spdif_bits
, TRID_REG(trident
, SI_SPDIF_CS
));
3521 /*---------------------------------------------------------------------------
3524 Description: This routine will create the device specific class for
3525 the 4DWave card. It will also perform basic initialization.
3527 Paramters: card - which card to create
3528 pci - interface to PCI bus resource info
3529 dma1ptr - playback dma buffer
3530 dma2ptr - capture dma buffer
3531 irqptr - interrupt resource info
3533 Returns: 4DWave device class private data
3535 ---------------------------------------------------------------------------*/
3537 int __devinit
snd_trident_create(struct snd_card
*card
,
3538 struct pci_dev
*pci
,
3540 int pcm_spdif_device
,
3541 int max_wavetable_size
,
3542 struct snd_trident
** rtrident
)
3544 struct snd_trident
*trident
;
3546 struct snd_trident_voice
*voice
;
3547 struct snd_trident_pcm_mixer
*tmix
;
3548 static struct snd_device_ops ops
= {
3549 .dev_free
= snd_trident_dev_free
,
3554 /* enable PCI device */
3555 if ((err
= pci_enable_device(pci
)) < 0)
3557 /* check, if we can restrict PCI DMA transfers to 30 bits */
3558 if (pci_set_dma_mask(pci
, DMA_30BIT_MASK
) < 0 ||
3559 pci_set_consistent_dma_mask(pci
, DMA_30BIT_MASK
) < 0) {
3560 snd_printk(KERN_ERR
"architecture does not support 30bit PCI busmaster DMA\n");
3561 pci_disable_device(pci
);
3565 trident
= kzalloc(sizeof(*trident
), GFP_KERNEL
);
3566 if (trident
== NULL
) {
3567 pci_disable_device(pci
);
3570 trident
->device
= (pci
->vendor
<< 16) | pci
->device
;
3571 trident
->card
= card
;
3573 spin_lock_init(&trident
->reg_lock
);
3574 spin_lock_init(&trident
->event_lock
);
3575 spin_lock_init(&trident
->voice_alloc
);
3576 if (pcm_streams
< 1)
3578 if (pcm_streams
> 32)
3580 trident
->ChanPCM
= pcm_streams
;
3581 if (max_wavetable_size
< 0 )
3582 max_wavetable_size
= 0;
3583 trident
->synth
.max_size
= max_wavetable_size
* 1024;
3586 trident
->midi_port
= TRID_REG(trident
, T4D_MPU401_BASE
);
3587 pci_set_master(pci
);
3589 if ((err
= pci_request_regions(pci
, "Trident Audio")) < 0) {
3591 pci_disable_device(pci
);
3594 trident
->port
= pci_resource_start(pci
, 0);
3596 if (request_irq(pci
->irq
, snd_trident_interrupt
, SA_INTERRUPT
|SA_SHIRQ
,
3597 "Trident Audio", trident
)) {
3598 snd_printk(KERN_ERR
"unable to grab IRQ %d\n", pci
->irq
);
3599 snd_trident_free(trident
);
3602 trident
->irq
= pci
->irq
;
3604 /* allocate 16k-aligned TLB for NX cards */
3605 trident
->tlb
.entries
= NULL
;
3606 trident
->tlb
.buffer
.area
= NULL
;
3607 if (trident
->device
== TRIDENT_DEVICE_ID_NX
) {
3608 if ((err
= snd_trident_tlb_alloc(trident
)) < 0) {
3609 snd_trident_free(trident
);
3614 trident
->spdif_bits
= trident
->spdif_pcm_bits
= SNDRV_PCM_DEFAULT_CON_SPDIF
;
3616 /* initialize chip */
3617 switch (trident
->device
) {
3618 case TRIDENT_DEVICE_ID_DX
:
3619 err
= snd_trident_4d_dx_init(trident
);
3621 case TRIDENT_DEVICE_ID_NX
:
3622 err
= snd_trident_4d_nx_init(trident
);
3624 case TRIDENT_DEVICE_ID_SI7018
:
3625 err
= snd_trident_sis_init(trident
);
3632 snd_trident_free(trident
);
3636 if ((err
= snd_device_new(card
, SNDRV_DEV_LOWLEVEL
, trident
, &ops
)) < 0) {
3637 snd_trident_free(trident
);
3641 if ((err
= snd_trident_mixer(trident
, pcm_spdif_device
)) < 0)
3644 /* initialise synth voices */
3645 for (i
= 0; i
< 64; i
++) {
3646 voice
= &trident
->synth
.voices
[i
];
3648 voice
->trident
= trident
;
3650 /* initialize pcm mixer entries */
3651 for (i
= 0; i
< 32; i
++) {
3652 tmix
= &trident
->pcm_mixer
[i
];
3653 tmix
->vol
= T4D_DEFAULT_PCM_VOL
;
3654 tmix
->pan
= T4D_DEFAULT_PCM_PAN
;
3655 tmix
->rvol
= T4D_DEFAULT_PCM_RVOL
;
3656 tmix
->cvol
= T4D_DEFAULT_PCM_CVOL
;
3659 snd_trident_enable_eso(trident
);
3661 snd_trident_proc_init(trident
);
3662 snd_card_set_dev(card
, &pci
->dev
);
3663 *rtrident
= trident
;
3667 /*---------------------------------------------------------------------------
3670 Description: This routine will free the device specific class for
3673 Paramters: trident - device specific private data for 4DWave card
3677 ---------------------------------------------------------------------------*/
3679 static int snd_trident_free(struct snd_trident
*trident
)
3681 snd_trident_free_gameport(trident
);
3682 snd_trident_disable_eso(trident
);
3683 // Disable S/PDIF out
3684 if (trident
->device
== TRIDENT_DEVICE_ID_NX
)
3685 outb(0x00, TRID_REG(trident
, NX_SPCTRL_SPCSO
+ 3));
3686 else if (trident
->device
== TRIDENT_DEVICE_ID_SI7018
) {
3687 outl(0, TRID_REG(trident
, SI_SERIAL_INTF_CTRL
));
3689 if (trident
->tlb
.buffer
.area
) {
3690 outl(0, TRID_REG(trident
, NX_TLBC
));
3691 if (trident
->tlb
.memhdr
)
3692 snd_util_memhdr_free(trident
->tlb
.memhdr
);
3693 if (trident
->tlb
.silent_page
.area
)
3694 snd_dma_free_pages(&trident
->tlb
.silent_page
);
3695 vfree(trident
->tlb
.shadow_entries
);
3696 snd_dma_free_pages(&trident
->tlb
.buffer
);
3698 if (trident
->irq
>= 0)
3699 free_irq(trident
->irq
, trident
);
3700 pci_release_regions(trident
->pci
);
3701 pci_disable_device(trident
->pci
);
3706 /*---------------------------------------------------------------------------
3707 snd_trident_interrupt
3709 Description: ISR for Trident 4DWave device
3711 Paramters: trident - device specific private data for 4DWave card
3713 Problems: It seems that Trident chips generates interrupts more than
3714 one time in special cases. The spurious interrupts are
3715 detected via sample timer (T4D_STIMER) and computing
3716 corresponding delta value. The limits are detected with
3717 the method try & fail so it is possible that it won't
3718 work on all computers. [jaroslav]
3722 ---------------------------------------------------------------------------*/
3724 static irqreturn_t
snd_trident_interrupt(int irq
, void *dev_id
, struct pt_regs
*regs
)
3726 struct snd_trident
*trident
= dev_id
;
3727 unsigned int audio_int
, chn_int
, stimer
, channel
, mask
, tmp
;
3729 struct snd_trident_voice
*voice
;
3731 audio_int
= inl(TRID_REG(trident
, T4D_MISCINT
));
3732 if ((audio_int
& (ADDRESS_IRQ
|MPU401_IRQ
)) == 0)
3734 if (audio_int
& ADDRESS_IRQ
) {
3735 // get interrupt status for all channels
3736 spin_lock(&trident
->reg_lock
);
3737 stimer
= inl(TRID_REG(trident
, T4D_STIMER
)) & 0x00ffffff;
3738 chn_int
= inl(TRID_REG(trident
, T4D_AINT_A
));
3741 outl(chn_int
, TRID_REG(trident
, T4D_AINT_A
)); /* ack */
3743 chn_int
= inl(TRID_REG(trident
, T4D_AINT_B
));
3746 for (channel
= 63; channel
>= 32; channel
--) {
3747 mask
= 1 << (channel
&0x1f);
3748 if ((chn_int
& mask
) == 0)
3750 voice
= &trident
->synth
.voices
[channel
];
3751 if (!voice
->pcm
|| voice
->substream
== NULL
) {
3752 outl(mask
, TRID_REG(trident
, T4D_STOP_B
));
3755 delta
= (int)stimer
- (int)voice
->stimer
;
3758 if ((unsigned int)delta
< voice
->spurious_threshold
) {
3759 /* do some statistics here */
3760 trident
->spurious_irq_count
++;
3761 if (trident
->spurious_irq_max_delta
< (unsigned int)delta
)
3762 trident
->spurious_irq_max_delta
= delta
;
3765 voice
->stimer
= stimer
;
3767 if (!voice
->isync3
) {
3768 tmp
= inw(TRID_REG(trident
, T4D_SBBL_SBCL
));
3769 if (trident
->bDMAStart
& 0x40)
3772 tmp
= voice
->isync_max
- tmp
;
3774 tmp
= inl(TRID_REG(trident
, NX_SPCTRL_SPCSO
)) & 0x00ffffff;
3776 if (tmp
< voice
->isync_mark
) {
3778 tmp
= voice
->isync_ESO
- 7;
3780 tmp
= voice
->isync_ESO
+ 2;
3781 /* update ESO for IRQ voice to preserve sync */
3782 snd_trident_stop_voice(trident
, voice
->number
);
3783 snd_trident_write_eso_reg(trident
, voice
, tmp
);
3784 snd_trident_start_voice(trident
, voice
->number
);
3786 } else if (voice
->isync2
) {
3788 /* write original ESO and update CSO for IRQ voice to preserve sync */
3789 snd_trident_stop_voice(trident
, voice
->number
);
3790 snd_trident_write_cso_reg(trident
, voice
, voice
->isync_mark
);
3791 snd_trident_write_eso_reg(trident
, voice
, voice
->ESO
);
3792 snd_trident_start_voice(trident
, voice
->number
);
3796 /* update CSO for extra voice to preserve sync */
3797 snd_trident_stop_voice(trident
, voice
->extra
->number
);
3798 snd_trident_write_cso_reg(trident
, voice
->extra
, 0);
3799 snd_trident_start_voice(trident
, voice
->extra
->number
);
3802 spin_unlock(&trident
->reg_lock
);
3803 snd_pcm_period_elapsed(voice
->substream
);
3804 spin_lock(&trident
->reg_lock
);
3806 outl(chn_int
, TRID_REG(trident
, T4D_AINT_B
)); /* ack */
3808 spin_unlock(&trident
->reg_lock
);
3810 if (audio_int
& MPU401_IRQ
) {
3811 if (trident
->rmidi
) {
3812 snd_mpu401_uart_interrupt(irq
, trident
->rmidi
->private_data
, regs
);
3814 inb(TRID_REG(trident
, T4D_MPUR0
));
3817 // outl((ST_TARGET_REACHED | MIXER_OVERFLOW | MIXER_UNDERFLOW), TRID_REG(trident, T4D_MISCINT));
3821 /*---------------------------------------------------------------------------
3822 snd_trident_attach_synthesizer
3824 Description: Attach synthesizer hooks
3826 Paramters: trident - device specific private data for 4DWave card
3830 ---------------------------------------------------------------------------*/
3831 int snd_trident_attach_synthesizer(struct snd_trident
*trident
)
3833 #if defined(CONFIG_SND_SEQUENCER) || (defined(MODULE) && defined(CONFIG_SND_SEQUENCER_MODULE))
3834 if (snd_seq_device_new(trident
->card
, 1, SNDRV_SEQ_DEV_ID_TRIDENT
,
3835 sizeof(struct snd_trident
*), &trident
->seq_dev
) >= 0) {
3836 strcpy(trident
->seq_dev
->name
, "4DWave");
3837 *(struct snd_trident
**)SNDRV_SEQ_DEVICE_ARGPTR(trident
->seq_dev
) = trident
;
3843 struct snd_trident_voice
*snd_trident_alloc_voice(struct snd_trident
* trident
, int type
, int client
, int port
)
3845 struct snd_trident_voice
*pvoice
;
3846 unsigned long flags
;
3849 spin_lock_irqsave(&trident
->voice_alloc
, flags
);
3850 if (type
== SNDRV_TRIDENT_VOICE_TYPE_PCM
) {
3851 idx
= snd_trident_allocate_pcm_channel(trident
);
3853 spin_unlock_irqrestore(&trident
->voice_alloc
, flags
);
3856 pvoice
= &trident
->synth
.voices
[idx
];
3859 pvoice
->capture
= 0;
3861 pvoice
->memblk
= NULL
;
3862 pvoice
->substream
= NULL
;
3863 spin_unlock_irqrestore(&trident
->voice_alloc
, flags
);
3866 if (type
== SNDRV_TRIDENT_VOICE_TYPE_SYNTH
) {
3867 idx
= snd_trident_allocate_synth_channel(trident
);
3869 spin_unlock_irqrestore(&trident
->voice_alloc
, flags
);
3872 pvoice
= &trident
->synth
.voices
[idx
];
3875 pvoice
->client
= client
;
3876 pvoice
->port
= port
;
3877 pvoice
->memblk
= NULL
;
3878 spin_unlock_irqrestore(&trident
->voice_alloc
, flags
);
3881 if (type
== SNDRV_TRIDENT_VOICE_TYPE_MIDI
) {
3883 spin_unlock_irqrestore(&trident
->voice_alloc
, flags
);
3887 void snd_trident_free_voice(struct snd_trident
* trident
, struct snd_trident_voice
*voice
)
3889 unsigned long flags
;
3890 void (*private_free
)(struct snd_trident_voice
*);
3893 if (voice
== NULL
|| !voice
->use
)
3895 snd_trident_clear_voices(trident
, voice
->number
, voice
->number
);
3896 spin_lock_irqsave(&trident
->voice_alloc
, flags
);
3897 private_free
= voice
->private_free
;
3898 private_data
= voice
->private_data
;
3899 voice
->private_free
= NULL
;
3900 voice
->private_data
= NULL
;
3902 snd_trident_free_pcm_channel(trident
, voice
->number
);
3904 snd_trident_free_synth_channel(trident
, voice
->number
);
3905 voice
->use
= voice
->pcm
= voice
->synth
= voice
->midi
= 0;
3906 voice
->capture
= voice
->spdif
= 0;
3907 voice
->sample_ops
= NULL
;
3908 voice
->substream
= NULL
;
3909 voice
->extra
= NULL
;
3910 spin_unlock_irqrestore(&trident
->voice_alloc
, flags
);
3912 private_free(voice
);
3915 static void snd_trident_clear_voices(struct snd_trident
* trident
, unsigned short v_min
, unsigned short v_max
)
3917 unsigned int i
, val
, mask
[2] = { 0, 0 };
3919 snd_assert(v_min
<= 63, return);
3920 snd_assert(v_max
<= 63, return);
3921 for (i
= v_min
; i
<= v_max
; i
++)
3922 mask
[i
>> 5] |= 1 << (i
& 0x1f);
3924 outl(mask
[0], TRID_REG(trident
, T4D_STOP_A
));
3925 val
= inl(TRID_REG(trident
, T4D_AINTEN_A
));
3926 outl(val
& ~mask
[0], TRID_REG(trident
, T4D_AINTEN_A
));
3929 outl(mask
[1], TRID_REG(trident
, T4D_STOP_B
));
3930 val
= inl(TRID_REG(trident
, T4D_AINTEN_B
));
3931 outl(val
& ~mask
[1], TRID_REG(trident
, T4D_AINTEN_B
));
3936 int snd_trident_suspend(struct pci_dev
*pci
, pm_message_t state
)
3938 struct snd_card
*card
= pci_get_drvdata(pci
);
3939 struct snd_trident
*trident
= card
->private_data
;
3941 trident
->in_suspend
= 1;
3942 snd_power_change_state(card
, SNDRV_CTL_POWER_D3hot
);
3943 snd_pcm_suspend_all(trident
->pcm
);
3944 snd_pcm_suspend_all(trident
->foldback
);
3945 snd_pcm_suspend_all(trident
->spdif
);
3947 snd_ac97_suspend(trident
->ac97
);
3948 snd_ac97_suspend(trident
->ac97_sec
);
3950 switch (trident
->device
) {
3951 case TRIDENT_DEVICE_ID_DX
:
3952 case TRIDENT_DEVICE_ID_NX
:
3954 case TRIDENT_DEVICE_ID_SI7018
:
3957 pci_disable_device(pci
);
3958 pci_save_state(pci
);
3962 int snd_trident_resume(struct pci_dev
*pci
)
3964 struct snd_card
*card
= pci_get_drvdata(pci
);
3965 struct snd_trident
*trident
= card
->private_data
;
3967 pci_restore_state(pci
);
3968 pci_enable_device(pci
);
3969 pci_set_master(pci
); /* to be sure */
3971 switch (trident
->device
) {
3972 case TRIDENT_DEVICE_ID_DX
:
3973 snd_trident_4d_dx_init(trident
);
3975 case TRIDENT_DEVICE_ID_NX
:
3976 snd_trident_4d_nx_init(trident
);
3978 case TRIDENT_DEVICE_ID_SI7018
:
3979 snd_trident_sis_init(trident
);
3983 snd_ac97_resume(trident
->ac97
);
3984 snd_ac97_resume(trident
->ac97_sec
);
3986 /* restore some registers */
3987 outl(trident
->musicvol_wavevol
, TRID_REG(trident
, T4D_MUSICVOL_WAVEVOL
));
3989 snd_trident_enable_eso(trident
);
3991 snd_power_change_state(card
, SNDRV_CTL_POWER_D0
);
3992 trident
->in_suspend
= 0;
3995 #endif /* CONFIG_PM */
3997 EXPORT_SYMBOL(snd_trident_alloc_voice
);
3998 EXPORT_SYMBOL(snd_trident_free_voice
);
3999 EXPORT_SYMBOL(snd_trident_start_voice
);
4000 EXPORT_SYMBOL(snd_trident_stop_voice
);
4001 EXPORT_SYMBOL(snd_trident_write_voice_regs
);
4002 /* trident_memory.c symbols */
4003 EXPORT_SYMBOL(snd_trident_synth_alloc
);
4004 EXPORT_SYMBOL(snd_trident_synth_free
);
4005 EXPORT_SYMBOL(snd_trident_synth_copy_from_user
);