revert between 56095 -> 55830 in arch
[AROS.git] / workbench / devs / AHI / Drivers / EMU10kx / emu10kx-main.c
blobdaa02d728101c9ea3ac14460f079bee9c0575d74
1 /*
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.
20 /******************************************************************************
21 ** WARNING *******************************************************************
22 *******************************************************************************
24 Note that you CANNOT base proprietary drivers on this particular
25 driver! Anything that is based on this driver has to be GPL:ed.
27 *******************************************************************************
28 ** WARNING *******************************************************************
29 ******************************************************************************/
32 #include <config.h>
34 #include <devices/ahi.h>
35 #include <exec/memory.h>
36 #include <libraries/ahi_sub.h>
38 #include <proto/ahi_sub.h>
39 #include <proto/exec.h>
40 #include <proto/utility.h>
42 #include <string.h>
44 #include "library.h"
45 #include "8010.h"
46 #include "emu10kx-misc.h"
47 #include "pci_wrapper.h"
50 /******************************************************************************
51 ** Globals ********************************************************************
52 ******************************************************************************/
54 #define FREQUENCIES 8
56 static const ULONG Frequencies[ FREQUENCIES ] =
58 8000, // ยต- and A-Law
59 11025, // CD/4
60 16000, // DAT/3
61 22050, // CD/2
62 24000, // DAT/2
63 32000, // DAT/1.5
64 44100, // CD
65 48000 // DAT
68 #define INPUTS 8
70 static const STRPTR Inputs[ INPUTS ] =
72 "Mixer",
73 "Line in",
74 "Mic",
75 "CD",
76 "Aux",
77 "Phone",
78 "Video",
79 "Mixer (mono)"
82 /* Not static since it's used in emu10kx-misc.c too */
83 const UWORD InputBits[ INPUTS ] =
85 AC97_RECMUX_STEREO_MIX,
86 AC97_RECMUX_LINE,
87 AC97_RECMUX_MIC,
88 AC97_RECMUX_CD,
89 AC97_RECMUX_AUX,
90 AC97_RECMUX_PHONE,
91 AC97_RECMUX_VIDEO,
92 AC97_RECMUX_MONO_MIX
96 #define OUTPUTS 2
98 static const STRPTR Outputs[ OUTPUTS ] =
100 "Front",
101 "Front & Rear"
105 /******************************************************************************
106 ** AHIsub_AllocAudio **********************************************************
107 ******************************************************************************/
109 ULONG
110 _AHIsub_AllocAudio( struct TagItem* taglist,
111 struct AHIAudioCtrlDrv* AudioCtrl,
112 struct DriverBase* AHIsubBase )
114 struct EMU10kxBase* EMU10kxBase = (struct EMU10kxBase*) AHIsubBase;
116 int card_num;
117 ULONG ret;
118 int i;
120 card_num = ( GetTagData( AHIDB_AudioID, 0, taglist) & 0x0000f000 ) >> 12;
122 if( card_num >= EMU10kxBase->cards_found ||
123 EMU10kxBase->driverdatas[ card_num ] == NULL )
125 Req( "No EMU10kxData for card %ld.", card_num );
126 return AHISF_ERROR;
128 else
130 struct EMU10kxData* dd = EMU10kxBase->driverdatas[ card_num ];
131 BOOL in_use;
133 AudioCtrl->ahiac_DriverData = dd;
135 ObtainSemaphore( &EMU10kxBase->semaphore );
136 in_use = ( dd->audioctrl != NULL );
137 if( !in_use )
139 dd->audioctrl = AudioCtrl;
141 ReleaseSemaphore( &EMU10kxBase->semaphore );
143 if( in_use )
145 return AHISF_ERROR;
148 /* Since the EMU10kx chips can play a voice at any sample rate, we
149 do not have to examine/modify AudioCtrl->ahiac_MixFreq here.
151 Had this not been the case, AudioCtrl->ahiac_MixFreq should be
152 set to the frequency we will use.
154 However, recording can only be performed at the fixed sampling
155 rates.
159 ret = AHISF_KNOWHIFI | AHISF_KNOWSTEREO | AHISF_KNOWMULTICHANNEL | \
160 AHISF_MIXING | AHISF_TIMING;
162 for( i = 0; i < FREQUENCIES; ++i )
164 if( AudioCtrl->ahiac_MixFreq == Frequencies[ i ] )
166 ret |= AHISF_CANRECORD;
167 break;
171 return ret;
176 /******************************************************************************
177 ** AHIsub_FreeAudio ***********************************************************
178 ******************************************************************************/
180 void
181 _AHIsub_FreeAudio( struct AHIAudioCtrlDrv* AudioCtrl,
182 struct DriverBase* AHIsubBase )
184 struct EMU10kxBase* EMU10kxBase = (struct EMU10kxBase*) AHIsubBase;
185 struct EMU10kxData* dd = (struct EMU10kxData*) AudioCtrl->ahiac_DriverData;
187 if( dd != NULL )
189 ObtainSemaphore( &EMU10kxBase->semaphore );
190 if( dd->audioctrl == AudioCtrl )
192 // Release it if we own it.
193 dd->audioctrl = NULL;
195 ReleaseSemaphore( &EMU10kxBase->semaphore );
197 AudioCtrl->ahiac_DriverData = NULL;
202 /******************************************************************************
203 ** AHIsub_Disable *************************************************************
204 ******************************************************************************/
206 void
207 _AHIsub_Disable( struct AHIAudioCtrlDrv* AudioCtrl,
208 struct DriverBase* AHIsubBase )
210 // V6 drivers do not have to preserve all registers
212 Disable();
216 /******************************************************************************
217 ** AHIsub_Enable **************************************************************
218 ******************************************************************************/
220 void
221 _AHIsub_Enable( struct AHIAudioCtrlDrv* AudioCtrl,
222 struct DriverBase* AHIsubBase )
224 // V6 drivers do not have to preserve all registers
226 Enable();
230 /******************************************************************************
231 ** AHIsub_Start ***************************************************************
232 ******************************************************************************/
234 ULONG
235 _AHIsub_Start( ULONG flags,
236 struct AHIAudioCtrlDrv* AudioCtrl,
237 struct DriverBase* AHIsubBase )
239 struct EMU10kxData* dd = (struct EMU10kxData*) AudioCtrl->ahiac_DriverData;
241 /* Stop playback/recording, free old buffers (if any) */
242 AHIsub_Stop( flags, AudioCtrl );
244 if( flags & AHISF_PLAY )
246 int num_voices;
247 int i;
248 ULONG dma_buffer_size;
249 ULONG dma_sample_frame_size;
251 /* Update cached/syncronized variables */
253 AHIsub_Update( AHISF_PLAY, AudioCtrl );
255 /* Allocate a new mixing buffer. Note: The buffer must be cleared, since
256 it might not be filled by the mixer software interrupt because of
257 pretimer/posttimer! */
259 dd->mix_buffer = AllocVec( AudioCtrl->ahiac_BuffSize,
260 MEMF_ANY | MEMF_PUBLIC | MEMF_CLEAR );
262 if( dd->mix_buffer == NULL )
264 Req( "Unable to allocate %ld bytes for mixing buffer.",
265 AudioCtrl->ahiac_BuffSize );
266 return AHIE_NOMEM;
269 /* Allocate 1 or 4 voice buffers large enough for 16-bit double-buffered
270 playback (mono, stereo or 8 channels) */
272 if( AudioCtrl->ahiac_Flags & AHIACF_STEREO ||
273 AudioCtrl->ahiac_Flags & AHIACF_MULTICHANNEL)
275 dma_sample_frame_size = 4;
276 dma_buffer_size = AudioCtrl->ahiac_MaxBuffSamples * dma_sample_frame_size;
278 else
280 dma_sample_frame_size = 2;
281 dma_buffer_size = AudioCtrl->ahiac_MaxBuffSamples * dma_sample_frame_size;
284 if( AudioCtrl->ahiac_Flags & AHIACF_MULTICHANNEL )
286 num_voices = 4;
288 // Disable front-to-center/LFE routing
289 emu10k1_set_volume_gpr( &dd->card, VOL_FRONT_CENTER, 0, VOL_5BIT);
290 emu10k1_set_volume_gpr( &dd->card, VOL_FRONT_LFE, 0, VOL_5BIT);
292 else
294 num_voices = 1;
296 // Enable front-to-center/LFE routing
297 emu10k1_set_volume_gpr( &dd->card, VOL_FRONT_CENTER, 100, VOL_5BIT);
298 emu10k1_set_volume_gpr( &dd->card, VOL_FRONT_LFE, 100, VOL_5BIT);
301 for( i = 0; i < num_voices; ++i )
303 if( emu10k1_voice_alloc_buffer( &dd->card,
304 &dd->voices[i].mem,
305 ( dma_buffer_size * 2 + PAGE_SIZE - 1 )
306 / PAGE_SIZE ) < 0 )
308 Req( "Unable to allocate voice buffer." );
309 return AHIE_NOMEM;
312 memset( dd->voices[i].mem.addr, 0, dma_buffer_size * 2 );
314 dd->voices[i].usage = VOICE_USAGE_PLAYBACK;
316 if( AudioCtrl->ahiac_Flags & AHIACF_STEREO ||
317 AudioCtrl->ahiac_Flags & AHIACF_MULTICHANNEL )
319 dd->voices[i].flags = VOICE_FLAGS_STEREO | VOICE_FLAGS_16BIT;
321 else
323 dd->voices[i].flags = VOICE_FLAGS_16BIT;
327 dd->voice_buffers_allocated = num_voices;
329 for( i = 0; i < num_voices; ++i )
331 if( emu10k1_voice_alloc( &dd->card, &dd->voices[i] ) < 0 )
333 Req( "Unable to allocate voice." );
334 return AHIE_UNKNOWN;
338 dd->voices_allocated = num_voices;
340 for( i = 0; i < num_voices; ++i )
342 dd->voices[i].initial_pitch = (u16) ( srToPitch( AudioCtrl->ahiac_MixFreq ) >> 8 );
343 dd->voices[i].pitch_target = SamplerateToLinearPitch( AudioCtrl->ahiac_MixFreq );
345 DPD(2, "Initial pitch --> %#x\n", dd->voice.initial_pitch);
347 /* start, startloop and endloop is unit sample frames, not bytes */
349 dd->voices[i].start = ( ( dd->voices[i].mem.emupageindex << 12 )
350 / dma_sample_frame_size );
351 dd->voices[i].endloop = dd->voices[i].start + AudioCtrl->ahiac_MaxBuffSamples * 2;
352 dd->voices[i].startloop = dd->voices[i].start;
354 /* Make interrupt routine start at the correct location */
356 dd->current_position = dd->current_length;
357 dd->current_buffers[i] = ( dd->voices[i].mem.addr +
358 dd->current_position * dma_sample_frame_size );
360 dd->voices[i].params[0].volume_target = 0xffff;
361 dd->voices[i].params[0].initial_fc = 0xff;
362 dd->voices[i].params[0].initial_attn = 0x00;
363 dd->voices[i].params[0].byampl_env_sustain = 0x7f;
364 dd->voices[i].params[0].byampl_env_decay = 0x7f;
366 if( dd->voices[i].flags & VOICE_FLAGS_STEREO )
368 if( dd->card.is_audigy )
370 static int routes[] = {
371 0x03020100, // Send FL/FR to ??/??, AHI_FRONT_L/MULTI_FRONT_R
372 0x03020504, // Send RL/RR to ??/??, AHI_REAR_L/AHI_REAR_R
373 0x03020706, // Send SL/SR to ??/??, AHI_SURROUND_L/AHI_SURROUND_R
374 0x03020908, // Send C/LFE to ??/??, AHI_CENTER,AHI_LFE
377 dd->voices[i].params[0].send_dcba = 0x000000ff;
378 dd->voices[i].params[0].send_hgfe = 0x00000000;
379 dd->voices[i].params[1].send_dcba = 0x0000ff00;
380 dd->voices[i].params[1].send_hgfe = 0x00000000;
382 dd->voices[i].params[0].send_routing = dd->voices[i].params[1].send_routing = routes[i];
383 dd->voices[i].params[0].send_routing2 = dd->voices[i].params[1].send_routing2 = 0x03020302;
385 /* dd->voices[i].params[0].send_dcba = 0x00ff00ff; */
386 /* dd->voices[i].params[0].send_hgfe = 0x00007f7f; */
387 /* dd->voices[i].params[1].send_dcba = 0xff00ff00; */
388 /* dd->voices[i].params[1].send_hgfe = 0x00007f7f; */
390 /* dd->voices[i].params[0].send_routing = dd->voices[i].params[1].send_routing = 0x03020100; */
391 /* dd->voices[i].params[0].send_routing2 = dd->voices[i].params[1].send_routing2 = 0x07060504; */
393 else
395 static int routes[] = {
396 0x3210, // Send FL/FR to ??/??, AHI_FRONT_L/MULTI_FRONT_R
397 0x3254, // Send RL/RR to ??/??, AHI_REAR_L/AHI_REAR_R
398 0x3276, // Send SL/SR to ??/??, AHI_SURROUND_L/AHI_SURROUND_R
399 0x3298, // Send C/LFE to ??/??, AHI_CENTER,AHI_LFE
402 dd->voices[i].params[0].send_dcba = 0x000000ff;
403 dd->voices[i].params[0].send_hgfe = 0;
404 dd->voices[i].params[1].send_dcba = 0x0000ff00;
405 dd->voices[i].params[1].send_hgfe = 0;
407 dd->voices[i].params[0].send_routing = dd->voices[i].params[1].send_routing = routes[i];
408 dd->voices[i].params[0].send_routing2 = dd->voices[i].params[1].send_routing2 = 0;
411 dd->voices[i].params[1].volume_target = 0xffff;
412 dd->voices[i].params[1].initial_fc = 0xff;
413 dd->voices[i].params[1].initial_attn = 0x00;
414 dd->voices[i].params[1].byampl_env_sustain = 0x7f;
415 dd->voices[i].params[1].byampl_env_decay = 0x7f;
417 else
419 if( dd->card.is_audigy )
421 dd->voices[i].params[0].send_dcba = 0xffffffff;
422 dd->voices[i].params[0].send_hgfe = 0x0000ffff;
424 dd->voices[i].params[0].send_routing = 0x03020100;
425 dd->voices[i].params[0].send_routing2 = 0x07060504;
427 else
429 dd->voices[i].params[0].send_dcba = 0x000ffff;
430 dd->voices[i].params[0].send_hgfe = 0;
432 dd->voices[i].params[0].send_routing = 0x3210;
433 dd->voices[i].params[0].send_routing2 = 0;
437 DPD(2, "voice: startloop=%x, endloop=%x\n",
438 dd->voice.startloop, dd->voice.endloop);
440 emu10k1_voice_playback_setup( &dd->voices[i] );
443 dd->playback_interrupt_enabled = TRUE;
445 /* Enable timer interrupts (TIMER_INTERRUPT_FREQUENCY Hz) */
447 emu10k1_timer_set( &dd->card, 48000 / TIMER_INTERRUPT_FREQUENCY );
448 emu10k1_irq_enable( &dd->card, INTE_INTERVALTIMERENB );
450 emu10k1_voices_start( dd->voices, num_voices, 0 );
452 dd->voices_started = num_voices;
454 dd->is_playing = TRUE;
457 if( flags & AHISF_RECORD )
459 int adcctl = 0;
460 /* Find out the recording frequency */
462 switch( AudioCtrl->ahiac_MixFreq )
464 case 48000:
465 adcctl = ADCCR_SAMPLERATE_48;
466 break;
468 case 44100:
469 adcctl = ADCCR_SAMPLERATE_44;
470 break;
472 case 32000:
473 adcctl = ADCCR_SAMPLERATE_32;
474 break;
476 case 24000:
477 adcctl = ADCCR_SAMPLERATE_24;
478 break;
480 case 22050:
481 adcctl = ADCCR_SAMPLERATE_22;
482 break;
484 case 16000:
485 adcctl = ADCCR_SAMPLERATE_16;
486 break;
488 case 11025:
489 adcctl = ADCCR_SAMPLERATE_11;
490 break;
492 case 8000:
493 adcctl = ADCCR_SAMPLERATE_8;
494 break;
496 default:
497 return AHIE_UNKNOWN;
500 if( dd->card.is_audigy )
501 adcctl |= A_ADCCR_LCHANENABLE | A_ADCCR_RCHANENABLE;
502 else
503 adcctl |= ADCCR_LCHANENABLE | ADCCR_RCHANENABLE;
505 /* Allocate a new recording buffer (page aligned!) */
506 dd->record_buffer = pci_alloc_consistent( dd->card.pci_dev,
507 RECORD_BUFFER_SAMPLES * 4,
508 &dd->record_dma_handle );
510 if( dd->record_buffer == NULL )
512 Req( "Unable to allocate %ld bytes for the recording buffer.",
513 RECORD_BUFFER_SAMPLES * 4 );
514 return AHIE_NOMEM;
517 SaveMixerState( dd );
518 UpdateMonitorMixer( dd );
520 #ifdef __AMIGAOS4__
521 // invalidate the whole record_buffer just to be on the safe side
522 CacheClearE( dd->record_buffer, RECORD_BUFFER_SAMPLES * 4, CACRF_InvalidateD );
523 #endif
525 sblive_writeptr( &dd->card, ADCBA, 0, dd->record_dma_handle );
526 sblive_writeptr( &dd->card, ADCBS, 0, RECORD_BUFFER_SIZE_VALUE );
527 sblive_writeptr( &dd->card, ADCCR, 0, adcctl );
529 dd->record_interrupt_enabled = TRUE;
531 /* Enable ADC interrupts */
533 emu10k1_irq_enable( &dd->card, INTE_ADCBUFENABLE );
535 dd->is_recording = TRUE;
538 return AHIE_OK;
542 /******************************************************************************
543 ** AHIsub_Update **************************************************************
544 ******************************************************************************/
546 void
547 _AHIsub_Update( ULONG flags,
548 struct AHIAudioCtrlDrv* AudioCtrl,
549 struct DriverBase* AHIsubBase )
551 struct EMU10kxData* dd = (struct EMU10kxData*) AudioCtrl->ahiac_DriverData;
553 dd->current_length = AudioCtrl->ahiac_BuffSamples;
555 if( AudioCtrl->ahiac_Flags & AHIACF_STEREO )
557 dd->current_size = dd->current_length * 4;
559 else
561 dd->current_size = dd->current_length * 2;
566 /******************************************************************************
567 ** AHIsub_Stop ****************************************************************
568 ******************************************************************************/
570 void
571 _AHIsub_Stop( ULONG flags,
572 struct AHIAudioCtrlDrv* AudioCtrl,
573 struct DriverBase* AHIsubBase )
575 struct EMU10kxData* dd = (struct EMU10kxData*) AudioCtrl->ahiac_DriverData;
577 if( flags & AHISF_PLAY )
579 int i;
580 dd->is_playing= FALSE;
582 if( dd->voices_started != 0 )
584 emu10k1_irq_disable( &dd->card, INTE_INTERVALTIMERENB );
586 // sblive_writeptr( &dd->card, CLIEL, dd->voice.num, 0 );
587 emu10k1_voices_stop( dd->voices, dd->voices_started );
588 dd->voices_started = 0;
591 for( i = 0; i < dd->voices_allocated; ++i )
593 emu10k1_voice_free( &dd->voices[i] );
596 dd->voices_allocated = 0;
598 for( i = 0; i < dd->voice_buffers_allocated; ++i )
600 emu10k1_voice_free_buffer( &dd->card, &dd->voices[i].mem );
603 dd->voice_buffers_allocated = 0;
605 memset( &dd->voices, 0, sizeof( dd->voices ) );
607 dd->current_length = 0;
608 dd->current_size = 0;
609 dd->current_buffers[0] = NULL;
610 dd->current_buffers[1] = NULL;
611 dd->current_buffers[2] = NULL;
612 dd->current_buffers[3] = NULL;
613 dd->current_position = 0;
615 FreeVec( dd->mix_buffer );
616 dd->mix_buffer = NULL;
619 if( flags & AHISF_RECORD )
621 emu10k1_irq_disable( &dd->card, INTE_ADCBUFENABLE );
623 sblive_writeptr( &dd->card, ADCCR, 0, 0 );
624 sblive_writeptr( &dd->card, ADCBS, 0, ADCBS_BUFSIZE_NONE );
626 if( dd->is_recording )
628 // Do not restore mixer unless they have been saved
629 RestoreMixerState( dd );
632 if( dd->record_buffer != NULL )
634 pci_free_consistent( dd->card.pci_dev,
635 RECORD_BUFFER_SAMPLES * 4,
636 dd->record_buffer,
637 dd->record_dma_handle );
640 dd->record_buffer = NULL;
641 dd->record_dma_handle = 0;
643 dd->is_recording = FALSE;
648 /******************************************************************************
649 ** AHIsub_GetAttr *************************************************************
650 ******************************************************************************/
652 IPTR
653 _AHIsub_GetAttr( ULONG attribute,
654 LONG argument,
655 IPTR def,
656 struct TagItem* taglist,
657 struct AHIAudioCtrlDrv* AudioCtrl,
658 struct DriverBase* AHIsubBase )
660 int i;
662 switch( attribute )
664 case AHIDB_Bits:
665 return 16;
667 case AHIDB_Frequencies:
668 return FREQUENCIES;
670 case AHIDB_Frequency: // Index->Frequency
671 return (LONG) Frequencies[ argument ];
673 case AHIDB_Index: // Frequency->Index
674 if( argument <= (LONG) Frequencies[ 0 ] )
676 return 0;
679 if( argument >= (LONG) Frequencies[ FREQUENCIES - 1 ] )
681 return FREQUENCIES-1;
684 for( i = 1; i < FREQUENCIES; i++ )
686 if( (LONG) Frequencies[ i ] > argument )
688 if( ( argument - (LONG) Frequencies[ i - 1 ] )
689 < ( (LONG) Frequencies[ i ] - argument ) )
691 return i-1;
693 else
695 return i;
700 return 0; // Will not happen
702 case AHIDB_Author:
703 return (IPTR) "Martin 'Leviticus' Blom, Bertrand Lee et al.";
705 case AHIDB_Copyright:
706 return (IPTR) "GNU GPL";
708 case AHIDB_Version:
709 return (IPTR) LibIDString;
711 case AHIDB_Annotation:
712 return (IPTR)
713 "Funded by Hyperion Entertainment. Based on the Linux driver.";
715 case AHIDB_Record:
716 return TRUE;
718 case AHIDB_FullDuplex:
719 return TRUE;
721 case AHIDB_Realtime:
722 return TRUE;
724 case AHIDB_MaxRecordSamples:
725 return RECORD_BUFFER_SAMPLES / 2;
727 case AHIDB_MinMonitorVolume:
728 return 0x00000;
730 case AHIDB_MaxMonitorVolume:
731 return 0x40000;
733 case AHIDB_MinInputGain:
734 return 0x10000;
736 case AHIDB_MaxInputGain:
737 return 0xD7450;
739 case AHIDB_MinOutputVolume:
740 return 0x00000;
742 case AHIDB_MaxOutputVolume:
743 return 0x40000;
745 case AHIDB_Inputs:
746 return INPUTS;
748 case AHIDB_Input:
749 return (IPTR) Inputs[ argument ];
751 case AHIDB_Outputs:
752 return OUTPUTS;
754 case AHIDB_Output:
755 return (IPTR) Outputs[ argument ];
757 default:
758 return def;
763 /******************************************************************************
764 ** AHIsub_HardwareControl *****************************************************
765 ******************************************************************************/
767 ULONG
768 _AHIsub_HardwareControl( ULONG attribute,
769 LONG argument,
770 struct AHIAudioCtrlDrv* AudioCtrl,
771 struct DriverBase* AHIsubBase )
773 struct EMU10kxData* dd = (struct EMU10kxData*) AudioCtrl->ahiac_DriverData;
775 switch( attribute )
777 case AHIC_MonitorVolume:
778 dd->monitor_volume = Linear2MixerGain( (Fixed) argument,
779 &dd->monitor_volume_bits );
780 if( dd->is_recording )
782 UpdateMonitorMixer( dd );
784 return TRUE;
786 case AHIC_MonitorVolume_Query:
787 return dd->monitor_volume;
789 case AHIC_InputGain:
790 dd->input_gain = Linear2RecordGain( (Fixed) argument,
791 &dd->input_gain_bits );
792 emu10k1_writeac97( &dd->card, AC97_RECORD_GAIN, dd->input_gain_bits );
793 return TRUE;
795 case AHIC_InputGain_Query:
796 return dd->input_gain;
798 case AHIC_OutputVolume:
799 dd->output_volume = Linear2MixerGain( (Fixed) argument,
800 &dd->output_volume_bits );
801 emu10k1_writeac97( &dd->card, AC97_PCMOUT_VOL, dd->output_volume_bits );
802 return TRUE;
804 case AHIC_OutputVolume_Query:
805 return dd->output_volume;
807 case AHIC_Input:
808 dd->input = argument;
809 emu10k1_writeac97( &dd->card, AC97_RECORD_SELECT, InputBits[ dd->input ] );
811 if( dd->is_recording )
813 UpdateMonitorMixer( dd );
816 return TRUE;
818 case AHIC_Input_Query:
819 return dd->input;
821 case AHIC_Output:
822 dd->output = argument;
824 if( dd->output == 0 )
826 emu10k1_set_volume_gpr( &dd->card, VOL_FRONT_REAR_L, 0, VOL_5BIT);
827 emu10k1_set_volume_gpr( &dd->card, VOL_FRONT_REAR_R, 0, VOL_5BIT);
829 else
831 emu10k1_set_volume_gpr( &dd->card, VOL_FRONT_REAR_L, 100, VOL_5BIT);
832 emu10k1_set_volume_gpr( &dd->card, VOL_FRONT_REAR_R, 100, VOL_5BIT);
834 return TRUE;
836 case AHIC_Output_Query:
837 return dd->output;
839 default:
840 return FALSE;