revert between 56095 -> 55830 in arch
[AROS.git] / workbench / devs / AHI / Drivers / Envy24HT / main.c
blobb73d64e5a331921be532df6c7308044c61f0b1a2
1 /*
2 Copyright © 2005-2013, Davy Wentzler. All rights reserved.
3 $Id$
4 */
6 #include <config.h>
7 #include "pci_wrapper.h"
9 #ifdef __amigaos4__
10 #undef __USE_INLINE__
11 #include <proto/expansion.h>
12 extern struct UtilityIFace* IUtility;
13 extern struct AHIsubIFace* IAHIsub;
14 extern struct MMUIFace* IMMU;
15 #endif
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>
25 #include <math.h>
27 #include <string.h>
29 #ifdef __amigaos4__
30 #include "library_card.h"
31 #elif __MORPHOS__
32 #include "library_mos.h"
33 #else
34 #include "library.h"
35 #endif
36 #include "regs.h"
37 #include "misc.h"
38 #include "DriverData.h"
39 #include "Revo51.h"
42 extern int z;
44 /******************************************************************************
45 ** Globals ********************************************************************
46 ******************************************************************************/
48 #define FREQUENCIES 15
50 static const ULONG Frequencies[ FREQUENCIES ] =
52 8000,
53 9600,
54 11025,
55 12000,
56 16000,
57 22050,
58 24000,
59 32000,
60 44100, // CD
61 48000,
62 64000,
63 88200,
64 96000,
65 176400,
66 192000
69 static const ULONG FrequencyBits[ FREQUENCIES ] =
73 10,
81 15,
82 11,
84 12,
85 14 // 176.4 KHz: only when CCS_SYSTEM_CONFIG:6 = 1 or (MT_I2S_FORMAT:MT_CLOCK_128x = 1 & CCS_SYSTEM_CONFIG:6 = 0)
89 #define SPDIF_FREQUENCIES 7
91 static const ULONG SPDIF_Frequencies[ SPDIF_FREQUENCIES ] =
93 32000,
94 44100, // CD
95 48000,
96 88200,
97 96000,
98 176400,
99 192000
102 #if 0
103 static const ULONG SPDIF_FrequencyBits[ SPDIF_FREQUENCIES ] =
113 #endif
117 #define INPUTS 12
119 static const STRPTR Inputs[ INPUTS ] __attribute__((used)) =
121 "CD in (16-bit)",
122 "CD in (24-bit)",
123 "Aux in (16-bit)",
124 "Aux in (24-bit)",
125 "Line in (16-bit)",
126 "Line in (24-bit)",
127 "Mic in (16-bit)",
128 "Mic in (24-bit)",
129 "Mix in (16-bit)",
130 "Mix in (24-bit)",
131 "Digital in (16-bit)",
132 "Digital in (24-bit)"
135 #define INPUTS_PHASE28 4 // also for JULIA
136 static const STRPTR Inputs_Phase28[ INPUTS_PHASE28 ] __attribute__((used)) =
138 "Line in (16-bit)",
139 "Line in (24-bit)",
140 "Digital in (16-bit)",
141 "Digital in (24-bit)"
145 #define INPUTS_REVO71 2
146 static const STRPTR Inputs_Revo71[ INPUTS_REVO71 ] __attribute__((used)) =
148 "Line in (16-bit)",
149 "Line in (24-bit)"
152 #define INPUTS_REVO51 3
153 static const STRPTR Inputs_Revo51[ INPUTS_REVO51 ] __attribute__((used)) =
155 "Mic in",
156 "Line in",
157 "CD in"
161 #define OUTPUTS 1
163 static const STRPTR Outputs[ OUTPUTS ] =
165 "Line & Digital",
169 /******************************************************************************
170 ** AHIsub_AllocAudio **********************************************************
171 ******************************************************************************/
173 ULONG
174 _AHIsub_AllocAudio( struct TagItem* taglist,
175 struct AHIAudioCtrlDrv* AudioCtrl,
176 struct DriverBase* AHIsubBase )
178 struct CardBase* CardBase = (struct CardBase*) AHIsubBase;
180 int card_num;
181 ULONG ret;
182 int i;
184 card_num = ( GETTAGDATA( AHIDB_AudioID, 0, taglist) & 0x0000f000 ) >> 12;
186 if( card_num >= CardBase->cards_found ||
187 CardBase->driverdatas[ card_num ] == NULL )
189 DEBUGPRINTF("no data for card = %ld\n", card_num);
190 Req( "No CardData for card %ld.", card_num );
191 return AHISF_ERROR;
193 else
195 struct CardData* card;
196 BOOL in_use;
198 card = CardBase->driverdatas[ card_num ];
199 AudioCtrl->ahiac_DriverData = card;
201 OBTAINSEMAPHORE( &CardBase->semaphore );
202 in_use = ( card->audioctrl != NULL );
203 if( !in_use )
205 card->audioctrl = AudioCtrl;
207 RELEASESEMAPHORE( &CardBase->semaphore );
209 if( in_use )
211 return AHISF_ERROR;
214 card->playback_interrupt_enabled = FALSE;
215 card->record_interrupt_enabled = FALSE;
218 ret = AHISF_KNOWHIFI | AHISF_KNOWSTEREO | AHISF_MIXING | AHISF_TIMING;
221 for( i = 0; i < FREQUENCIES; ++i )
223 if( AudioCtrl->ahiac_MixFreq == Frequencies[ i ] )
225 ret |= AHISF_CANRECORD;
226 break;
230 return ret;
235 /******************************************************************************
236 ** AHIsub_FreeAudio ***********************************************************
237 ******************************************************************************/
239 void
240 _AHIsub_FreeAudio( struct AHIAudioCtrlDrv* AudioCtrl,
241 struct DriverBase* AHIsubBase )
243 struct CardBase* CardBase = (struct CardBase*) AHIsubBase;
244 struct CardData* card = (struct CardData*) AudioCtrl->ahiac_DriverData;
246 if( card != NULL )
248 OBTAINSEMAPHORE( &CardBase->semaphore );
249 if( card->audioctrl == AudioCtrl )
251 // Release it if we own it.
252 card->audioctrl = NULL;
254 RELEASESEMAPHORE( &CardBase->semaphore );
256 AudioCtrl->ahiac_DriverData = NULL;
261 /******************************************************************************
262 ** AHIsub_Disable *************************************************************
263 ******************************************************************************/
265 void
266 _AHIsub_Disable( struct AHIAudioCtrlDrv* AudioCtrl,
267 struct DriverBase* AHIsubBase )
269 // V6 drivers do not have to preserve all registers
271 #ifdef __amigaos4__
272 IExec->Disable();
273 #else
274 Disable();
275 #endif
279 /******************************************************************************
280 ** AHIsub_Enable **************************************************************
281 ******************************************************************************/
283 void
284 _AHIsub_Enable( struct AHIAudioCtrlDrv* AudioCtrl,
285 struct DriverBase* AHIsubBase )
287 // V6 drivers do not have to preserve all registers
289 #ifdef __amigaos4__
290 IExec->Enable();
291 #else
292 Enable();
293 #endif
298 /******************************************************************************
299 ** AHIsub_Start ***************************************************************
300 ******************************************************************************/
302 ULONG
303 _AHIsub_Start( ULONG flags,
304 struct AHIAudioCtrlDrv* AudioCtrl,
305 struct DriverBase* AHIsubBase )
307 struct CardData* card = (struct CardData*) AudioCtrl->ahiac_DriverData;
308 ULONG dma_buffer_size = 0;
309 int i, freqbit = 9;
310 BOOL SPDIF = FALSE;
311 unsigned char RMASK = MT_RDMA0_MASK;
312 #ifdef __amigaos4__
313 APTR stack;
314 #endif
316 /* Stop playback/recording, free old buffers (if any) */
317 //IAHIsub->AHIsub_Stop( flags, AudioCtrl );
319 for( i = 0; i < FREQUENCIES; ++i )
321 if( AudioCtrl->ahiac_MixFreq == Frequencies[ i ] )
323 freqbit = i;
324 break;
328 for( i = 0; i < SPDIF_FREQUENCIES; ++i )
330 if( AudioCtrl->ahiac_MixFreq == SPDIF_Frequencies[ i ] )
332 SPDIF = TRUE;
333 break;
337 OUTBYTE(card->mtbase + MT_SAMPLERATE, FrequencyBits[freqbit]);
338 OUTBYTE(card->mtbase + MT_DMAI_BURSTSIZE, 2); // set to stereo pair mode
341 if( flags & AHISF_PLAY )
344 ULONG dma_sample_frame_size;
346 /* Allocate a new mixing buffer. Note: The buffer must be cleared, since
347 it might not be filled by the mixer software interrupt because of
348 pretimer/posttimer! */
350 card->mix_buffer = ALLOCVEC( AudioCtrl->ahiac_BuffSize, MEMF_PUBLIC | MEMF_CLEAR );
352 if( card->mix_buffer == NULL )
354 Req( "Unable to allocate %ld bytes for mixing buffer.", AudioCtrl->ahiac_BuffSize );
355 return AHIE_NOMEM;
358 /* Allocate a buffer large enough for 32-bit double-buffered playback (only stereo) */
360 dma_sample_frame_size = 16; // we need 4-channel, otherwise the length can't be divided by 8
361 dma_buffer_size = AudioCtrl->ahiac_MaxBuffSamples * dma_sample_frame_size;
363 //DEBUGPRINTF("dma_buffer_size = %lu\n", dma_buffer_size);
365 /*if (dma_buffer_size != card->current_bytesize)
367 if (card->playback_buffer)
369 DEBUGPRINTF("Freeing prev buffer\n");
370 pci_free_consistent(card->playback_buffer_nonaligned);
373 card->playback_buffer = pci_alloc_consistent(dma_buffer_size * 2, &card->playback_buffer_nonaligned, 4096);
374 card->spdif_out_buffer = pci_alloc_consistent(dma_buffer_size, &card->spdif_out_buffer_nonaligned, 4096); // only stereo
376 if (!card->playback_buffer || !card->spdif_out_buffer)
378 Req( "Unable to allocate playback buffer." );
379 return AHIE_NOMEM;
382 ClearMask8(card, card->mtbase, MT_DMA_CONTROL, MT_PDMA0_START | MT_PDMA4_START); // stop
383 ClearMask8(card, card->mtbase, MT_INTR_MASK, MT_PDMA0_MASK); // allow PDMA0 interrupts
385 card->current_bytesize = dma_buffer_size;
386 card->current_frames = AudioCtrl->ahiac_MaxBuffSamples;
387 card->current_buffer = card->playback_buffer + card->current_bytesize;
388 card->spdif_out_current_buffer = card->spdif_out_buffer + card->current_bytesize / 2;
389 card->playback_interrupt_enabled = TRUE;
391 #ifdef __amigaos4__
392 stack = IExec->SuperState();
393 card->playback_buffer_phys = IMMU->GetPhysicalAddress(card->playback_buffer);
394 card->spdif_out_buffer_phys = IMMU->GetPhysicalAddress(card->spdif_out_buffer);
395 IExec->UserState(stack);
396 #elif __MORPHOS__
397 card->playback_buffer_phys =
398 ahi_pci_logic_to_physic_addr(card->playback_buffer, card->pci_dev);
399 card->spdif_out_buffer_phys =
400 ahi_pci_logic_to_physic_addr(card->spdif_out_buffer, card->pci_dev);
401 #else
402 card->playback_buffer_phys = card->playback_buffer;
403 card->spdif_out_buffer_phys = card->spdif_out_buffer; // if SPDIF were false, this pointer wouldn't get initialized, which might mean trouble in the IRQ
404 #endif
406 OUTLONG(card->mtbase + MT_DMAI_PB_ADDRESS,
407 (ULONG)card->playback_buffer_phys);
409 //kprintf("card->playback_buffer_phys = %lx, virt = %lx\n", card->playback_buffer_phys, card->playback_buffer);
410 //DEBUGPRINTF("addr = %lx, %lx\n", card->playback_buffer_phys, INLONG(card->mtbase + MT_DMAI_PB_ADDRESS));
412 //DEBUGPRINTF("dmai length = %lu\n", (dma_buffer_size * 2) / 4 - 1);
413 OUTWORD(card->mtbase + MT_DMAI_PB_LENGTH, (dma_buffer_size * 2) / 4 - 1);
414 OUTBYTE(card->mtbase + MT_DMAI_PB_LENGTH + 2, 0);
415 OUTWORD(card->mtbase + MT_DMAI_INTLEN, (dma_buffer_size * 1) / 4 - 1);
417 card->flip = 0;
419 // enable S/PDIF out
420 if (SPDIF)
422 ClearMask8(card, card->iobase, CCS_SPDIF_CONFIG, CCS_SPDIF_INTEGRATED); // disable: see doc: 4-27
424 OUTWORD(card->mtbase + MT_SPDIF_TRANSMIT, 0x04 | 1 << 5 | (FrequencyBits[freqbit] << 12)); // dig/dig converter
426 WriteMask8(card, card->iobase, CCS_SPDIF_CONFIG, CCS_SPDIF_INTEGRATED); // enable
428 OUTLONG(card->mtbase + MT_PDMA4_ADDRESS,
429 (ULONG)card->spdif_out_buffer_phys);
430 OUTWORD(card->mtbase + MT_PDMA4_LENGTH, (dma_buffer_size ) / 4 - 1);
431 OUTWORD(card->mtbase + MT_PDMA4_INTLEN, (dma_buffer_size / 2) / 4 - 1);
435 WriteMask8(card, card->mtbase, MT_INTR_STATUS, MT_DMA_FIFO | MT_PDMA0 | MT_PDMA4); // clear possibly pending interrupts
438 if( flags & AHISF_RECORD )
440 if ((card->SubType == PHASE28 && card->input >= 2) ||
441 (card->SubType == JULIA && card->input >= 2) ||
442 (card->SubType == PHASE22 && card->input >= 2) ||
443 (card->SubType != AUREON_SKY && card->input >= 10)) { // digital in
444 //unsigned long GPIO;
446 RMASK = MT_RDMA1_MASK;
447 //GPIO = GetGPIOData(card, card->iobase);
448 //DEBUGPRINTF("%d %d %d\n", (GPIO & PHASE28_FREQ2) >> 16, (GPIO & PHASE28_FREQ1) >> 21, (GPIO & PHASE28_FREQ0) >> 22);
450 WriteMask8(card, card->mtbase, MT_SAMPLERATE, MT_SPDIF_MASTER); // tbd!
453 card->current_record_bytesize_32bit = RECORD_BUFFER_SAMPLES * 4 * 2; // 32-bit stereo
455 //DEBUGPRINTF("REC: current_record_bytesize = %ld\n", card->current_record_bytesize_32bit);
457 /* Allocate a new recording buffer (page aligned!) */
458 card->record_buffer = pci_alloc_consistent(card->current_record_bytesize_32bit, &card->record_buffer_nonaligned, 4096);
459 card->record_buffer_32bit = pci_alloc_consistent(card->current_record_bytesize_32bit * 2, &card->record_buffer_nonaligned_32bit, 4096);
461 if( card->record_buffer == NULL || card->record_buffer_32bit == NULL)
463 Req( "Unable to allocate %ld bytes for the recording buffer.", card->current_record_bytesize_32bit);
464 return AHIE_NOMEM;
467 SaveMixerState( card );
468 UpdateMonitorMixer( card );
471 ClearMask8(card, card->mtbase, MT_DMA_CONTROL, RMASK); // stop
472 ClearMask8(card, card->mtbase, MT_INTR_MASK, RMASK);
474 card->current_record_buffer = card->record_buffer + card->current_record_bytesize_32bit / 2;
475 card->current_record_buffer_32bit = card->record_buffer_32bit + card->current_record_bytesize_32bit;
477 #ifdef __amigaos4__
478 stack = IExec->SuperState();
479 card->record_buffer_32bit_phys = IMMU->GetPhysicalAddress(card->record_buffer_32bit);
480 IExec->UserState(stack);
481 #elif __MORPHOS__
482 card->record_buffer_32bit_phys =
483 ahi_pci_logic_to_physic_addr(card->record_buffer_32bit, card->pci_dev);
484 #else
485 card->record_buffer_32bit_phys = card->record_buffer_32bit;
486 #endif
488 if (RMASK == MT_RDMA0_MASK)
490 OUTLONG(card->mtbase + MT_RDMA0_ADDRESS, (long) card->record_buffer_32bit_phys);
491 OUTWORD(card->mtbase + MT_RDMA0_LENGTH, (card->current_record_bytesize_32bit * 2) / 4 - 1);
492 OUTWORD(card->mtbase + MT_RDMA0_INTLEN, (card->current_record_bytesize_32bit * 1) / 4 - 1);
495 else
497 OUTLONG(card->mtbase + MT_RDMA1_ADDRESS, (long) card->record_buffer_32bit_phys);
498 OUTWORD(card->mtbase + MT_RDMA1_LENGTH, (card->current_record_bytesize_32bit * 2) / 4 - 1);
499 OUTWORD(card->mtbase + MT_RDMA1_INTLEN, (card->current_record_bytesize_32bit * 1) / 4 - 1);
502 card->record_interrupt_enabled = TRUE;
503 card->recflip = 0;
505 if (card->SubType == AUREON_SKY || card->SubType == AUREON_SPACE || card->SubType == PHASE28)
506 wm_put(card, card->iobase, 0x1C, 0x0D); // turn on zero-latency monitoring and PCM, disable AC97 mix
509 WriteMask8(card, card->mtbase, MT_INTR_STATUS, RMASK);
512 if( flags & AHISF_PLAY )
514 unsigned char start = MT_PDMA0_START;
515 /*int i;*/
517 if (SPDIF)
519 start |= MT_PDMA4_START;
522 card->is_playing = TRUE;
524 //DEBUGPRINTF("START\n");
526 //DEBUGPRINTF("Config 4-5 = %x\n", READCONFIGWORD( PCI_COMMAND ));
527 // DEBUGPRINTF("BAR0 = %lx\n", dev->ReadConfigLong(0x10));
528 // DEBUGPRINTF("BAR1 = %lx\n", dev->ReadConfigLong(0x14));
530 /*for (i = 0; i <= 0x1F; i++)
532 DEBUGPRINTF("CCS %02d (%02x) = %x\n", i, i, INBYTE(card->iobase + i));
535 for (i = 0; i <= 0x76; i+=4)
537 DEBUGPRINTF("MT %02d (%02x) = %lx\n", i, i, INLONG(card->mtbase + i));
540 WriteMask8(card, card->mtbase, MT_DMA_CONTROL, start);
543 if( flags & AHISF_RECORD )
545 card->is_recording = TRUE;
546 WriteMask8(card, card->mtbase, MT_DMA_CONTROL, RMASK);
549 return AHIE_OK;
553 /******************************************************************************
554 ** AHIsub_Update **************************************************************
555 ******************************************************************************/
557 void
558 _AHIsub_Update( ULONG flags,
559 struct AHIAudioCtrlDrv* AudioCtrl,
560 struct DriverBase* AHIsubBase )
562 /*struct CardBase* CardBase = (struct CardBase*) AHIsubBase;
563 struct CardData* card = (struct CardData*) AudioCtrl->ahiac_DriverData;
565 card->current_frames = AudioCtrl->ahiac_BuffSamples;
567 if( AudioCtrl->ahiac_Flags & AHIACF_STEREO )
569 card->current_bytesize = card->current_frames * 4;
571 else
573 card->current_bytesize = card->current_frames * 2;
578 /******************************************************************************
579 ** AHIsub_Stop ****************************************************************
580 ******************************************************************************/
582 void
583 _AHIsub_Stop( ULONG flags,
584 struct AHIAudioCtrlDrv* AudioCtrl,
585 struct DriverBase* AHIsubBase )
587 struct CardData* card = (struct CardData*) AudioCtrl->ahiac_DriverData;
588 unsigned char RMASK = MT_RDMA0_MASK;
590 if( flags & AHISF_PLAY && card->is_playing)
592 card->is_playing= FALSE;
594 ClearMask8(card, card->mtbase, MT_DMA_CONTROL, MT_PDMA0_START | MT_PDMA4_START);
595 WriteMask8(card, card->mtbase, MT_INTR_MASK, MT_DMA_FIFO_MASK | MT_PDMA0_MASK);
597 if (card->current_bytesize > 0) {
598 pci_free_consistent(card->playback_buffer_nonaligned);
599 pci_free_consistent(card->spdif_out_buffer_nonaligned);
602 card->current_bytesize = 0;
603 card->current_frames = 0;
604 card->current_buffer = NULL;
606 if (card->mix_buffer) {
607 FREEVEC( card->mix_buffer );
609 card->mix_buffer = NULL;
610 card->playback_interrupt_enabled = FALSE;
613 if( flags & AHISF_RECORD && card->is_recording)
615 card->is_recording = FALSE;
616 if ((card->SubType == PHASE28 && card->input >= 2) ||
617 (card->SubType == JULIA && card->input >= 2) ||
618 (card->SubType != PHASE28 && card->input >= 10))
619 RMASK = MT_RDMA1_MASK;
621 ClearMask8(card, card->mtbase, MT_DMA_CONTROL, RMASK);
622 WriteMask8(card, card->mtbase, MT_INTR_MASK, RMASK);
624 if (card->SubType == AUREON_SKY || card->SubType == AUREON_SPACE || card->SubType == PHASE28)
626 wm_put(card, card->iobase, 0x1C, 0x0B); // turn off zero-latency monitoring: enable PCM and AC97 mix
629 DELAY(1);
631 if( card->record_buffer != NULL )
633 pci_free_consistent( card->record_buffer_nonaligned );
634 pci_free_consistent( card->record_buffer_nonaligned_32bit );
637 card->record_buffer = NULL;
638 card->current_record_bytesize_32bit = 0;
639 card->record_buffer_32bit = NULL;
640 card->record_interrupt_enabled = FALSE;
646 /******************************************************************************
647 ** AHIsub_GetAttr *************************************************************
648 ******************************************************************************/
650 LONG
651 _AHIsub_GetAttr( ULONG attribute,
652 LONG argument,
653 LONG def,
654 struct TagItem* taglist,
655 struct AHIAudioCtrlDrv* AudioCtrl,
656 struct DriverBase* AHIsubBase )
658 struct CardBase* CardBase = (struct CardBase*) AHIsubBase;
659 struct CardData* card = CardBase->driverdatas[0]; // warning, don't take from AudioCtrl, since it is not always
660 // initialized before a call to GetAttr()!!!
661 int i;
663 switch( attribute )
665 case AHIDB_Bits:
666 return 16;
668 case AHIDB_Frequencies:
669 if (card->SubType == PHASE22)
670 return FREQUENCIES - 2;
671 else
672 return FREQUENCIES;
674 case AHIDB_Frequency: // Index->Frequency
675 return (LONG) Frequencies[ argument ];
677 case AHIDB_Index: // Frequency->Index
678 if( argument <= (LONG) Frequencies[ 0 ] )
680 return 0;
683 if( argument >= (LONG) Frequencies[ FREQUENCIES - 1 ] )
685 return FREQUENCIES-1;
688 for( i = 1; i < FREQUENCIES; i++ )
690 if( (LONG) Frequencies[ i ] > argument )
692 if( ( argument - (LONG) Frequencies[ i - 1 ] ) < ( (LONG) Frequencies[ i ] - argument ) )
694 return i-1;
696 else
698 return i;
703 return 0; // Will not happen
705 case AHIDB_Author:
706 return (LONG) "Davy Wentzler";
708 case AHIDB_Copyright:
709 return (LONG) "(C) Davy Wentzler";
711 case AHIDB_Version:
712 return (LONG) LibIDString;
714 case AHIDB_Annotation:
715 return (LONG)
716 "Terratec Aureon, Phase22/28, M-Audio Revolution 5.1/7.1 and ESI Juli@ driver";
718 case AHIDB_Record:
719 return TRUE;
721 case AHIDB_FullDuplex:
722 return TRUE;
724 case AHIDB_Realtime:
725 return TRUE;
727 case AHIDB_MaxRecordSamples:
728 return RECORD_BUFFER_SAMPLES;
730 /* formula's:
731 #include <math.h>
733 unsigned long res = (unsigned long) (0x10000 * pow (10.0, dB / 20.0));
734 double dB = 20.0 * log10(0xVALUE / 65536.0);
736 printf("dB = %f, res = %lx\n", dB, res);*/
738 case AHIDB_MinMonitorVolume:
739 if (card->SubType == REVO51)
740 return 7; // -79dB
741 else
742 return 0x00000;
744 case AHIDB_MaxMonitorVolume:
745 if (card->SubType == REVO51)
746 return 0x10000;
747 else
748 return 0x00000;
750 case AHIDB_MinInputGain:
751 if (card->SubType == REVO71 || card->SubType == JULIA || card->SubType == PHASE22)
752 return 0x10000;
753 else if (card->SubType == REVO51)
754 return 0x10000;
755 else
756 return 0x404D; // -12 dB gain
758 case AHIDB_MaxInputGain:
759 if (card->SubType == REVO71 || card->SubType == JULIA)
760 return 0x10000;
761 else if (card->SubType == REVO51)
762 return 0x3FB27; // 12 dB
763 else if (card->SubType == PHASE22)
764 return 0x7F17A;
765 else
766 return 0x8E99A; // 19 dB gain
768 case AHIDB_MinOutputVolume:
769 if (card->SubType == PHASE22)
770 return 0x10000;
771 else
772 return 0x00000; // -100 dB / mute
774 case AHIDB_MaxOutputVolume:
775 return 0x10000; // 0 dB
777 case AHIDB_Inputs:
778 if (card->SubType == PHASE28 || card->SubType == JULIA || card->SubType == PHASE22)
779 return INPUTS_PHASE28;
780 else if (card->SubType == REVO71)
781 return INPUTS_REVO71;
782 else if (card->SubType == REVO51)
783 return INPUTS_REVO51;
784 else
785 return INPUTS;
787 case AHIDB_Input:
788 if (card->SubType == PHASE28 || card->SubType == JULIA || card->SubType == PHASE22)
789 return (LONG) Inputs_Phase28[ argument ];
790 else if (card->SubType == REVO71)
791 return (LONG) Inputs_Revo71[ argument ];
792 else if (card->SubType == REVO51)
793 return (LONG) Inputs_Revo51[ argument ];
794 else
795 return (LONG) Inputs[ argument ];
797 case AHIDB_Outputs:
798 return OUTPUTS;
800 case AHIDB_Output:
801 return (LONG) Outputs[ argument ];
803 default:
804 return def;
809 /******************************************************************************
810 ** AHIsub_HardwareControl *****************************************************
811 ******************************************************************************/
813 ULONG
814 _AHIsub_HardwareControl( ULONG attribute,
815 LONG argument,
816 struct AHIAudioCtrlDrv* AudioCtrl,
817 struct DriverBase* AHIsubBase )
819 struct CardData* card = (struct CardData*) AudioCtrl->ahiac_DriverData;
821 switch( attribute )
823 case AHIC_MonitorVolume:
824 card->monitor_volume = 0;
826 if (card->SubType == REVO51)
828 double dB = 20.0 * log10((Fixed) argument / 65536.0);
829 int val = (int) dB;
830 int offset = card->input * 4; // left/right (10dB/1dB)
831 unsigned char bytes[4];
833 int dB10 = -val / 10;
834 int dB1 = -val % 10;
835 bytes[0] = pt2258_db_codes[offset + 0] | dB10;
836 bytes[1] = pt2258_db_codes[offset + 1] | dB1;
837 bytes[2] = pt2258_db_codes[offset + 2] | dB10;
838 bytes[3] = pt2258_db_codes[offset + 3] | dB1;
839 //DEBUGPRINTF("MON offset = %d, %x %x\n", offset, bytes[0], bytes[1]);
840 WriteBytesI2C(card, card->i2c, bytes, 4);
842 return TRUE;
844 case AHIC_MonitorVolume_Query:
845 return card->monitor_volume;
847 case AHIC_InputGain:
848 card->input_gain = Linear2RecordGain( (Fixed) argument, &card->input_gain_bits );
849 //DEBUGPRINTF("gain = %lx, bits = %x, argument = %lx\n", card->input_gain, card->input_gain_bits, argument);
851 if (card->SubType != REVO71 && card->SubType != REVO51 && card->SubType != JULIA && card->SubType != PHASE22)
852 wm_put(card, card->iobase, 0x19, card->input_gain_bits | 0x40); // | LRBOTH
854 else if (card->SubType == PHASE22)
856 double dB = 20.0 * log10((Fixed) argument / 65536.0);
857 unsigned char val = 128 + (int) (dB * 2);
859 akm4xxx_write(card, card->RevoFrontCodec, 0, 0x04, val);
860 akm4xxx_write(card, card->RevoFrontCodec, 0, 0x05, val);
862 else if (card->SubType == REVO51)
864 double dB = 20.0 * log10((Fixed) argument / 65536.0);
865 unsigned char val = 0x80 + (int) (dB * 2);
867 akm4xxx_write_new(card, card->RevoRecCodec, 0, 0x04, val);
868 akm4xxx_write_new(card, card->RevoRecCodec, 0, 0x05, val);
870 return TRUE;
872 case AHIC_InputGain_Query:
873 return card->input_gain;
875 case AHIC_OutputVolume:
876 if (card->SubType != REVO71 && card->SubType != REVO51 && card->SubType != JULIA && card->SubType != PHASE22) {
877 card->output_volume = Linear2MixerGain( (Fixed) argument, &card->output_volume_bits );
879 //DEBUGPRINTF("AHI: output %x\n", card->output_volume_bits);
881 wm_put(card, card->iobase, 9, card->output_volume_bits | 0x100); // | update on all channels
882 wm_put(card, card->iobase, 10, card->output_volume_bits | 0x100);
884 else if (card->SubType == REVO71 || card->SubType == REVO51) {
885 double dB = 20.0 * log10((Fixed) argument / 65536.0);
886 unsigned int val = (unsigned int) (255.0 * pow(10.0, dB / 20.0));
888 card->output_volume = Linear2AKMGain( (Fixed) argument, &card->output_volume_bits );
890 if (card->SubType == REVO71)
892 akm4xxx_write(card, card->RevoFrontCodec, 0, 0x03, val);
893 akm4xxx_write(card, card->RevoFrontCodec, 0, 0x04, val);
895 akm4xxx_write(card, card->RevoSurroundCodec, 0, 0x04, card->output_volume_bits);
896 akm4xxx_write(card, card->RevoSurroundCodec, 0, 0x05, card->output_volume_bits);
898 else // REVO51
900 double dB;
901 unsigned int val;
903 if (argument == 0) // prevent overflow
904 argument = 1;
905 dB = -20.0 * log10((Fixed) argument / 65536.0);
907 if (dB > 63.0)
908 val = 0x80;
909 else
910 val = 0x80 | (0x7F - (unsigned int)(dB * 2));
912 //DEBUGPRINTF("arg = %ld, val = %lu, dB = %d\n", argument, val, (int) dB);
914 akm4xxx_write_new(card, card->RevoFrontCodec, 0, 0x04, val);
915 akm4xxx_write_new(card, card->RevoFrontCodec, 0, 0x05, val);
919 else if (card->SubType == JULIA) {
920 double dB = -20.0 * log10((Fixed) argument / 65536.0);
921 unsigned int val = 0x80 | (0x7F - (unsigned int)(dB * 2));
923 //DEBUGPRINTF("val = %x, dB = %ld.%ld\n", val, (int)(dB), (int) ((dB - (int)(dB)) * 1000) );
925 WriteI2C(card->pci_dev, card, AK4358_ADDR, 0x08, val); // dig out is conn. to the DAC as analogue out
926 WriteI2C(card->pci_dev, card, AK4358_ADDR, 0x09, val);
928 /*WriteI2C(card->pci_dev, card, AK4358_ADDR, 0x06, val);
929 WriteI2C(card->pci_dev, card, AK4358_ADDR, 0x07, val);
931 WriteI2C(card->pci_dev, card, AK4358_ADDR, 0x08, val);
932 WriteI2C(card->pci_dev, card, AK4358_ADDR, 0x09, val);
934 WriteI2C(card->pci_dev, card, AK4358_ADDR, 0x0B, val);
935 WriteI2C(card->pci_dev, card, AK4358_ADDR, 0x0C, val);*/
937 else if (card->SubType == PHASE22) {
940 //DEBUGPRINTF("card->output_volume = %lx, bits = %lx\n", card->output_volume, card->output_volume_bits);
941 return TRUE;
943 case AHIC_OutputVolume_Query:
944 return card->output_volume;
946 case AHIC_Input:
947 card->input = argument;
949 if (card->SubType == REVO51)
950 card->input_is_24bits = FALSE;
951 else
953 if (card->input % 2 == 0)
954 card->input_is_24bits = FALSE;
955 else
956 card->input_is_24bits = TRUE;
959 if (card->SubType != PHASE28 && card->input < 10 && card->SubType != REVO71 && card->SubType != REVO51 && card->SubType != JULIA && card->SubType != PHASE22) // analogue
960 wm_put(card, card->iobase, 0x1B, (card->input / 2) + 0x10 * (card->input / 2) );
961 else if (card->SubType == REVO51)
963 akm4xxx_write_new(card, card->RevoRecCodec, 0, 0x01, card->input);
966 if( card->is_recording )
968 UpdateMonitorMixer( card );
971 return TRUE;
973 case AHIC_Input_Query:
974 return card->input;
976 case AHIC_Output:
977 card->output = argument;
979 if( card->output == 0 )
982 else
985 return TRUE;
987 case AHIC_Output_Query:
988 return card->output;
990 default:
991 return FALSE;