Importing CMI8738-20072011
[AROS.git] / workbench / devs / AHI / Drivers / CMI8738 / cmi8738.c
blob96287f80c8cdf50400eb42436c890df5ef7fb6e9
1 /*
2 The contents of this file are subject to the AROS Public License Version 1.1 (the "License");
3 you may not use this file except in compliance with the License. You may obtain a copy of the License at
4 http://www.aros.org/license.html
5 Software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTY OF
6 ANY KIND, either express or implied. See the License for the specific language governing rights and
7 limitations under the License.
9 The Original Code is written by Davy Wentzler.
12 #include <config.h>
14 #undef __USE_INLINE__
15 #include <proto/expansion.h>
18 #include <devices/ahi.h>
19 #include <exec/memory.h>
20 #include <libraries/ahi_sub.h>
22 #include <proto/ahi_sub.h>
23 #include <proto/exec.h>
24 #include <proto/dos.h>
25 #include <proto/utility.h>
26 #include <proto/fakedma.h>
27 #include <math.h>
28 #include <string.h>
30 #include "library_card.h"
31 #include "regs.h"
32 #include "misc.h"
33 #include "DriverData.h"
35 extern struct UtilityIFace* IUtility;
36 extern struct AHIsubIFace* IAHIsub;
37 extern struct MMUIFace* IMMU;
38 extern int z;
40 /******************************************************************************
41 ** Globals ********************************************************************
42 ******************************************************************************/
44 #define FREQUENCIES 8
46 static const ULONG Frequencies[ FREQUENCIES ] =
48 5512,
49 8000, // ยต- and A-Law
50 11025, // CD/4
51 16000, // DAT/3
52 22050, // CD/2
53 32000, // DAT/1.5
54 44100, // CD
55 48000 // DAT
59 static const ULONG FrequencyBits[ FREQUENCIES ] =
74 #define INPUTS 5
76 static const STRPTR Inputs[ INPUTS ] =
78 "Line in",
79 "Mic",
80 "CD",
81 "Aux",
82 "S/PDIF"
85 #if 0
86 /* Not static since it's used in misc.c too */
87 const UWORD InputBits[ INPUTS ] =
89 AC97_RECMUX_LINE,
90 AC97_RECMUX_MIC,
91 AC97_RECMUX_CD,
92 AC97_RECMUX_VIDEO,
93 AC97_RECMUX_AUX,
94 AC97_RECMUX_STEREO_MIX,
95 AC97_RECMUX_MONO_MIX,
96 AC97_RECMUX_PHONE
98 #endif
101 #define OUTPUTS 2
103 static const STRPTR Outputs[ OUTPUTS ] =
105 "Line Out",
106 "Digital Out"
111 /******************************************************************************
112 ** AHIsub_AllocAudio **********************************************************
113 ******************************************************************************/
115 ULONG
116 _AHIsub_AllocAudio( struct TagItem* taglist,
117 struct AHIAudioCtrlDrv* AudioCtrl,
118 struct DriverBase* AHIsubBase )
120 struct CardBase* CardBase = (struct CardBase*) AHIsubBase;
122 int card_num;
123 ULONG ret;
124 int i, freq = 6;
126 card_num = ( IUtility->GetTagData( AHIDB_AudioID, 0, taglist) & 0x0000f000 ) >> 12;
128 if( card_num >= CardBase->cards_found ||
129 CardBase->driverdatas[ card_num ] == NULL )
131 IExec->DebugPrintF("no date for card = %ld\n", card_num);
132 Req( "No CardData for card %ld.", card_num );
133 return AHISF_ERROR;
135 else
137 struct CardData* card;
138 BOOL in_use;
139 struct PCIDevice *dev;
141 card = CardBase->driverdatas[ card_num ];
142 AudioCtrl->ahiac_DriverData = card;
144 IExec->ObtainSemaphore( &CardBase->semaphore );
145 in_use = ( card->audioctrl != NULL );
146 if( !in_use )
148 card->audioctrl = AudioCtrl;
150 IExec->ReleaseSemaphore( &CardBase->semaphore );
152 if( in_use )
154 return AHISF_ERROR;
157 dev = card->pci_dev;
158 card->playback_interrupt_enabled = FALSE;
159 card->record_interrupt_enabled = FALSE;
161 for( i = 1; i < FREQUENCIES; i++ )
163 if( (ULONG) Frequencies[ i ] > AudioCtrl->ahiac_MixFreq )
165 if ( ( AudioCtrl->ahiac_MixFreq - (LONG) Frequencies[ i - 1 ] ) < ( (LONG) Frequencies[ i ] - AudioCtrl->ahiac_MixFreq ) )
167 freq = i-1;
168 break;
170 else
172 freq = i;
173 break;
180 ret = AHISF_KNOWHIFI | AHISF_KNOWSTEREO | AHISF_MIXING | AHISF_TIMING;
183 for( i = 0; i < FREQUENCIES; ++i )
185 if( AudioCtrl->ahiac_MixFreq == Frequencies[ i ] )
187 ret |= AHISF_CANRECORD;
188 break;
192 return ret;
197 /******************************************************************************
198 ** AHIsub_FreeAudio ***********************************************************
199 ******************************************************************************/
201 void
202 _AHIsub_FreeAudio( struct AHIAudioCtrlDrv* AudioCtrl,
203 struct DriverBase* AHIsubBase )
205 struct CardBase* CardBase = (struct CardBase*) AHIsubBase;
206 struct CardData* card = (struct CardData*) AudioCtrl->ahiac_DriverData;
208 if( card != NULL )
210 IExec->ObtainSemaphore( &CardBase->semaphore );
211 if( card->audioctrl == AudioCtrl )
213 // Release it if we own it.
214 card->audioctrl = NULL;
216 IExec->ReleaseSemaphore( &CardBase->semaphore );
218 AudioCtrl->ahiac_DriverData = NULL;
223 /******************************************************************************
224 ** AHIsub_Disable *************************************************************
225 ******************************************************************************/
227 void
228 _AHIsub_Disable( struct AHIAudioCtrlDrv* AudioCtrl,
229 struct DriverBase* AHIsubBase )
231 struct CardBase* CardBase = (struct CardBase*) AHIsubBase;
233 // V6 drivers do not have to preserve all registers
235 IExec->Disable();
239 /******************************************************************************
240 ** AHIsub_Enable **************************************************************
241 ******************************************************************************/
243 void
244 _AHIsub_Enable( struct AHIAudioCtrlDrv* AudioCtrl,
245 struct DriverBase* AHIsubBase )
247 struct CardBase* CardBase = (struct CardBase*) AHIsubBase;
249 // V6 drivers do not have to preserve all registers
251 IExec->Enable();
255 /******************************************************************************
256 ** AHIsub_Start ***************************************************************
257 ******************************************************************************/
259 ULONG
260 _AHIsub_Start( ULONG flags,
261 struct AHIAudioCtrlDrv* AudioCtrl,
262 struct DriverBase* AHIsubBase )
264 struct CardBase* CardBase = (struct CardBase*) AHIsubBase;
265 struct CardData* card = (struct CardData*) AudioCtrl->ahiac_DriverData;
266 struct PCIDevice *dev = card->pci_dev;
267 UWORD PlayCtrlFlags = 0, RecCtrlFlags = 0;
268 ULONG dma_buffer_size = 0;
269 int i, freqbit = 6;
270 unsigned long phys_addr;
271 APTR stack;
273 /* Stop playback/recording, free old buffers (if any) */
274 //IAHIsub->AHIsub_Stop( flags, AudioCtrl );
276 for( i = 0; i < FREQUENCIES; ++i )
278 if( AudioCtrl->ahiac_MixFreq == Frequencies[ i ] )
280 freqbit = i;
281 break;
285 card->mixerstate = cmimix_rd(dev, card, CMPCI_SB16_MIXER_OUTMIX);
287 if( flags & AHISF_PLAY )
289 ULONG dma_sample_frame_size;
290 int i;
291 short *a;
292 unsigned short cod, ChannelsFlag = CMPCI_REG_FORMAT_16BIT;
294 //WriteMask(dev, card, CMPCI_REG_FUNC_0, CMPCI_REG_CH0_RESET | CMPCI_REG_CH1_RESET);
295 //ClearMask(dev, card, CMPCI_REG_FUNC_0, CMPCI_REG_CH0_RESET | CMPCI_REG_CH1_RESET);
297 /* Allocate a new mixing buffer. Note: The buffer must be cleared, since
298 it might not be filled by the mixer software interrupt because of
299 pretimer/posttimer! */
301 card->mix_buffer = IExec->AllocVec( AudioCtrl->ahiac_BuffSize, MEMF_PUBLIC | MEMF_CLEAR );
303 if( card->mix_buffer == NULL )
305 Req( "Unable to allocate %ld bytes for mixing buffer.", AudioCtrl->ahiac_BuffSize );
306 return AHIE_NOMEM;
309 /* Allocate a buffer large enough for 16-bit double-buffered
310 playback (mono or stereo) */
313 if( AudioCtrl->ahiac_Flags & AHIACF_STEREO )
315 dma_sample_frame_size = 4;
316 dma_buffer_size = AudioCtrl->ahiac_MaxBuffSamples * dma_sample_frame_size;
317 ChannelsFlag |= CMPCI_REG_FORMAT_STEREO;
319 else
321 dma_sample_frame_size = 2;
322 dma_buffer_size = AudioCtrl->ahiac_MaxBuffSamples * dma_sample_frame_size;
325 //IExec->DebugPrintF("dma_buffer_size = %ld, AudioCtrl->ahiac_BuffSize = %ld, AudioCtrl->ahiac_MaxBuffSamples = %ld\nAudioCtrl->ahiac_BuffSamples = %ld", dma_buffer_size, AudioCtrl->ahiac_BuffSize, AudioCtrl->ahiac_MaxBuffSamples, AudioCtrl->ahiac_BuffSamples);
327 card->playback_buffer = pci_alloc_consistent(dma_buffer_size * 2, &card->playback_buffer_nonaligned);
329 if (!card->playback_buffer)
331 Req( "Unable to allocate playback buffer." );
332 return AHIE_NOMEM;
335 card->current_bytesize = dma_buffer_size;
336 card->current_frames = AudioCtrl->ahiac_MaxBuffSamples;
337 card->current_buffer = card->playback_buffer + card->current_bytesize;
338 card->playback_interrupt_enabled = TRUE;
340 card->flip = 0;
341 card->oldflip = 0;
343 WritePartialMask(dev, card, CMPCI_REG_FUNC_1, CMPCI_REG_DAC_FS_SHIFT, CMPCI_REG_DAC_FS_MASK, FrequencyBits[freqbit]);
344 WritePartialMask(dev, card, CMPCI_REG_CHANNEL_FORMAT, CMPCI_REG_CH0_FORMAT_SHIFT, CMPCI_REG_CH0_FORMAT_MASK, ChannelsFlag);
345 WriteMask(dev, card, CMPCI_REG_CHANNEL_FORMAT, (13 << 1));
347 if (IFakeDMA == NULL)
349 stack = IExec->SuperState();
350 card->playback_buffer_phys = IMMU->GetPhysicalAddress(card->playback_buffer);
351 IExec->UserState(stack);
353 else
354 card->playback_buffer_phys = card->playback_buffer;
355 //IExec->DebugPrintF("ADDR = %lx\n", card->playback_buffer_phys);
357 dev->OutLong(card->iobase + CMPCI_REG_DMA0_BASE, card->playback_buffer_phys);
358 dev->OutWord(card->iobase + CMPCI_REG_DMA0_LENGTH, (dma_buffer_size / dma_sample_frame_size) * 2 - 1);
359 dev->OutWord(card->iobase + CMPCI_REG_DMA0_INTLEN, (dma_buffer_size / dma_sample_frame_size) - 1);
361 card->is_playing = TRUE;
364 if( flags & AHISF_RECORD )
366 UWORD mask;
367 ULONG ChannelsFlag = CMPCI_REG_FORMAT_16BIT;
368 unsigned char byte;
370 card->current_record_bytesize = RECORD_BUFFER_SAMPLES * 4;
372 /* Allocate a new recording buffer (page aligned!) */
373 card->record_buffer = pci_alloc_consistent(card->current_record_bytesize * 2, &card->record_buffer_nonaligned);
375 if( card->record_buffer == NULL )
377 Req( "Unable to allocate %ld bytes for the recording buffer.", card->current_record_bytesize);
378 return AHIE_NOMEM;
381 SaveMixerState( card );
382 UpdateMonitorMixer( card );
386 switch (card->input)
388 case 0: // line
389 cmimix_wr(dev, card, CMPCI_SB16_MIXER_OUTMIX, card->mixerstate | CMPCI_SB16_SW_LINE);
390 break;
392 case 1: // mic
393 cmimix_wr(dev, card, CMPCI_SB16_MIXER_OUTMIX, card->mixerstate | CMPCI_SB16_SW_MIC);
394 break;
396 case 2: // CD
397 cmimix_wr(dev, card, CMPCI_SB16_MIXER_OUTMIX, card->mixerstate | CMPCI_SB16_SW_CD);
398 break;
400 case 3: // Aux
401 byte = dev->InByte(card->iobase + CMPCI_REG_MIXER25);
402 byte |= 0x30;
403 dev->OutByte(card->iobase + CMPCI_REG_MIXER25, byte); // unmute Aux
404 break;
406 default:
407 break;
410 card->record_interrupt_enabled = TRUE;
412 card->recflip = 0;
414 WritePartialMask(dev, card, CMPCI_REG_FUNC_1, CMPCI_REG_ADC_FS_SHIFT, CMPCI_REG_ADC_FS_MASK, FrequencyBits[freqbit]);
415 WritePartialMask(dev, card, CMPCI_REG_CHANNEL_FORMAT, CMPCI_REG_CH1_FORMAT_SHIFT, CMPCI_REG_CH1_FORMAT_MASK, CMPCI_REG_FORMAT_16BIT | CMPCI_REG_FORMAT_STEREO);
417 if (IFakeDMA == NULL)
419 stack = IExec->SuperState();
420 card->record_buffer_phys = IMMU->GetPhysicalAddress(card->record_buffer);
421 IExec->UserState(stack);
423 else
424 card->record_buffer_phys = card->record_buffer;
427 dev->OutLong(card->iobase + CMPCI_REG_DMA1_BASE, card->record_buffer_phys);
428 //IDOS->Delay(1);
429 dev->OutWord(card->iobase + CMPCI_REG_DMA1_LENGTH, (card->current_record_bytesize / 4) * 2 - 1);
430 //IDOS->Delay(1);
431 dev->OutWord(card->iobase + CMPCI_REG_DMA1_INTLEN, (card->current_record_bytesize / 4) - 1);
432 //IDOS->Delay(1);
433 card->current_record_buffer = card->record_buffer + card->current_record_bytesize;
434 card->is_recording = TRUE;
437 if( flags & AHISF_PLAY )
439 z = 0;
440 WriteMask(dev, card, CMPCI_REG_FUNC_0, CMPCI_REG_CH0_ENABLE);
441 WriteMask(dev, card, CMPCI_REG_INTR_CTRL, CMPCI_REG_CH0_INTR_ENABLE);
444 if( flags & AHISF_RECORD )
446 WriteMask(dev, card, CMPCI_REG_FUNC_0, CMPCI_REG_CH1_ENABLE);
447 WriteMask(dev, card, CMPCI_REG_INTR_CTRL, CMPCI_REG_CH1_INTR_ENABLE);
450 return AHIE_OK;
454 /******************************************************************************
455 ** AHIsub_Update **************************************************************
456 ******************************************************************************/
458 void
459 _AHIsub_Update( ULONG flags,
460 struct AHIAudioCtrlDrv* AudioCtrl,
461 struct DriverBase* AHIsubBase )
463 struct CardBase* CardBase = (struct CardBase*) AHIsubBase;
464 struct CardData* card = (struct CardData*) AudioCtrl->ahiac_DriverData;
465 #if 0
466 card->current_frames = AudioCtrl->ahiac_BuffSamples;
468 if( AudioCtrl->ahiac_Flags & AHIACF_STEREO )
470 card->current_bytesize = card->current_frames * 4;
472 else
474 card->current_bytesize = card->current_frames * 2;
476 #endif
480 /******************************************************************************
481 ** AHIsub_Stop ****************************************************************
482 ******************************************************************************/
484 void
485 _AHIsub_Stop( ULONG flags,
486 struct AHIAudioCtrlDrv* AudioCtrl,
487 struct DriverBase* AHIsubBase )
489 struct CardBase* CardBase = (struct CardBase*) AHIsubBase;
490 struct CardData* card = (struct CardData*) AudioCtrl->ahiac_DriverData;
491 struct PCIDevice *dev = card->pci_dev;
494 if( flags & AHISF_PLAY )
496 unsigned short play_ctl;
498 card->is_playing= FALSE;
500 ClearMask(dev, card, CMPCI_REG_INTR_CTRL, CMPCI_REG_CH0_INTR_ENABLE);
501 ClearMask(dev, card, CMPCI_REG_FUNC_0, CMPCI_REG_CH0_ENABLE);
503 if (card->current_bytesize > 0)
504 pci_free_consistent(card->playback_buffer_nonaligned);
506 card->current_bytesize = 0;
507 card->current_frames = 0;
508 card->current_buffer = NULL;
510 if ( card->mix_buffer)
511 IExec->FreeVec( card->mix_buffer );
512 card->mix_buffer = NULL;
513 card->playback_interrupt_enabled = FALSE;
514 card->current_bytesize = 0;
515 //IExec->DebugPrintF("#IRQ's = %ld\n", z);
518 if( flags & AHISF_RECORD && card->is_recording)
520 unsigned short rec_ctl, val;
521 unsigned char byte;
523 ClearMask(dev, card, CMPCI_REG_INTR_CTRL, CMPCI_REG_CH1_INTR_ENABLE);
524 ClearMask(dev, card, CMPCI_REG_FUNC_0, CMPCI_REG_CH1_ENABLE);
526 switch (card->input)
528 case 0: // line
529 cmimix_wr(dev, card, CMPCI_SB16_MIXER_OUTMIX, card->mixerstate);
530 break;
532 case 1: // mic
533 cmimix_wr(dev, card, CMPCI_SB16_MIXER_OUTMIX, card->mixerstate);
534 break;
536 case 2: // CD
537 cmimix_wr(dev, card, CMPCI_SB16_MIXER_OUTMIX, card->mixerstate);
538 break;
540 case 3: // Aux
541 byte = dev->InByte(card->iobase + CMPCI_REG_MIXER25);
542 dev->OutByte(card->iobase + CMPCI_REG_MIXER25, byte & ~0x30); // mute Aux
543 break;
545 default:
546 break;
549 if( card->record_buffer != NULL )
551 pci_free_consistent( card->record_buffer_nonaligned);
554 card->record_buffer = NULL;
555 card->current_record_bytesize = 0;
557 card->is_recording = FALSE;
558 card->record_interrupt_enabled = FALSE;
565 /******************************************************************************
566 ** AHIsub_GetAttr *************************************************************
567 ******************************************************************************/
569 LONG
570 _AHIsub_GetAttr( ULONG attribute,
571 LONG argument,
572 LONG def,
573 struct TagItem* taglist,
574 struct AHIAudioCtrlDrv* AudioCtrl,
575 struct DriverBase* AHIsubBase )
577 struct CardBase* CardBase = (struct CardBase*) AHIsubBase;
578 int i;
581 switch( attribute )
583 case AHIDB_Bits:
584 return 16;
586 case AHIDB_Frequencies:
587 return FREQUENCIES;
589 case AHIDB_Frequency: // Index->Frequency
590 return (LONG) Frequencies[ argument ];
592 case AHIDB_Index: // Frequency->Index
593 if( argument <= (LONG) Frequencies[ 0 ] )
595 return 0;
598 if( argument >= (LONG) Frequencies[ FREQUENCIES - 1 ] )
600 return FREQUENCIES-1;
603 for( i = 1; i < FREQUENCIES; i++ )
605 if( (LONG) Frequencies[ i ] > argument )
607 if( ( argument - (LONG) Frequencies[ i - 1 ] ) < ( (LONG) Frequencies[ i ] - argument ) )
609 return i-1;
611 else
613 return i;
618 return 0; // Will not happen
620 case AHIDB_Author:
621 return (LONG) "Davy Wentzler";
623 case AHIDB_Copyright:
624 return (LONG) "(C) Davy Wentzler";
626 case AHIDB_Version:
627 return (LONG) LibIDString;
629 case AHIDB_Annotation:
630 return (LONG)
631 "OS4 PPC native driver";
633 case AHIDB_Record:
634 return TRUE;
636 case AHIDB_FullDuplex:
637 return TRUE;
639 case AHIDB_Realtime:
640 return TRUE;
642 case AHIDB_MaxRecordSamples:
643 return RECORD_BUFFER_SAMPLES;
645 /* formula's:
646 #include <math.h>
648 unsigned long res = (unsigned long) (0x10000 * pow (10.0, dB / 20.0));
649 double dB = 20.0 * log10(0xVALUE / 65536.0);
651 printf("dB = %f, res = %lx\n", dB, res);*/
653 case AHIDB_MinMonitorVolume:
654 return 0x00000;
656 case AHIDB_MaxMonitorVolume:
657 return 0x00000;
659 case AHIDB_MinInputGain:
660 return 0x10000; // 0.0 dB gain
662 case AHIDB_MaxInputGain:
663 return 0x10000; // 0 dB gain
665 case AHIDB_MinOutputVolume:
666 return 0x34; // -62 dB
668 case AHIDB_MaxOutputVolume:
669 return 0x10000; // 0 dB
671 case AHIDB_Inputs:
672 return INPUTS;
674 case AHIDB_Input:
675 return (LONG) Inputs[ argument ];
677 case AHIDB_Outputs:
678 return OUTPUTS;
680 case AHIDB_Output:
681 return (LONG) Outputs[ argument ];
683 default:
684 return def;
689 /******************************************************************************
690 ** AHIsub_HardwareControl *****************************************************
691 ******************************************************************************/
693 ULONG
694 _AHIsub_HardwareControl( ULONG attribute,
695 LONG argument,
696 struct AHIAudioCtrlDrv* AudioCtrl,
697 struct DriverBase* AHIsubBase )
699 struct CardBase* CardBase = (struct CardBase*) AHIsubBase;
700 struct CardData* card = (struct CardData*) AudioCtrl->ahiac_DriverData;
701 struct PCIDevice *dev = card->pci_dev;
702 unsigned char byte;
704 switch( attribute )
706 case AHIC_MonitorVolume:
707 card->monitor_volume = Linear2MixerGain( (Fixed) argument, &card->monitor_volume_bits );
708 //IExec->DebugPrintF("card->monitor_volume = %lu, %lx\n", card->monitor_volume, card->monitor_volume);
709 if( card->is_recording )
711 UpdateMonitorMixer( card );
713 return TRUE;
715 case AHIC_MonitorVolume_Query:
716 return card->monitor_volume;
718 case AHIC_InputGain:
719 card->input_gain = Linear2RecordGain( (Fixed) argument, &card->input_gain_bits );
720 //codec_write(card, AC97_RECORD_GAIN, card->input_gain_bits );
721 return TRUE;
723 case AHIC_InputGain_Query:
724 return card->input_gain;
726 case AHIC_OutputVolume:
728 double dB = 20.0 * log10((Fixed) argument / 65536.0);
729 unsigned int val = 0xFF - ( ((unsigned int)(-dB/2)) << 3);
730 cmimix_wr(dev, card, 0x30, val);
731 cmimix_wr(dev, card, 0x31, val);
732 return TRUE;
734 case AHIC_OutputVolume_Query:
735 return card->output_volume;
737 case AHIC_Input:
738 card->input = argument;
740 switch (card->input)
742 case 0: // line
743 cmimix_wr(dev, card, CMPCI_SB16_MIXER_ADCMIX_L, (CMPCI_SB16_MIXER_LINE_SRC_R << 1) );
744 cmimix_wr(dev, card, CMPCI_SB16_MIXER_ADCMIX_R, CMPCI_SB16_MIXER_LINE_SRC_R );
745 break;
747 case 1: // mic
748 cmimix_wr(dev, card, CMPCI_SB16_MIXER_ADCMIX_L, CMPCI_SB16_MIXER_MIC_SRC);
749 cmimix_wr(dev, card, CMPCI_SB16_MIXER_ADCMIX_R, CMPCI_SB16_MIXER_MIC_SRC);
750 break;
752 case 2: // CD
753 cmimix_wr(dev, card, CMPCI_SB16_MIXER_ADCMIX_L, (CMPCI_SB16_MIXER_CD_SRC_R << 1) );
754 cmimix_wr(dev, card, CMPCI_SB16_MIXER_ADCMIX_R, CMPCI_SB16_MIXER_CD_SRC_R );
755 break;
757 case 3: // Aux
758 byte = dev->InByte(card->iobase + CMPCI_REG_MIXER25);
759 dev->OutByte(card->iobase + CMPCI_REG_MIXER25, byte | 0xC0); // rec source Aux
760 break;
762 case 4: // SPDIF
764 break;
766 default:
767 break;
770 if( card->is_recording )
772 UpdateMonitorMixer( card );
775 return TRUE;
777 case AHIC_Input_Query:
778 return card->input;
780 case AHIC_Output:
781 card->output = argument;
783 if( card->output == 0 )
785 ClearMask(dev, card, CMPCI_REG_FUNC_1, CMPCI_REG_SPDIFOUT_DAC | CMPCI_REG_SPDIF0_ENABLE);
786 ClearMask(dev, card, CMPCI_REG_LEGACY_CTRL, CMPCI_REG_XSPDIF_ENABLE);
788 else
790 WriteMask(dev, card, CMPCI_REG_FUNC_1, CMPCI_REG_SPDIFOUT_DAC | CMPCI_REG_SPDIF0_ENABLE);
791 WriteMask(dev, card, CMPCI_REG_LEGACY_CTRL, CMPCI_REG_XSPDIF_ENABLE);
793 return TRUE;
795 case AHIC_Output_Query:
796 return card->output;
798 default:
799 return FALSE;