change init code to support multiple cards. small fixes and corrections to code.
[AROS.git] / workbench / devs / AHI / Drivers / CMI8738 / cmi8738.c
blob06977bd85dcdc05e48edaffd6a286823122a57d3
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 #if !defined(__AROS__)
15 #undef __USE_INLINE__
16 #include <proto/expansion.h>
17 #endif
19 #include <devices/ahi.h>
20 #include <exec/memory.h>
21 #include <libraries/ahi_sub.h>
23 #include <proto/ahi_sub.h>
24 #include <proto/exec.h>
25 #include <proto/dos.h>
26 #include <proto/utility.h>
28 #ifdef __AROS__
29 #define DEBUG 1
30 #include <aros/debug.h>
31 #define DebugPrintF bug
32 #endif
33 #include <math.h>
34 #include <string.h>
36 #include "library.h"
37 #include "regs.h"
38 #include "misc.h"
39 #include "pci_wrapper.h"
41 extern int z;
43 /******************************************************************************
44 ** Globals ********************************************************************
45 ******************************************************************************/
47 #define FREQUENCIES 8
49 static const ULONG Frequencies[ FREQUENCIES ] =
51 5512,
52 8000, // ยต- and A-Law
53 11025, // CD/4
54 16000, // DAT/3
55 22050, // CD/2
56 32000, // DAT/1.5
57 44100, // CD
58 48000 // DAT
61 static const ULONG FrequencyBits[ FREQUENCIES ] =
73 #define INPUTS 5
75 static const STRPTR Inputs[ INPUTS ] =
77 "Line in",
78 "Mic",
79 "CD",
80 "Aux",
81 "S/PDIF"
84 #if 0
85 /* Not static since it's used in misc.c too */
86 const UWORD InputBits[ INPUTS ] =
88 AC97_RECMUX_LINE,
89 AC97_RECMUX_MIC,
90 AC97_RECMUX_CD,
91 AC97_RECMUX_VIDEO,
92 AC97_RECMUX_AUX,
93 AC97_RECMUX_STEREO_MIX,
94 AC97_RECMUX_MONO_MIX,
95 AC97_RECMUX_PHONE
97 #endif
99 #define OUTPUTS 2
101 static const STRPTR Outputs[ OUTPUTS ] =
103 "Line Out",
104 "Digital Out"
107 /******************************************************************************
108 ** AHIsub_AllocAudio **********************************************************
109 ******************************************************************************/
111 ULONG
112 _AHIsub_AllocAudio( struct TagItem* taglist,
113 struct AHIAudioCtrlDrv* AudioCtrl,
114 struct DriverBase* AHIsubBase )
116 struct CMI8738Base* CMI8738Base = (struct CMI8738Base*) AHIsubBase;
118 int card_num;
119 ULONG ret;
120 int i, freq = 6;
122 bug("[CMI8738]: %s()\n", __PRETTY_FUNCTION__);
124 card_num = ( GetTagData( AHIDB_AudioID, 0, taglist) & 0x0000f000 ) >> 12;
126 if( card_num >= CMI8738Base->cards_found ||
127 CMI8738Base->driverdatas[ card_num ] == NULL )
129 DebugPrintF("no date for card = %ld\n", card_num);
130 Req( "No CMI8738_DATA for card %ld.", card_num );
131 return AHISF_ERROR;
133 else
135 struct CMI8738_DATA* card;
136 BOOL in_use;
137 struct PCIDevice *dev;
139 card = CMI8738Base->driverdatas[ card_num ];
140 AudioCtrl->ahiac_DriverData = card;
142 ObtainSemaphore( &CMI8738Base->semaphore );
143 in_use = ( card->audioctrl != NULL );
144 if( !in_use )
146 card->audioctrl = AudioCtrl;
148 ReleaseSemaphore( &CMI8738Base->semaphore );
150 if( in_use )
152 return AHISF_ERROR;
155 dev = card->pci_dev;
156 card->playback_interrupt_enabled = FALSE;
157 card->record_interrupt_enabled = FALSE;
159 for( i = 1; i < FREQUENCIES; i++ )
161 if( (ULONG) Frequencies[ i ] > AudioCtrl->ahiac_MixFreq )
163 if ( ( AudioCtrl->ahiac_MixFreq - (LONG) Frequencies[ i - 1 ] ) < ( (LONG) Frequencies[ i ] - AudioCtrl->ahiac_MixFreq ) )
165 freq = i-1;
166 break;
168 else
170 freq = i;
171 break;
177 ret = AHISF_KNOWHIFI | AHISF_KNOWSTEREO | AHISF_MIXING | AHISF_TIMING;
179 for( i = 0; i < FREQUENCIES; ++i )
181 if( AudioCtrl->ahiac_MixFreq == Frequencies[ i ] )
183 ret |= AHISF_CANRECORD;
184 break;
188 return ret;
193 /******************************************************************************
194 ** AHIsub_FreeAudio ***********************************************************
195 ******************************************************************************/
197 void
198 _AHIsub_FreeAudio( struct AHIAudioCtrlDrv* AudioCtrl,
199 struct DriverBase* AHIsubBase )
201 struct CMI8738Base* CMI8738Base = (struct CMI8738Base*) AHIsubBase;
202 struct CMI8738_DATA* card = (struct CMI8738_DATA*) AudioCtrl->ahiac_DriverData;
204 bug("[CMI8738]: %s()\n", __PRETTY_FUNCTION__);
206 if( card != NULL )
208 ObtainSemaphore( &CMI8738Base->semaphore );
209 if( card->audioctrl == AudioCtrl )
211 // Release it if we own it.
212 card->audioctrl = NULL;
214 ReleaseSemaphore( &CMI8738Base->semaphore );
216 AudioCtrl->ahiac_DriverData = NULL;
221 /******************************************************************************
222 ** AHIsub_Disable *************************************************************
223 ******************************************************************************/
225 void
226 _AHIsub_Disable( struct AHIAudioCtrlDrv* AudioCtrl,
227 struct DriverBase* AHIsubBase )
229 struct CMI8738Base* CMI8738Base = (struct CMI8738Base*) AHIsubBase;
231 bug("[CMI8738]: %s()\n", __PRETTY_FUNCTION__);
233 // V6 drivers do not have to preserve all registers
235 Disable();
239 /******************************************************************************
240 ** AHIsub_Enable **************************************************************
241 ******************************************************************************/
243 void
244 _AHIsub_Enable( struct AHIAudioCtrlDrv* AudioCtrl,
245 struct DriverBase* AHIsubBase )
247 struct CMI8738Base* CMI8738Base = (struct CMI8738Base*) AHIsubBase;
249 bug("[CMI8738]: %s()\n", __PRETTY_FUNCTION__);
251 // V6 drivers do not have to preserve all registers
253 Enable();
257 /******************************************************************************
258 ** AHIsub_Start ***************************************************************
259 ******************************************************************************/
261 ULONG
262 _AHIsub_Start( ULONG flags,
263 struct AHIAudioCtrlDrv* AudioCtrl,
264 struct DriverBase* AHIsubBase )
266 struct CMI8738Base* CMI8738Base = (struct CMI8738Base*) AHIsubBase;
267 struct CMI8738_DATA* card = (struct CMI8738_DATA*) AudioCtrl->ahiac_DriverData;
268 struct PCIDevice *dev = card->pci_dev;
269 UWORD PlayCtrlFlags = 0, RecCtrlFlags = 0;
270 ULONG dma_buffer_size = 0;
271 int i, freqbit = 6;
272 unsigned long phys_addr;
273 APTR stack;
275 bug("[CMI8738]: %s()\n", __PRETTY_FUNCTION__);
277 /* Stop playback/recording, free old buffers (if any) */
278 //IAHIsub->AHIsub_Stop( flags, AudioCtrl );
280 for( i = 0; i < FREQUENCIES; ++i )
282 if( AudioCtrl->ahiac_MixFreq == Frequencies[ i ] )
284 freqbit = i;
285 break;
289 card->mixerstate = cmimix_rd(dev, card, CMPCI_SB16_MIXER_OUTMIX);
291 if( flags & AHISF_PLAY )
293 ULONG dma_sample_frame_size;
294 int i;
295 short *a;
296 unsigned short cod, ChannelsFlag = CMPCI_REG_FORMAT_16BIT;
298 //WriteMask(dev, card, CMPCI_REG_FUNC_0, CMPCI_REG_CH0_RESET | CMPCI_REG_CH1_RESET);
299 //ClearMask(dev, card, CMPCI_REG_FUNC_0, CMPCI_REG_CH0_RESET | CMPCI_REG_CH1_RESET);
301 /* Allocate a new mixing buffer. Note: The buffer must be cleared, since
302 it might not be filled by the mixer software interrupt because of
303 pretimer/posttimer! */
305 card->mix_buffer = AllocVec( AudioCtrl->ahiac_BuffSize, MEMF_PUBLIC | MEMF_CLEAR );
307 if( card->mix_buffer == NULL )
309 Req( "Unable to allocate %ld bytes for mixing buffer.", AudioCtrl->ahiac_BuffSize );
310 return AHIE_NOMEM;
313 /* Allocate a buffer large enough for 16-bit double-buffered
314 playback (mono or stereo) */
316 if( AudioCtrl->ahiac_Flags & AHIACF_STEREO )
318 dma_sample_frame_size = 4;
319 dma_buffer_size = AudioCtrl->ahiac_MaxBuffSamples * dma_sample_frame_size;
320 ChannelsFlag |= CMPCI_REG_FORMAT_STEREO;
322 else
324 dma_sample_frame_size = 2;
325 dma_buffer_size = AudioCtrl->ahiac_MaxBuffSamples * dma_sample_frame_size;
328 //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);
330 card->playback_buffer = pci_alloc_consistent(dma_buffer_size * 2, &card->playback_buffer_nonaligned, 128);
332 if (!card->playback_buffer)
334 Req( "Unable to allocate playback buffer." );
335 return AHIE_NOMEM;
338 card->current_bytesize = dma_buffer_size;
339 card->current_frames = AudioCtrl->ahiac_MaxBuffSamples;
340 card->current_buffer = card->playback_buffer + card->current_bytesize;
341 card->playback_interrupt_enabled = TRUE;
343 card->flip = 0;
344 card->oldflip = 0;
346 WritePartialMask(dev, card, CMPCI_REG_FUNC_1, CMPCI_REG_DAC_FS_SHIFT, CMPCI_REG_DAC_FS_MASK, FrequencyBits[freqbit]);
347 WritePartialMask(dev, card, CMPCI_REG_CHANNEL_FORMAT, CMPCI_REG_CH0_FORMAT_SHIFT, CMPCI_REG_CH0_FORMAT_MASK, ChannelsFlag);
348 WriteMask(dev, card, CMPCI_REG_CHANNEL_FORMAT, (13 << 1));
350 #if !defined(__AROS__)
351 if (IFakeDMA == NULL)
353 stack = SuperState();
354 card->playback_buffer_phys = IMMU->GetPhysicalAddress(card->playback_buffer);
355 UserState(stack);
357 else
358 #endif
359 card->playback_buffer_phys = card->playback_buffer;
361 bug("[CMI8738] %s: Playback buffer @ 0x%p\n", __PRETTY_FUNCTION__, card->playback_buffer);
363 pci_outl(card->playback_buffer_phys, CMPCI_REG_DMA0_BASE, card);
364 pci_outw((dma_buffer_size / dma_sample_frame_size) * 2 - 1, CMPCI_REG_DMA0_LENGTH, card);
365 pci_outw((dma_buffer_size / dma_sample_frame_size) - 1, CMPCI_REG_DMA0_INTLEN, card);
367 card->is_playing = TRUE;
370 if( flags & AHISF_RECORD )
372 UWORD mask;
373 ULONG ChannelsFlag = CMPCI_REG_FORMAT_16BIT;
374 unsigned char byte;
376 card->current_record_bytesize = RECORD_BUFFER_SAMPLES * 4;
378 /* Allocate a new recording buffer (page aligned!) */
379 card->record_buffer = pci_alloc_consistent(card->current_record_bytesize * 2, &card->record_buffer_nonaligned, 128);
381 if( card->record_buffer == NULL )
383 Req( "Unable to allocate %ld bytes for the recording buffer.", card->current_record_bytesize, 128);
384 return AHIE_NOMEM;
387 SaveMixerState( card );
388 UpdateMonitorMixer( card );
390 switch (card->input)
392 case 0: // line
393 cmimix_wr(dev, card, CMPCI_SB16_MIXER_OUTMIX, card->mixerstate | CMPCI_SB16_SW_LINE);
394 break;
396 case 1: // mic
397 cmimix_wr(dev, card, CMPCI_SB16_MIXER_OUTMIX, card->mixerstate | CMPCI_SB16_SW_MIC);
398 break;
400 case 2: // CD
401 cmimix_wr(dev, card, CMPCI_SB16_MIXER_OUTMIX, card->mixerstate | CMPCI_SB16_SW_CD);
402 break;
404 case 3: // Aux
405 byte = pci_inb(CMPCI_REG_MIXER25, card);
406 byte |= 0x30;
407 pci_outb(byte, CMPCI_REG_MIXER25, card); // unmute Aux
408 break;
410 default:
411 break;
414 card->record_interrupt_enabled = TRUE;
416 card->recflip = 0;
418 WritePartialMask(dev, card, CMPCI_REG_FUNC_1, CMPCI_REG_ADC_FS_SHIFT, CMPCI_REG_ADC_FS_MASK, FrequencyBits[freqbit]);
419 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);
421 #if !defined(__AROS__)
422 if (IFakeDMA == NULL)
424 stack = SuperState();
425 card->record_buffer_phys = IMMU->GetPhysicalAddress(card->record_buffer);
426 UserState(stack);
428 else
429 #endif
430 card->record_buffer_phys = card->record_buffer;
432 pci_outl(card->record_buffer_phys, CMPCI_REG_DMA1_BASE, card);
433 udelay(1);
434 pci_outw((card->current_record_bytesize / 4) * 2 - 1, CMPCI_REG_DMA1_LENGTH, card);
435 udelay(1);
436 pci_outw((card->current_record_bytesize / 4) - 1, CMPCI_REG_DMA1_INTLEN, card);
437 udelay(1);
438 card->current_record_buffer = card->record_buffer + card->current_record_bytesize;
439 card->is_recording = TRUE;
442 if( flags & AHISF_PLAY )
444 z = 0;
445 WriteMask(dev, card, CMPCI_REG_FUNC_0, CMPCI_REG_CH0_ENABLE);
446 WriteMask(dev, card, CMPCI_REG_INTR_CTRL, CMPCI_REG_CH0_INTR_ENABLE);
449 if( flags & AHISF_RECORD )
451 WriteMask(dev, card, CMPCI_REG_FUNC_0, CMPCI_REG_CH1_ENABLE);
452 WriteMask(dev, card, CMPCI_REG_INTR_CTRL, CMPCI_REG_CH1_INTR_ENABLE);
455 return AHIE_OK;
459 /******************************************************************************
460 ** AHIsub_Update **************************************************************
461 ******************************************************************************/
463 void
464 _AHIsub_Update( ULONG flags,
465 struct AHIAudioCtrlDrv* AudioCtrl,
466 struct DriverBase* AHIsubBase )
468 struct CMI8738Base* CMI8738Base = (struct CMI8738Base*) AHIsubBase;
469 struct CMI8738_DATA* card = (struct CMI8738_DATA*) AudioCtrl->ahiac_DriverData;
471 bug("[CMI8738]: %s()\n", __PRETTY_FUNCTION__);
473 #if 0
474 card->current_frames = AudioCtrl->ahiac_BuffSamples;
476 if( AudioCtrl->ahiac_Flags & AHIACF_STEREO )
478 card->current_bytesize = card->current_frames * 4;
480 else
482 card->current_bytesize = card->current_frames * 2;
484 #endif
488 /******************************************************************************
489 ** AHIsub_Stop ****************************************************************
490 ******************************************************************************/
492 void
493 _AHIsub_Stop( ULONG flags,
494 struct AHIAudioCtrlDrv* AudioCtrl,
495 struct DriverBase* AHIsubBase )
497 struct CMI8738Base* CMI8738Base = (struct CMI8738Base*) AHIsubBase;
498 struct CMI8738_DATA* card = (struct CMI8738_DATA*) AudioCtrl->ahiac_DriverData;
499 struct PCIDevice *dev = card->pci_dev;
501 bug("[CMI8738]: %s()\n", __PRETTY_FUNCTION__);
503 if( flags & AHISF_PLAY )
505 unsigned short play_ctl;
507 card->is_playing= FALSE;
509 ClearMask(dev, card, CMPCI_REG_INTR_CTRL, CMPCI_REG_CH0_INTR_ENABLE);
510 ClearMask(dev, card, CMPCI_REG_FUNC_0, CMPCI_REG_CH0_ENABLE);
512 if (card->current_bytesize > 0)
513 pci_free_consistent(card->playback_buffer_nonaligned);
515 card->current_bytesize = 0;
516 card->current_frames = 0;
517 card->current_buffer = NULL;
519 if ( card->mix_buffer)
520 FreeVec( card->mix_buffer );
522 card->mix_buffer = NULL;
523 card->playback_interrupt_enabled = FALSE;
524 card->current_bytesize = 0;
525 //DebugPrintF("#IRQ's = %ld\n", z);
528 if( flags & AHISF_RECORD && card->is_recording)
530 unsigned short rec_ctl, val;
531 unsigned char byte;
533 ClearMask(dev, card, CMPCI_REG_INTR_CTRL, CMPCI_REG_CH1_INTR_ENABLE);
534 ClearMask(dev, card, CMPCI_REG_FUNC_0, CMPCI_REG_CH1_ENABLE);
536 switch (card->input)
538 case 0: // line
539 cmimix_wr(dev, card, CMPCI_SB16_MIXER_OUTMIX, card->mixerstate);
540 break;
542 case 1: // mic
543 cmimix_wr(dev, card, CMPCI_SB16_MIXER_OUTMIX, card->mixerstate);
544 break;
546 case 2: // CD
547 cmimix_wr(dev, card, CMPCI_SB16_MIXER_OUTMIX, card->mixerstate);
548 break;
550 case 3: // Aux
551 byte = pci_inb(CMPCI_REG_MIXER25, card);
552 pci_outb(byte & ~0x30, CMPCI_REG_MIXER25, card); // mute Aux
553 break;
555 default:
556 break;
559 if( card->record_buffer != NULL )
561 pci_free_consistent( card->record_buffer_nonaligned);
564 card->record_buffer = NULL;
565 card->current_record_bytesize = 0;
567 card->is_recording = FALSE;
568 card->record_interrupt_enabled = FALSE;
573 /******************************************************************************
574 ** AHIsub_GetAttr *************************************************************
575 ******************************************************************************/
577 LONG
578 _AHIsub_GetAttr( ULONG attribute,
579 LONG argument,
580 LONG def,
581 struct TagItem* taglist,
582 struct AHIAudioCtrlDrv* AudioCtrl,
583 struct DriverBase* AHIsubBase )
585 struct CMI8738Base* CMI8738Base = (struct CMI8738Base*) AHIsubBase;
586 int i;
588 bug("[CMI8738]: %s()\n", __PRETTY_FUNCTION__);
590 struct CMI8738_DATA* card = (struct CMI8738_DATA*) AudioCtrl->ahiac_DriverData;
591 if (card == NULL)
593 int card_num = ( GetTagData( AHIDB_AudioID, 0, taglist) & 0x0000f000 ) >> 12;
595 if( card_num <= CMI8738Base->cards_found ||
596 CMI8738Base->driverdatas[ card_num ] != NULL )
597 card = CMI8738Base->driverdatas[ card_num ];
599 bug("[CMI8738] %s: card data @ 0x%p\n", __PRETTY_FUNCTION__, card);
601 switch( attribute )
603 case AHIDB_Bits:
604 return 16;
606 case AHIDB_MaxChannels:
607 if (card)
608 return card->channels;
609 return 2;
611 case AHIDB_Frequencies:
612 return FREQUENCIES;
614 case AHIDB_Frequency: // Index->Frequency
615 return (LONG) Frequencies[ argument ];
617 case AHIDB_Index: // Frequency->Index
618 if( argument <= (LONG) Frequencies[ 0 ] )
620 return 0;
623 if( argument >= (LONG) Frequencies[ FREQUENCIES - 1 ] )
625 return FREQUENCIES-1;
628 for( i = 1; i < FREQUENCIES; i++ )
630 if( (LONG) Frequencies[ i ] > argument )
632 if( ( argument - (LONG) Frequencies[ i - 1 ] ) < ( (LONG) Frequencies[ i ] - argument ) )
634 return i-1;
636 else
638 return i;
643 return 0; // Will not happen
645 case AHIDB_Author:
646 return (LONG) "Davy Wentzler";
648 case AHIDB_Copyright:
649 return (LONG) "(C) 2011 The AROS Dev Team";
651 case AHIDB_Version:
652 return (LONG) LibIDString;
654 case AHIDB_Annotation:
655 return (LONG) "AROS CMI8738 Audio driver";
657 case AHIDB_Record:
658 return TRUE;
660 case AHIDB_FullDuplex:
661 return TRUE;
663 case AHIDB_Realtime:
664 return TRUE;
666 case AHIDB_MaxRecordSamples:
667 return RECORD_BUFFER_SAMPLES;
669 /* formula's:
670 #include <math.h>
672 unsigned long res = (unsigned long) (0x10000 * pow (10.0, dB / 20.0));
673 double dB = 20.0 * log10(0xVALUE / 65536.0);
675 printf("dB = %f, res = %lx\n", dB, res);*/
677 case AHIDB_MinMonitorVolume:
678 return 0x00000;
680 case AHIDB_MaxMonitorVolume:
681 return 0x00000;
683 case AHIDB_MinInputGain:
684 return 0x10000; // 0.0 dB gain
686 case AHIDB_MaxInputGain:
687 return 0x10000; // 0 dB gain
689 case AHIDB_MinOutputVolume:
690 return 0x34; // -62 dB
692 case AHIDB_MaxOutputVolume:
693 return 0x10000; // 0 dB
695 case AHIDB_Inputs:
696 return INPUTS;
698 case AHIDB_Input:
699 return (LONG) Inputs[ argument ];
701 case AHIDB_Outputs:
702 return OUTPUTS;
704 case AHIDB_Output:
705 return (LONG) Outputs[ argument ];
707 default:
708 return def;
713 /******************************************************************************
714 ** AHIsub_HardwareControl *****************************************************
715 ******************************************************************************/
717 ULONG
718 _AHIsub_HardwareControl( ULONG attribute,
719 LONG argument,
720 struct AHIAudioCtrlDrv* AudioCtrl,
721 struct DriverBase* AHIsubBase )
723 struct CMI8738Base* CMI8738Base = (struct CMI8738Base*) AHIsubBase;
724 struct CMI8738_DATA* card = (struct CMI8738_DATA*) AudioCtrl->ahiac_DriverData;
725 struct PCIDevice *dev = card->pci_dev;
726 unsigned char byte;
728 bug("[CMI8738]: %s()\n", __PRETTY_FUNCTION__);
730 switch( attribute )
732 case AHIC_MonitorVolume:
733 card->monitor_volume = Linear2MixerGain( (Fixed) argument, &card->monitor_volume_bits );
734 //DebugPrintF("card->monitor_volume = %lu, %lx\n", card->monitor_volume, card->monitor_volume);
735 if( card->is_recording )
737 UpdateMonitorMixer( card );
739 return TRUE;
741 case AHIC_MonitorVolume_Query:
742 return card->monitor_volume;
744 case AHIC_InputGain:
745 card->input_gain = Linear2RecordGain( (Fixed) argument, &card->input_gain_bits );
746 //codec_write(card, AC97_RECORD_GAIN, card->input_gain_bits );
747 return TRUE;
749 case AHIC_InputGain_Query:
750 return card->input_gain;
752 case AHIC_OutputVolume:
754 double dB = 20.0 * log10((Fixed) argument / 65536.0);
755 unsigned int val = 0xFF - ( ((unsigned int)(-dB/2)) << 3);
756 cmimix_wr(dev, card, 0x30, val);
757 cmimix_wr(dev, card, 0x31, val);
758 return TRUE;
760 case AHIC_OutputVolume_Query:
761 return card->output_volume;
763 case AHIC_Input:
764 card->input = argument;
766 switch (card->input)
768 case 0: // line
769 cmimix_wr(dev, card, CMPCI_SB16_MIXER_ADCMIX_L, (CMPCI_SB16_MIXER_LINE_SRC_R << 1) );
770 cmimix_wr(dev, card, CMPCI_SB16_MIXER_ADCMIX_R, CMPCI_SB16_MIXER_LINE_SRC_R );
771 break;
773 case 1: // mic
774 cmimix_wr(dev, card, CMPCI_SB16_MIXER_ADCMIX_L, CMPCI_SB16_MIXER_MIC_SRC);
775 cmimix_wr(dev, card, CMPCI_SB16_MIXER_ADCMIX_R, CMPCI_SB16_MIXER_MIC_SRC);
776 break;
778 case 2: // CD
779 cmimix_wr(dev, card, CMPCI_SB16_MIXER_ADCMIX_L, (CMPCI_SB16_MIXER_CD_SRC_R << 1) );
780 cmimix_wr(dev, card, CMPCI_SB16_MIXER_ADCMIX_R, CMPCI_SB16_MIXER_CD_SRC_R );
781 break;
783 case 3: // Aux
784 byte = pci_inb(CMPCI_REG_MIXER25, card);
785 pci_outb(byte | 0xC0, CMPCI_REG_MIXER25, card); // rec source Aux
786 break;
788 case 4: // SPDIF
790 break;
792 default:
793 break;
796 if( card->is_recording )
798 UpdateMonitorMixer( card );
801 return TRUE;
803 case AHIC_Input_Query:
804 return card->input;
806 case AHIC_Output:
807 card->output = argument;
809 if( card->output == 0 )
811 ClearMask(dev, card, CMPCI_REG_FUNC_1, CMPCI_REG_SPDIFOUT_DAC | CMPCI_REG_SPDIF0_ENABLE);
812 ClearMask(dev, card, CMPCI_REG_LEGACY_CTRL, CMPCI_REG_XSPDIF_ENABLE);
814 else
816 WriteMask(dev, card, CMPCI_REG_FUNC_1, CMPCI_REG_SPDIFOUT_DAC | CMPCI_REG_SPDIF0_ENABLE);
817 WriteMask(dev, card, CMPCI_REG_LEGACY_CTRL, CMPCI_REG_XSPDIF_ENABLE);
819 return TRUE;
821 case AHIC_Output_Query:
822 return card->output;
824 default:
825 return FALSE;