2 emu10kx.audio - AHI driver for SoundBlaster Live! series
3 Copyright (C) 2002-2005 Martin Blom <martin@blom.org>
5 This program is free software; you can redistribute it and/or
6 modify it under the terms of the GNU General Public License
7 as published by the Free Software Foundation; either version 2
8 of the License, or (at your option) any later version.
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
22 #include <exec/memory.h>
23 #include <proto/dos.h>
27 #include "emu10kx-interrupt.h"
28 #include "emu10kx-misc.h"
29 #include "pci_wrapper.h"
31 /* Global in emu10kx.c */
32 extern const UWORD InputBits
[];
34 /* Public functions in main.c */
35 int emu10k1_init(struct emu10k1_card
*card
);
36 void emu10k1_cleanup(struct emu10k1_card
*card
);
39 static void AddResetHandler(struct EMU10kxData
* dd
);
42 /******************************************************************************
43 ** DriverData allocation ******************************************************
44 ******************************************************************************/
46 // This code used to be in _AHIsub_AllocAudio(), but since we're now
47 // handling CAMD support too, it needs to be done at driver loading
50 INTGW( static, void, playbackinterrupt
, PlaybackInterrupt
);
51 INTGW( static, void, recordinterrupt
, RecordInterrupt
);
52 INTGW( static, ULONG
, emu10kxinterrupt
, EMU10kxInterrupt
);
56 AllocDriverData( APTR dev
,
57 struct DriverBase
* AHIsubBase
)
59 struct EMU10kxData
* dd
;
62 // FIXME: This should be non-cachable, DMA-able memory
63 dd
= AllocVec( sizeof( *dd
), MEMF_PUBLIC
| MEMF_CLEAR
);
67 Req( "Unable to allocate driver structure." );
72 dd
->ahisubbase
= AHIsubBase
;
74 dd
->interrupt
.is_Node
.ln_Type
= INTERRUPT_NODE_TYPE
;
75 dd
->interrupt
.is_Node
.ln_Pri
= 0;
76 dd
->interrupt
.is_Node
.ln_Name
= (STRPTR
) LibName
;
77 dd
->interrupt
.is_Code
= (APTR
) emu10kxinterrupt
;
78 dd
->interrupt
.is_Data
= (APTR
) dd
;
80 dd
->playback_interrupt
.is_Node
.ln_Type
= INTERRUPT_NODE_TYPE
;
81 dd
->playback_interrupt
.is_Node
.ln_Pri
= 0;
82 dd
->playback_interrupt
.is_Node
.ln_Name
= (STRPTR
) LibName
;
83 dd
->playback_interrupt
.is_Code
= (APTR
) playbackinterrupt
;
84 dd
->playback_interrupt
.is_Data
= (APTR
) dd
;
86 dd
->record_interrupt
.is_Node
.ln_Type
= INTERRUPT_NODE_TYPE
;
87 dd
->record_interrupt
.is_Node
.ln_Pri
= 0;
88 dd
->record_interrupt
.is_Node
.ln_Name
= (STRPTR
) LibName
;
89 dd
->record_interrupt
.is_Code
= (APTR
) recordinterrupt
;
90 dd
->record_interrupt
.is_Data
= (APTR
) dd
;
92 dd
->card
.pci_dev
= dev
;
94 // if( pci_set_dma_mask(dd->card.pci_dev, EMU10K1_DMA_MASK) )
96 // printf( "Unable to set DMA mask for card." );
100 command_word
= ahi_pci_read_config_word( PCI_COMMAND
, dd
->card
.pci_dev
);
101 command_word
|= PCI_COMMAND_IO
| PCI_COMMAND_MEMORY
| PCI_COMMAND_MASTER
;
102 ahi_pci_write_config_word( PCI_COMMAND
, command_word
, dd
->card
.pci_dev
);
104 dd
->pci_master_enabled
= TRUE
;
106 // FIXME: How about latency/pcibios_set_master()??
108 dd
->card
.iobase
= (unsigned long) ahi_pci_get_base_address(0, dev
);
109 dd
->card
.length
= ~( ahi_pci_get_base_size(0, dev
) & PCI_BASE_ADDRESS_IO_MASK
);
110 dd
->card
.irq
= ahi_pci_get_irq(dev
);
111 dd
->card
.chiprev
= ahi_pci_read_config_byte( PCI_REVISION_ID
, dev
);
112 dd
->card
.model
= ahi_pci_read_config_word( PCI_SUBSYSTEM_ID
, dev
);
113 dd
->card
.is_audigy
= ( ahi_pci_read_config_word(PCI_DEVICE_ID
, dev
) == PCI_DEVICE_ID_CREATIVE_AUDIGY
);
114 dd
->card
.is_aps
= ( ahi_pci_read_config_long( PCI_SUBSYSTEM_VENDOR_ID
, dev
) == EMU_APS_SUBID
);
116 ahi_pci_add_intserver( &dd
->interrupt
, dev
);
118 dd
->interrupt_added
= TRUE
;
120 /* Initialize chip */
121 if( emu10k1_init( &dd
->card
) < 0 )
123 Req( "Unable to initialize EMU10kx subsystem.");
127 dd
->emu10k1_initialized
= TRUE
;
130 /* Initialize mixer */
132 emu10k1_writeac97( &dd
->card
, AC97_RESET
, 0L);
136 if (emu10k1_readac97( &dd
->card
, AC97_RESET
) & 0x8000) {
137 Req( "ac97 codec not present.");
144 dd
->monitor_volume
= Linear2MixerGain( 0, &dd
->monitor_volume_bits
);
145 dd
->input_gain
= Linear2RecordGain( 0x10000, &dd
->input_gain_bits
);
146 dd
->output_volume
= Linear2MixerGain( 0x10000, &dd
->output_volume_bits
);
148 // No attenuation and natural tone for all outputs
149 emu10k1_writeac97( &dd
->card
, AC97_MASTER_VOL_STEREO
, 0x0000 );
150 emu10k1_writeac97( &dd
->card
, AC97_MASTER_VOL_MONO
, 0x0000 );
151 emu10k1_writeac97( &dd
->card
, AC97_MASTER_TONE
, 0x0f0f );
153 emu10k1_writeac97( &dd
->card
, AC97_RECORD_GAIN
, 0x0000 );
154 emu10k1_writeac97( &dd
->card
, AC97_RECORD_SELECT
, InputBits
[ 0 ] );
156 emu10k1_writeac97( &dd
->card
, AC97_PCMOUT_VOL
, 0x0808 );
157 emu10k1_writeac97( &dd
->card
, AC97_PCBEEP_VOL
, 0x0000 );
159 emu10k1_writeac97( &dd
->card
, AC97_LINEIN_VOL
, 0x0808 );
160 emu10k1_writeac97( &dd
->card
, AC97_MIC_VOL
, AC97_MUTE
| 0x0008 );
161 emu10k1_writeac97( &dd
->card
, AC97_CD_VOL
, 0x0808 );
162 emu10k1_writeac97( &dd
->card
, AC97_AUX_VOL
, 0x0808 );
163 emu10k1_writeac97( &dd
->card
, AC97_PHONE_VOL
, 0x0008 );
164 emu10k1_writeac97( &dd
->card
, AC97_VIDEO_VOL
, 0x0808 );
167 if (emu10k1_readac97( &dd
->card
, AC97_EXTENDED_ID
) & 0x0080 )
169 sblive_writeptr( &dd
->card
, AC97SLOT
, 0, AC97SLOT_CNTR
| AC97SLOT_LFE
);
171 // Disable center/LFE to front speakers (Not headphone; it's actially surround mix.)
172 emu10k1_writeac97( &dd
->card
, AC97_HEADPHONE_VOL
, AC97_MUTE
| 0x0808 );
174 // No attenuation for center/LFE
175 emu10k1_writeac97( &dd
->card
, AC97_SURROUND_MASTER
, 0x0 );
186 /******************************************************************************
187 ** DriverData deallocation ****************************************************
188 ******************************************************************************/
190 // And this code used to be in _AHIsub_FreeAudio().
193 FreeDriverData( struct EMU10kxData
* dd
,
194 struct DriverBase
* AHIsubBase
)
198 if( dd
->card
.pci_dev
!= NULL
)
200 if( dd
->emu10k1_initialized
)
202 emu10k1_cleanup( &dd
->card
);
205 if( dd
->pci_master_enabled
)
209 cmd
= ahi_pci_read_config_word( PCI_COMMAND
, dd
->card
.pci_dev
);
210 cmd
&= ~( PCI_COMMAND_IO
| PCI_COMMAND_MEMORY
| PCI_COMMAND_MASTER
);
211 ahi_pci_write_config_word( PCI_COMMAND
, cmd
, dd
->card
.pci_dev
);
215 if( dd
->interrupt_added
)
217 ahi_pci_rem_intserver( &dd
->interrupt
, dd
->card
.pci_dev
);
224 /******************************************************************************
225 ** Misc. **********************************************************************
226 ******************************************************************************/
229 SaveMixerState( struct EMU10kxData
* dd
)
231 dd
->ac97_mic
= emu10k1_readac97( &dd
->card
, AC97_MIC_VOL
);
232 dd
->ac97_cd
= emu10k1_readac97( &dd
->card
, AC97_CD_VOL
);
233 dd
->ac97_video
= emu10k1_readac97( &dd
->card
, AC97_VIDEO_VOL
);
234 dd
->ac97_aux
= emu10k1_readac97( &dd
->card
, AC97_AUX_VOL
);
235 dd
->ac97_linein
= emu10k1_readac97( &dd
->card
, AC97_LINEIN_VOL
);
236 dd
->ac97_phone
= emu10k1_readac97( &dd
->card
, AC97_PHONE_VOL
);
241 RestoreMixerState( struct EMU10kxData
* dd
)
243 emu10k1_writeac97( &dd
->card
, AC97_MIC_VOL
, dd
->ac97_mic
);
244 emu10k1_writeac97( &dd
->card
, AC97_CD_VOL
, dd
->ac97_cd
);
245 emu10k1_writeac97( &dd
->card
, AC97_VIDEO_VOL
, dd
->ac97_video
);
246 emu10k1_writeac97( &dd
->card
, AC97_AUX_VOL
, dd
->ac97_aux
);
247 emu10k1_writeac97( &dd
->card
, AC97_LINEIN_VOL
, dd
->ac97_linein
);
248 emu10k1_writeac97( &dd
->card
, AC97_PHONE_VOL
, dd
->ac97_phone
);
252 UpdateMonitorMixer( struct EMU10kxData
* dd
)
254 int i
= InputBits
[ dd
->input
];
255 UWORD m
= dd
->monitor_volume_bits
& 0x801f;
256 UWORD s
= dd
->monitor_volume_bits
;
257 UWORD mm
= AC97_MUTE
| 0x0008;
258 UWORD sm
= AC97_MUTE
| 0x0808;
260 if( i
== AC97_RECMUX_STEREO_MIX
||
261 i
== AC97_RECMUX_MONO_MIX
)
263 // Use the original mixer settings
264 RestoreMixerState( dd
);
268 emu10k1_writeac97( &dd
->card
, AC97_MIC_VOL
,
269 i
== AC97_RECMUX_MIC
? m
: mm
);
271 emu10k1_writeac97( &dd
->card
, AC97_CD_VOL
,
272 i
== AC97_RECMUX_CD
? s
: sm
);
274 emu10k1_writeac97( &dd
->card
, AC97_VIDEO_VOL
,
275 i
== AC97_RECMUX_VIDEO
? s
: sm
);
277 emu10k1_writeac97( &dd
->card
, AC97_AUX_VOL
,
278 i
== AC97_RECMUX_AUX
? s
: sm
);
280 emu10k1_writeac97( &dd
->card
, AC97_LINEIN_VOL
,
281 i
== AC97_RECMUX_LINE
? s
: sm
);
283 emu10k1_writeac97( &dd
->card
, AC97_PHONE_VOL
,
284 i
== AC97_RECMUX_PHONE
? m
: mm
);
290 Linear2MixerGain( Fixed linear
,
293 static const Fixed gain
[ 33 ] =
332 while( linear
< gain
[ v
] )
339 *bits
= 0x8000; // Mute
343 *bits
= ( v
<< 8 ) | v
;
346 // KPrintF( "l2mg %08lx -> %08lx (%04lx)\n", linear, gain[ v ], *bits );
351 Linear2RecordGain( Fixed linear
,
354 static const Fixed gain
[ 17 ] =
377 while( linear
< gain
[ v
] )
384 *bits
= 0x8000; // Mute
388 *bits
= ( ( 15 - v
) << 8 ) | ( 15 - v
);
396 SamplerateToLinearPitch( ULONG samplingrate
)
398 samplingrate
= (samplingrate
<< 8) / 375;
399 return (samplingrate
>> 1) + (samplingrate
& 1);
404 static ULONG
ResetHandler(struct ExceptionContext
*ctx
, struct ExecBase
*pExecBase
, struct EMU10kxData
* dd
)
406 emu10k1_irq_disable( &dd
->card
, INTE_INTERVALTIMERENB
);
407 emu10k1_voices_stop( dd
->voices
, dd
->voices_started
);
413 void AddResetHandler(struct EMU10kxData
* dd
)
415 static struct Interrupt interrupt
;
417 interrupt
.is_Code
= (void (*)())ResetHandler
;
418 interrupt
.is_Data
= (APTR
) dd
;
419 interrupt
.is_Node
.ln_Pri
= 0;
420 interrupt
.is_Node
.ln_Type
= NT_EXTINTERRUPT
;
421 interrupt
.is_Node
.ln_Name
= "reset handler";
423 AddResetCallback( &interrupt
);