2 Copyright © 2005-2013, Davy Wentzler. All rights reserved.
3 Copyright © 2010-2013, The AROS Development Team. All rights reserved.
10 #include <proto/expansion.h>
12 extern struct UtilityIFace
* IUtility
;
13 extern struct AHIsubIFace
* IAHIsub
;
14 extern struct MMUIFace
* IMMU
;
17 #include <devices/ahi.h>
18 #include <exec/memory.h>
19 #include <libraries/ahi_sub.h>
21 #include <proto/ahi_sub.h>
22 #include <proto/exec.h>
23 #include <proto/dos.h>
24 #include <proto/utility.h>
31 #include "pci_wrapper.h"
34 #include <aros/debug.h>
35 #define DebugPrintF bug
38 /******************************************************************************
39 ** Globals ********************************************************************
40 ******************************************************************************/
42 #define FREQUENCIES 11
44 static const ULONG Frequencies
[ FREQUENCIES
] =
61 static const STRPTR Inputs
[ INPUTS
] =
73 /* Not static since it's used in misc.c too */
74 const UWORD InputBits
[ INPUTS
] =
81 AC97_RECMUX_STEREO_MIX
,
90 BOOL
ac97_wait_idle2(struct CardData
*card
);
92 static const STRPTR Outputs
[ OUTPUTS
] =
97 inline unsigned int codec_xread(struct CardData
*card
)
99 return pci_inl(VIA_REG_AC97
, card
);
103 inline void codec_xwrite(struct CardData
*card
, unsigned int val
)
105 pci_outl(val
, VIA_REG_AC97
, card
);
108 int codec_ready(struct CardData
*card
)
110 unsigned int timeout
= 100; /* 1ms */
115 val
= codec_xread(card
);
116 if (! (val
& VIA_REG_AC97_BUSY
))
121 snd_printk("(codec_ready()) AC97 codec not ready!\n");
125 int codec_valid(struct CardData
*card
)
127 unsigned int timeout
= 1000; /* 1ms */
128 unsigned int val
, val1
;
129 unsigned int stat
= VIA_REG_AC97_PRIMARY_VALID
;
131 while (timeout
-- > 0) {
132 val
= codec_xread(card
);
133 val1
= val
& (VIA_REG_AC97_BUSY
| stat
);
141 void codec_wait(struct CardData
*card
)
144 err
= codec_ready(card
);
148 void codec_write(struct CardData
*card
,
154 xval
= VIA_REG_AC97_CODEC_ID_PRIMARY
;
155 xval
<<= VIA_REG_AC97_CODEC_ID_SHIFT
;
156 xval
|= reg
<< VIA_REG_AC97_CMD_SHIFT
;
157 xval
|= val
<< VIA_REG_AC97_DATA_SHIFT
;
159 codec_xwrite(card
, xval
);
164 BOOL
ac97_wait_idle(struct CardData
*card
)
166 unsigned long tul
= 0;
168 unsigned long iobase
= 0;
169 struct PCIDevice
*dev
= card
->pci_dev
;
173 if( !( ( tul
= pci_inl(VIA_REG_AC97
, card
)) & VIA_REG_AC97_BUSY
) )
178 DebugPrintF("Timed out waiting for AC97 controller!\n");
182 unsigned short codec_read(struct CardData
*card
, unsigned char reg
)
189 xval
|= VIA_REG_AC97_PRIMARY_VALID
;
190 xval
|= VIA_REG_AC97_READ
;
191 xval
|= (reg
& 0x7f) << VIA_REG_AC97_CMD_SHIFT
;
193 ac97_wait_idle2(card
);
194 codec_xwrite(card
, xval
);
196 ac97_wait_idle2(card
);
197 xval
= codec_xread(card
);
199 data
= (xval
& 0xFFFF);
201 if ( !( xval
& VIA_REG_AC97_PRIMARY_VALID
) )
203 DebugPrintF("Codec read failed!\n");
210 //IO base 0 registers
211 static const unsigned char VIA_AC97_RX
= 0x80; //ac97 register
212 static const unsigned long VIA_AC97_RX_PRIMARY_ID
= 0x00; //primamry codec ID (RW)
213 static const unsigned long VIA_AC97_RX_SECODARY_ID
= 0x40000000; //secondary codec ID (RW)
214 static const unsigned long VIA_AC97_RX_SECODARY_VALID
= 0x08000000; //secondary valid data/status/index (RWC)
215 static const unsigned long VIA_AC97_RX_PRIMARY_VALID
= 0x02000000; //primary valid data etc. (RWC)
216 static const unsigned long VIA_AC97_RX_BUSY
= 0x01000000; //controller busy (R)
217 static const unsigned long VIA_AC97_RX_READ
= 0x00800000; //read/write select (RW)
219 static const unsigned char VIA_AC97_RX_SHIFT
= 0x10; //register shift
220 static const unsigned long VIA_AC97_RX_DATA_MASK
= 0xffff; //data mask
222 BOOL
ac97_wait_idle2(struct CardData
*card
)
224 struct PCIDevice
*dev
= card
->pci_dev
;
225 unsigned long tul
= 0;
226 int cnt
= 26; //..about half a second, for no good reason
227 unsigned long iobase
= card
->iobase
;
231 if( !( ( tul
= pci_inl(VIA_AC97_RX
, card
) ) & VIA_AC97_RX_BUSY
) )
236 DebugPrintF("Timed out waiting for AC97 controller! VIA_AC97_RX = %lx\n", tul
);
241 //note: this only reads the primary codec
242 BOOL
ac97_read_reg(struct CardData
*card
, unsigned char reg
, unsigned short *data
)
244 struct PCIDevice
*dev
= card
->pci_dev
;
245 unsigned long iobase
= card
->iobase
;
246 //set up with required codec register, read mode, and clear the primary codec valid flag
247 unsigned long tul
= ( ( reg
<< VIA_AC97_RX_SHIFT
) | VIA_AC97_RX_READ
| VIA_AC97_RX_PRIMARY_VALID
);
249 //wait for the controller to become free, and write the command
250 ac97_wait_idle2(card
);
251 pci_outl(tul
, VIA_AC97_RX
, card
);
253 //wait for the controller to become free, and read the result
254 ac97_wait_idle2(card
);
255 tul
= pci_inl(VIA_AC97_RX
, card
);
256 *data
= ( tul
& VIA_AC97_RX_DATA_MASK
);
258 //complain if the data/register etc. is invalid...
259 if( !( tul
& VIA_AC97_RX_PRIMARY_VALID
) )
261 DebugPrintF("Info: (ac97_read_reg) Primary codec operation failed!\n");
273 static void set_table_ptr(struct CardData
*card
, BOOL Play
)
275 struct PCIDevice
*dev
= card
->pci_dev
;
285 stack
= IExec
->SuperState();
286 phys_addr
= IMMU
->GetPhysicalAddress(card
->play_idx_table
);
287 IExec
->UserState(stack
);
289 phys_addr
= (ULONG
)card
->play_idx_table
;
292 pci_outl(phys_addr
, 4, card
);
297 stack
= IExec
->SuperState();
298 phys_addr
= IMMU
->GetPhysicalAddress(card
->rec_idx_table
);
299 IExec
->UserState(stack
);
301 phys_addr
= (ULONG
)card
->rec_idx_table
;
304 pci_outl(phys_addr
, 4 + RECORD
, card
);
314 #define tolittle(a) ((((ULONG) (a) & 0xFF000000) >> 24) | \
315 (((ULONG) (a) & 0x00FF0000) >> 8) | \
316 (((ULONG) (a) & 0x0000FF00) << 8) | \
317 (((ULONG) (a) & 0x000000FF) << 24))
319 #define tolittle(a) AROS_LONG2LE(a)
322 static int build_via_table(struct CardData
*card
, APTR sgbuf1
, APTR sgbuf2
, int OneBufferSize
, struct snd_via_sg_table
**idx
,
323 APTR
*idx_nonaligned
)
325 struct PCIDevice
*dev
= card
->pci_dev
;
332 *idx
= pci_alloc_consistent(sizeof(**idx
) * 4, idx_nonaligned
);
335 stack
= IExec
->SuperState();
336 phys_addr
= IMMU
->GetPhysicalAddress(sgbuf1
);
337 IExec
->UserState(stack
);
339 phys_addr
= (ULONG
)sgbuf1
;
342 (*idx
)[0].offset
= (APTR
) tolittle(phys_addr
);
343 (*idx
)[0].size
= tolittle( (OneBufferSize
) | VIA_TBL_BIT_FLAG
);
346 stack
= IExec
->SuperState();
347 phys_addr
= IMMU
->GetPhysicalAddress(sgbuf2
);
348 IExec
->UserState(stack
);
350 phys_addr
= (ULONG
)sgbuf2
;
353 (*idx
)[1].offset
= (APTR
) tolittle(phys_addr
);
354 (*idx
)[1].size
= tolittle( (OneBufferSize
) | VIA_TBL_BIT_EOL
);
356 CacheClearE(*idx
, sizeof(**idx
) * 4, CACRF_ClearD
);
357 //DebugPrintF("===> play_idx_table at %lx, %lx\n", *idx, *idx_nonaligned);
363 /******************************************************************************
364 ** AHIsub_AllocAudio **********************************************************
365 ******************************************************************************/
368 _AHIsub_AllocAudio( struct TagItem
* taglist
,
369 struct AHIAudioCtrlDrv
* AudioCtrl
,
370 struct DriverBase
* AHIsubBase
)
372 struct CardBase
* CardBase
= (struct CardBase
*) AHIsubBase
;
380 card_num
= (GetTagData( AHIDB_AudioID
, 0, taglist
) & 0x0000f000 ) >> 12;
382 if( card_num
>= CardBase
->cards_found
||
383 CardBase
->driverdatas
[ card_num
] == NULL
)
385 DebugPrintF("no date for card = %ld\n", card_num
);
386 Req( "No CardData for card %ld.", card_num
);
392 struct PCIDevice
*dev
;
393 struct CardData
*card
;
396 card
= CardBase
->driverdatas
[ card_num
];
397 AudioCtrl
->ahiac_DriverData
= card
;
399 ObtainSemaphore( &CardBase
->semaphore
);
400 in_use
= ( card
->audioctrl
!= NULL
);
403 card
->audioctrl
= AudioCtrl
;
405 ReleaseSemaphore( &CardBase
->semaphore
);
413 card
->playback_interrupt_enabled
= FALSE
;
414 card
->record_interrupt_enabled
= FALSE
;
416 for( i
= 1; i
< FREQUENCIES
; i
++ )
418 if( (ULONG
) Frequencies
[ i
] > AudioCtrl
->ahiac_MixFreq
)
420 if ( ( AudioCtrl
->ahiac_MixFreq
- (LONG
) Frequencies
[ i
- 1 ] ) < ( (LONG
) Frequencies
[ i
] - AudioCtrl
->ahiac_MixFreq
) )
435 ret
= AHISF_KNOWHIFI
| AHISF_KNOWSTEREO
| AHISF_MIXING
| AHISF_TIMING
;
438 for( i
= 0; i
< FREQUENCIES
; ++i
)
440 if( AudioCtrl
->ahiac_MixFreq
== Frequencies
[ i
] )
442 ret
|= AHISF_CANRECORD
;
452 /******************************************************************************
453 ** AHIsub_FreeAudio ***********************************************************
454 ******************************************************************************/
457 _AHIsub_FreeAudio( struct AHIAudioCtrlDrv
* AudioCtrl
,
458 struct DriverBase
* AHIsubBase
)
460 struct CardBase
* CardBase
= (struct CardBase
*) AHIsubBase
;
461 struct CardData
* card
= (struct CardData
*) AudioCtrl
->ahiac_DriverData
;
465 ObtainSemaphore( &CardBase
->semaphore
);
466 if( card
->audioctrl
== AudioCtrl
)
468 // Release it if we own it.
469 card
->audioctrl
= NULL
;
471 ReleaseSemaphore( &CardBase
->semaphore
);
473 AudioCtrl
->ahiac_DriverData
= NULL
;
478 /******************************************************************************
479 ** AHIsub_Disable *************************************************************
480 ******************************************************************************/
483 _AHIsub_Disable( struct AHIAudioCtrlDrv
* AudioCtrl
,
484 struct DriverBase
* AHIsubBase
)
486 struct CardBase
* CardBase
= (struct CardBase
*) AHIsubBase
;
488 // V6 drivers do not have to preserve all registers
494 /******************************************************************************
495 ** AHIsub_Enable **************************************************************
496 ******************************************************************************/
499 _AHIsub_Enable( struct AHIAudioCtrlDrv
* AudioCtrl
,
500 struct DriverBase
* AHIsubBase
)
502 struct CardBase
* CardBase
= (struct CardBase
*) AHIsubBase
;
504 // V6 drivers do not have to preserve all registers
510 /******************************************************************************
511 ** AHIsub_Start ***************************************************************
512 ******************************************************************************/
515 _AHIsub_Start( ULONG flags
,
516 struct AHIAudioCtrlDrv
* AudioCtrl
,
517 struct DriverBase
* AHIsubBase
)
519 struct CardBase
* CardBase
= (struct CardBase
*) AHIsubBase
;
520 struct CardData
* card
= (struct CardData
*) AudioCtrl
->ahiac_DriverData
;
521 UWORD PlayCtrlFlags
= 0, RecCtrlFlags
= 0;
522 ULONG dma_buffer_size
= 0;
526 //channel_reset(card);
527 codec_write(card
, 0x2, 0);
528 codec_write(card
, 0x08, 0x0F0F);
529 codec_write(card
, 0x0A, 0x8000);
530 codec_write(card
, 0x18, 0x0808);
532 uval
= codec_read(card
, 0x2A);
533 codec_write(card
, 0x2A, uval
| 0x1); // enable VRA
534 codec_write(card
, 0x2C, AudioCtrl
->ahiac_MixFreq
);
537 if( flags
& AHISF_PLAY
)
540 ULONG dma_sample_frame_size
;
543 unsigned short cod
, ChannelsFlag
= 0;
545 card
->mix_buffer
= AllocVec( AudioCtrl
->ahiac_BuffSize
, MEMF_PUBLIC
| MEMF_CLEAR
);
547 if( card
->mix_buffer
== NULL
)
549 Req( "Unable to allocate %ld bytes for mixing buffer.",
550 AudioCtrl
->ahiac_BuffSize
);
554 /* Allocate a buffer large enough for 16-bit double-buffered
555 playback (mono or stereo) */
558 if( AudioCtrl
->ahiac_Flags
& AHIACF_STEREO
)
560 dma_sample_frame_size
= 4;
561 dma_buffer_size
= AudioCtrl
->ahiac_MaxBuffSamples
* dma_sample_frame_size
;
565 dma_sample_frame_size
= 2;
566 dma_buffer_size
= AudioCtrl
->ahiac_MaxBuffSamples
* dma_sample_frame_size
;
569 //DebugPrintF("dma_buffer_size = %ld, %lx\n", dma_buffer_size, dma_buffer_size);
571 card
->playback_buffer1
= pci_alloc_consistent(dma_buffer_size
, &card
->playback_buffer1_nonaligned
);
572 card
->playback_buffer2
= pci_alloc_consistent(dma_buffer_size
, &card
->playback_buffer2_nonaligned
);
574 if (!card
->playback_buffer1
)
576 Req( "Unable to allocate playback buffer." );
580 CacheClearE(card
->playback_buffer1
, dma_buffer_size
, CACRF_ClearD
);
581 CacheClearE(card
->playback_buffer2
, dma_buffer_size
, CACRF_ClearD
);
583 card
->current_bytesize
= dma_buffer_size
;
584 card
->current_frames
= AudioCtrl
->ahiac_MaxBuffSamples
;
585 card
->current_buffer
= card
->playback_buffer1
;
586 card
->playback_interrupt_enabled
= TRUE
;
588 build_via_table(card
, card
->playback_buffer1
, card
->playback_buffer2
, dma_buffer_size
, &card
->play_idx_table
, &card
->play_idx_table_nonaligned
);
589 set_table_ptr(card
, TRUE
);
591 pci_outb(VIA_REG_TYPE_AUTOSTART
| 0x40 |
593 VIA_REG_TYPE_STEREO
|
594 VIA_REG_TYPE_INT_LSAMPLE
|
595 VIA_REG_TYPE_INT_EOL
|
596 VIA_REG_TYPE_INT_FLAG
,
597 VIA_REG_OFFSET_TYPE
, card
);
601 card
->is_playing
= TRUE
;
604 if( flags
& AHISF_RECORD
)
608 card
->current_record_bytesize
= RECORD_BUFFER_SAMPLES
* 4;
610 /* Allocate a new recording buffer (page aligned!) */
611 card
->record_buffer1
= pci_alloc_consistent(card
->current_record_bytesize
, &card
->record_buffer1_nonaligned
);
612 card
->record_buffer2
= pci_alloc_consistent(card
->current_record_bytesize
, &card
->record_buffer2_nonaligned
);
614 if( card
->record_buffer1
== NULL
)
616 Req( "Unable to allocate %ld bytes for the recording buffer.", card
->current_record_bytesize
);
620 SaveMixerState( card
);
621 UpdateMonitorMixer( card
);
623 card
->record_interrupt_enabled
= TRUE
;
627 build_via_table(card
, card
->record_buffer1
, card
->record_buffer2
, card
->current_record_bytesize
, &card
->rec_idx_table
, &card
->rec_idx_table_nonaligned
);
628 set_table_ptr(card
, FALSE
);
630 pci_outb(VIA_REG_TYPE_AUTOSTART
| 0x40 |
632 VIA_REG_TYPE_STEREO
|
633 VIA_REG_TYPE_INT_EOL
|
634 VIA_REG_TYPE_INT_FLAG
,
635 VIA_REG_OFFSET_TYPE
+ RECORD
,
638 card
->is_recording
= TRUE
;
639 card
->current_record_buffer
= card
->record_buffer1
;
643 if( flags
& AHISF_PLAY
)
647 val
= VIA_REG_CTRL_START
;
648 pci_outb(val
, VIA_REG_OFFSET_CONTROL
, card
);
651 if( flags
& AHISF_RECORD
)
655 val
= VIA_REG_CTRL_START
;
656 pci_outb(val
, VIA_REG_OFFSET_CONTROL
+ RECORD
, card
);
663 /******************************************************************************
664 ** AHIsub_Update **************************************************************
665 ******************************************************************************/
668 _AHIsub_Update( ULONG flags
,
669 struct AHIAudioCtrlDrv
* AudioCtrl
,
670 struct DriverBase
* AHIsubBase
)
672 struct CardBase
* CardBase
= (struct CardBase
*) AHIsubBase
;
673 struct CardData
* card
= (struct CardData
*) AudioCtrl
->ahiac_DriverData
;
675 card
->current_frames
= AudioCtrl
->ahiac_BuffSamples
;
677 if( AudioCtrl
->ahiac_Flags
& AHIACF_STEREO
)
679 card
->current_bytesize
= card
->current_frames
* 4;
683 card
->current_bytesize
= card
->current_frames
* 2;
688 /******************************************************************************
689 ** AHIsub_Stop ****************************************************************
690 ******************************************************************************/
693 _AHIsub_Stop( ULONG flags
,
694 struct AHIAudioCtrlDrv
* AudioCtrl
,
695 struct DriverBase
* AHIsubBase
)
697 struct CardBase
* CardBase
= (struct CardBase
*) AHIsubBase
;
698 struct CardData
* card
= (struct CardData
*) AudioCtrl
->ahiac_DriverData
;
699 struct PCIDevice
*dev
= card
->pci_dev
;
703 val
= VIA_REG_CTRL_TERMINATE
;
705 if( flags
& AHISF_PLAY
&& card
->is_playing
)
707 pci_outb(val
, VIA_REG_OFFSET_CONTROL
, card
);
708 card
->is_playing
= FALSE
;
710 if (card
->current_bytesize
> 0)
712 pci_free_consistent(card
->playback_buffer1
);
713 pci_free_consistent(card
->playback_buffer2
);
716 card
->current_bytesize
= 0;
717 card
->current_frames
= 0;
718 card
->current_buffer
= NULL
;
720 if ( card
->mix_buffer
)
721 FreeVec( card
->mix_buffer
);
722 card
->mix_buffer
= NULL
;
723 card
->playback_interrupt_enabled
= FALSE
;
725 if (card
->play_idx_table_nonaligned
)
727 FreeVec(card
->play_idx_table_nonaligned
);
729 card
->play_idx_table
= NULL
;
732 if( flags
& AHISF_RECORD
&& card
->is_recording
)
734 unsigned short rec_ctl
;
736 pci_outb(val
, VIA_REG_OFFSET_CONTROL
+ RECORD
, card
);
737 if( card
->is_recording
)
739 // Do not restore mixer unless they have been saved
740 RestoreMixerState( card
);
743 if( card
->record_buffer1
!= NULL
)
745 pci_free_consistent( card
->record_buffer1
);
746 pci_free_consistent( card
->record_buffer2
);
749 card
->record_buffer1
= NULL
;
750 card
->record_buffer2
= NULL
;
751 card
->current_record_bytesize
= 0;
753 card
->is_recording
= FALSE
;
754 card
->record_interrupt_enabled
= FALSE
;
756 pci_free_consistent(card
->rec_idx_table_nonaligned
);
757 card
->rec_idx_table
= NULL
;
761 card
->current_bytesize
= 0;
765 /******************************************************************************
766 ** AHIsub_GetAttr *************************************************************
767 ******************************************************************************/
770 _AHIsub_GetAttr( ULONG attribute
,
773 struct TagItem
* taglist
,
774 struct AHIAudioCtrlDrv
* AudioCtrl
,
775 struct DriverBase
* AHIsubBase
)
777 struct CardBase
* CardBase
= (struct CardBase
*) AHIsubBase
;
786 case AHIDB_Frequencies
:
789 case AHIDB_Frequency
: // Index->Frequency
790 return (SIPTR
) Frequencies
[ argument
];
792 case AHIDB_Index
: // Frequency->Index
793 if( argument
<= (LONG
) Frequencies
[ 0 ] )
798 if( argument
>= (LONG
) Frequencies
[ FREQUENCIES
- 1 ] )
800 return FREQUENCIES
-1;
803 for( i
= 1; i
< FREQUENCIES
; i
++ )
805 if( (LONG
) Frequencies
[ i
] > argument
)
807 if( ( argument
- (LONG
) Frequencies
[ i
- 1 ] ) < ( (LONG
) Frequencies
[ i
] - argument
) )
818 return 0; // Will not happen
821 return (SIPTR
) "Davy Wentzler";
823 case AHIDB_Copyright
:
824 return (SIPTR
) "(C) Davy Wentzler";
827 return (SIPTR
) LibIDString
;
829 case AHIDB_Annotation
:
831 "VIA VT82C686 AC97 driver";
836 case AHIDB_FullDuplex
:
842 case AHIDB_MaxRecordSamples
:
843 return RECORD_BUFFER_SAMPLES
;
848 unsigned long res = (unsigned long) (0x10000 * pow (10.0, dB / 20.0));
849 double dB = 20.0 * log10(0xVALUE / 65536.0);
851 printf("dB = %f, res = %lx\n", dB, res);*/
853 case AHIDB_MinMonitorVolume
:
856 case AHIDB_MaxMonitorVolume
:
859 case AHIDB_MinInputGain
:
860 return 0x10000; // 0.0 dB gain
862 case AHIDB_MaxInputGain
:
863 return 0xD55D0; // 22.5 dB gain
865 case AHIDB_MinOutputVolume
:
866 return 0x00000; // -96 dB
868 case AHIDB_MaxOutputVolume
:
869 return 0x10000; // 0 dB
875 return (SIPTR
) Inputs
[ argument
];
881 return (SIPTR
) Outputs
[ argument
];
889 /******************************************************************************
890 ** AHIsub_HardwareControl *****************************************************
891 ******************************************************************************/
894 _AHIsub_HardwareControl( ULONG attribute
,
896 struct AHIAudioCtrlDrv
* AudioCtrl
,
897 struct DriverBase
* AHIsubBase
)
899 struct CardBase
* CardBase
= (struct CardBase
*) AHIsubBase
;
900 struct CardData
* card
= (struct CardData
*) AudioCtrl
->ahiac_DriverData
;
904 case AHIC_MonitorVolume
:
905 card
->monitor_volume
= Linear2MixerGain( (Fixed
) argument
, &card
->monitor_volume_bits
);
906 if( card
->is_recording
)
908 UpdateMonitorMixer( card
);
912 case AHIC_MonitorVolume_Query
:
913 return card
->monitor_volume
;
916 card
->input_gain
= Linear2RecordGain( (Fixed
) argument
, &card
->input_gain_bits
);
917 codec_write(card
, AC97_RECORD_GAIN
, card
->input_gain_bits
);
920 case AHIC_InputGain_Query
:
921 return card
->input_gain
;
923 case AHIC_OutputVolume
:
924 card
->output_volume
= Linear2MixerGain( (Fixed
) argument
, &card
->output_volume_bits
);
925 codec_write(card
, AC97_PCMOUT_VOL
, card
->output_volume_bits
);
928 case AHIC_OutputVolume_Query
:
929 return card
->output_volume
;
932 card
->input
= argument
;
933 codec_write(card
, AC97_RECORD_SELECT
, InputBits
[ card
->input
] );
935 if( card
->is_recording
)
937 UpdateMonitorMixer( card
);
942 case AHIC_Input_Query
:
946 card
->output
= argument
;
950 case AHIC_Output_Query
: