grub2: bring back build of aros-side grub2 tools
[AROS.git] / workbench / devs / AHI / Drivers / Envy24 / main.c
blobb7574ea7f6884f91d21caa7f6b17b1dea7c07548
1 /*
2 Copyright © 2004-2014, Davy Wentzler. All rights reserved.
3 $Id$
4 */
6 #include <config.h>
8 #undef __USE_INLINE__
9 #include <proto/expansion.h>
10 #ifdef __amigaos4__
11 extern struct UtilityIFace* IUtility;
12 extern struct AHIsubIFace* IAHIsub;
13 extern struct MMUIFace* IMMU;
14 #endif
16 #include <devices/ahi.h>
17 #include <exec/memory.h>
18 #include <libraries/ahi_sub.h>
20 #include <proto/ahi_sub.h>
21 #include <proto/exec.h>
22 #include <proto/dos.h>
23 #include <proto/utility.h>
24 #include <math.h>
25 #include <string.h>
27 #include "library.h"
28 #include "regs.h"
29 #include "misc.h"
30 #include "pci_wrapper.h"
31 #include "DriverData.h"
34 /******************************************************************************
35 ** Globals ********************************************************************
36 ******************************************************************************/
38 #define FREQUENCIES 13
40 static const ULONG Frequencies[ FREQUENCIES ] =
42 8000,
43 9600,
44 11025,
45 12000,
46 16000,
47 22050,
48 24000,
49 32000,
50 44100, // CD
51 48000,
52 64000,
53 88200,
54 96000
57 static const ULONG FrequencyBits[ FREQUENCIES ] =
61 10,
69 15,
70 11,
78 #define INPUTS 4
80 static const STRPTR Inputs[ INPUTS ] =
82 "Mic/Line 1 - 2",
83 "Line 3 - 4",
84 "Line 5 - 6",
85 "Line 7 - 8",
86 // "S/PDIF",
90 #define INPUTS_2496 1
92 static const STRPTR Inputs_2496[ INPUTS ] =
94 "Line",
95 "S/PDIF",
98 #define OUTPUTS 4
100 static const STRPTR Outputs[ OUTPUTS ] =
102 "Line 1 - 2",
103 "Line 3 - 4",
104 "Line 5 - 6",
105 "Line 7 - 8",
106 // "S/PDIF",
109 #define OUTPUTS_2496 1
111 static const STRPTR Outputs_2496[ OUTPUTS ] =
113 "Line",
114 "S/PDIF",
117 #define INPUTS_DELTA44 2
119 static const STRPTR Inputs_Delta44[ INPUTS_DELTA44 ] =
121 "Line 1 - 2",
122 "Line 3 - 4"
125 #define OUTPUTS_DELTA44 1
127 static const STRPTR Outputs_Delta44[ OUTPUTS_DELTA44 ] =
129 "Line 1 - 2"
130 // "Line 3 - 4"
134 #define INPUTS_DELTA66 2
136 static const STRPTR Inputs_Delta66[ INPUTS_DELTA66 ] =
138 "Line 1 - 2",
139 "Line 3 - 4",
140 // "S/PDIF"
143 #define OUTPUTS_DELTA66 1
145 static const STRPTR Outputs_Delta66[ OUTPUTS_DELTA66 ] =
147 "Line 1 - 2"
148 // "Line 3 - 4",
149 // "S/PDIF"
151 /******************************************************************************
152 ** AHIsub_AllocAudio **********************************************************
153 ******************************************************************************/
155 ULONG
156 _AHIsub_AllocAudio( struct TagItem* taglist,
157 struct AHIAudioCtrlDrv* AudioCtrl,
158 struct DriverBase* AHIsubBase )
160 struct CardBase* CardBase = (struct CardBase*) AHIsubBase;
162 int card_num;
163 ULONG ret;
164 int i;
166 card_num = ( GetTagData( AHIDB_AudioID, 0, taglist) & 0x0000f000 ) >> 12;
168 if( card_num >= CardBase->cards_found ||
169 CardBase->driverdatas[ card_num ] == NULL )
171 DebugPrintF("no data for card = %ld\n", card_num);
172 Req( "No CardData for card %ld.", card_num );
173 return AHISF_ERROR;
175 else
177 struct CardData* card;
178 BOOL in_use;
180 card = CardBase->driverdatas[ card_num ];
181 AudioCtrl->ahiac_DriverData = card;
183 ObtainSemaphore( &CardBase->semaphore );
184 in_use = ( card->audioctrl != NULL );
185 if( !in_use )
187 card->audioctrl = AudioCtrl;
189 ReleaseSemaphore( &CardBase->semaphore );
191 if( in_use )
193 return AHISF_ERROR;
196 card->playback_interrupt_enabled = FALSE;
197 card->record_interrupt_enabled = FALSE;
200 ret = AHISF_KNOWHIFI | AHISF_KNOWSTEREO | AHISF_MIXING | AHISF_TIMING;
203 for( i = 0; i < FREQUENCIES; ++i )
205 if( AudioCtrl->ahiac_MixFreq == Frequencies[ i ] )
207 ret |= AHISF_CANRECORD;
208 break;
212 return ret;
217 /******************************************************************************
218 ** AHIsub_FreeAudio ***********************************************************
219 ******************************************************************************/
221 void
222 _AHIsub_FreeAudio( struct AHIAudioCtrlDrv* AudioCtrl,
223 struct DriverBase* AHIsubBase )
225 struct CardBase* CardBase = (struct CardBase*) AHIsubBase;
226 struct CardData* card = (struct CardData*) AudioCtrl->ahiac_DriverData;
228 if( card != NULL )
230 ObtainSemaphore( &CardBase->semaphore );
231 if( card->audioctrl == AudioCtrl )
233 // Release it if we own it.
234 card->audioctrl = NULL;
236 ReleaseSemaphore( &CardBase->semaphore );
238 AudioCtrl->ahiac_DriverData = NULL;
243 /******************************************************************************
244 ** AHIsub_Disable *************************************************************
245 ******************************************************************************/
247 void
248 _AHIsub_Disable( struct AHIAudioCtrlDrv* AudioCtrl,
249 struct DriverBase* AHIsubBase )
251 // V6 drivers do not have to preserve all registers
253 Disable();
257 /******************************************************************************
258 ** AHIsub_Enable **************************************************************
259 ******************************************************************************/
261 void
262 _AHIsub_Enable( struct AHIAudioCtrlDrv* AudioCtrl,
263 struct DriverBase* AHIsubBase )
265 // V6 drivers do not have to preserve all registers
267 Enable();
271 /******************************************************************************
272 ** AHIsub_Update **************************************************************
273 ******************************************************************************/
275 void
276 _AHIsub_Update( ULONG flags,
277 struct AHIAudioCtrlDrv* AudioCtrl,
278 struct DriverBase* AHIsubBase )
280 struct CardData* card = (struct CardData*) AudioCtrl->ahiac_DriverData;
282 card->current_frames = AudioCtrl->ahiac_BuffSamples;
284 if( AudioCtrl->ahiac_Flags & AHIACF_STEREO )
286 card->current_bytesize = card->current_frames * 4;
288 else
290 card->current_bytesize = card->current_frames * 2;
295 /******************************************************************************
296 ** AHIsub_Start ***************************************************************
297 ******************************************************************************/
299 ULONG
300 _AHIsub_Start( ULONG flags,
301 struct AHIAudioCtrlDrv* AudioCtrl,
302 struct DriverBase* AHIsubBase )
304 struct CardData* card = (struct CardData*) AudioCtrl->ahiac_DriverData;
305 ULONG dma_buffer_size = 0;
306 int i, freqbit = 9;
308 /* Stop playback/recording, free old buffers (if any) */
309 //IAHIsub->AHIsub_Stop( flags, AudioCtrl );
311 for( i = 0; i < FREQUENCIES; ++i )
313 if( AudioCtrl->ahiac_MixFreq == Frequencies[ i ] )
315 freqbit = i;
316 break;
320 if( flags & AHISF_PLAY )
323 ULONG dma_sample_frame_size;
325 /* Update cached/syncronized variables */
327 _AHIsub_Update( AHISF_PLAY, AudioCtrl, AHIsubBase);
329 /* Allocate a new mixing buffer. Note: The buffer must be cleared, since
330 it might not be filled by the mixer software interrupt because of
331 pretimer/posttimer! */
333 card->mix_buffer = AllocVec( AudioCtrl->ahiac_BuffSize, MEMF_PUBLIC | MEMF_CLEAR );
335 if( card->mix_buffer == NULL )
337 Req( "Unable to allocate %ld bytes for mixing buffer.", AudioCtrl->ahiac_BuffSize );
338 return AHIE_NOMEM;
341 /* Allocate a buffer large enough for 16-bit double-buffered playback (only stereo) */
343 dma_sample_frame_size = 40; // 5 stereo 32-bit streams
344 dma_buffer_size = AudioCtrl->ahiac_MaxBuffSamples * dma_sample_frame_size;
346 //DebugPrintF("dma_buffer_size = %ld, %lx (hex)\n", dma_buffer_size, dma_buffer_size);
348 card->playback_buffer = pci_alloc_consistent(dma_buffer_size * 2, &card->playback_buffer_nonaligned, AHIsubBase);
350 card->playback_buffer_phys = ahi_pci_logic_to_physic_addr(card->playback_buffer, card->pci_dev);
352 if (!card->playback_buffer)
354 Req( "Unable to allocate playback buffer." );
355 return AHIE_NOMEM;
358 ClearMask8(card, MT_DMA_CONTROL, MT_PLAY_START); // stop first
360 pci_outb_mt(FrequencyBits[freqbit] & MT_RATE_MASK, MT_SAMPLERATE, card);
361 //pci_outb_mt(0, MT_I2S_FORMAT, card);
362 ClearMask8(card, MT_INTR_MASK_STATUS, MT_PLAY_MASK);
364 card->current_bytesize = dma_buffer_size;
365 card->current_frames = AudioCtrl->ahiac_MaxBuffSamples;
366 card->current_buffer = card->playback_buffer + card->current_bytesize;
367 card->playback_interrupt_enabled = TRUE;
369 card->flip = 0;
371 pci_outl_mt((long) card->playback_buffer_phys, MT_DMA_PB_ADDRESS, card);
372 pci_outw_mt((dma_buffer_size * 2) / 4 - 1, MT_DMA_PB_LENGTH, card);
373 pci_outw_mt((dma_buffer_size * 1) / 4 - 1, MT_DMA_PB_INTLEN, card);
375 card->is_playing = TRUE;
377 //DebugPrintF("PLAY STARTED\n");
380 if( flags & AHISF_RECORD )
382 if ((card->SubType == PHASE88 && card->input >= 4) ||
383 (card->SubType == MAUDIO_1010LT && card->input >= 4) ||
384 (card->SubType == MAUDIO_2496 && card->input >= 1) ||
385 (card->SubType == MAUDIO_DELTA66 && card->input >= 3) ) { // digital in
387 WriteMask8(card, MT_SAMPLERATE, MT_SPDIF_MASTER); // tbd!
388 //DebugPrintF("REC: SPDIF is master\n");
391 WriteMask8(card, MT_SAMPLERATE, FrequencyBits[freqbit] & MT_RATE_MASK);
392 card->current_record_bytesize_target = RECORD_BUFFER_SAMPLES * 4;
393 card->current_record_bytesize_32bit = RECORD_BUFFER_SAMPLES * 48; // 12 tracks 32-bit
395 //DebugPrintF("REC: current_record_bytesize = %ld\n", card->current_record_bytesize_32bit);
397 /* Allocate a new recording buffer (page aligned!) */
398 card->record_buffer = pci_alloc_consistent(card->current_record_bytesize_target * 2, &card->record_buffer_nonaligned, AHIsubBase);
399 card->record_buffer_32bit = pci_alloc_consistent(card->current_record_bytesize_32bit * 2, &card->record_buffer_nonaligned_32bit, AHIsubBase);
401 if( card->record_buffer == NULL || card->record_buffer_32bit == NULL)
403 Req( "Unable to allocate %ld bytes for the recording buffer.", card->current_record_bytesize_32bit);
404 return AHIE_NOMEM;
407 ClearMask8(card, MT_DMA_CONTROL, MT_REC_START); // stop
408 pci_outb_mt(FrequencyBits[freqbit] & MT_RATE_MASK, MT_SAMPLERATE, card);
409 ClearMask8(card, MT_INTR_MASK_STATUS, MT_REC_MASK);
412 card->current_record_buffer = card->record_buffer + card->current_record_bytesize_target;
413 card->current_record_buffer_32bit = card->record_buffer_32bit + card->current_record_bytesize_32bit;
415 card->record_buffer_32bit_phys = ahi_pci_logic_to_physic_addr(card->record_buffer_32bit, card->pci_dev);
417 pci_outl_mt((long) card->record_buffer_32bit_phys, MT_DMA_REC_ADDRESS, card);
418 pci_outw_mt((card->current_record_bytesize_32bit * 2) / 4 - 1, MT_DMA_REC_LENGTH, card);
419 pci_outw_mt((card->current_record_bytesize_32bit * 1) / 4 - 1, MT_DMA_REC_INTLEN, card);
421 card->record_interrupt_enabled = TRUE;
422 card->recflip = 0;
424 card->is_recording = TRUE;
427 for (i = 0x60; i < 0x64; i++)
428 DebugPrintF("config %lx = %x\n", i, inb_config(i, card->pci_dev));
430 for (i = 0x0; i < 0x1E; i++)
431 DebugPrintF("CCS %lx = %x\n", i, pci_inb(i, card));
433 for (i = 0x0; i < 0x31; i++)
434 DebugPrintF("CCI %lx = %x\n", i, ReadCCI(card, i));
436 for (i = 0x0; i < 0x34; i++)
437 DebugPrintF("MT %lx = %x\n", i, pci_inb_mt(i, card));
439 if( flags & AHISF_PLAY )
441 WriteMask8(card, MT_DMA_CONTROL, MT_PLAY_START);
444 if( flags & AHISF_RECORD )
446 //DebugPrintF("REC STARTED, freqbit = %ld\n", freqbit);
447 WriteMask8(card, MT_DMA_CONTROL, MT_REC_START);
450 return AHIE_OK;
454 /******************************************************************************
455 ** AHIsub_Stop ****************************************************************
456 ******************************************************************************/
458 void
459 _AHIsub_Stop( ULONG flags,
460 struct AHIAudioCtrlDrv* AudioCtrl,
461 struct DriverBase* AHIsubBase )
463 struct CardData* card = (struct CardData*) AudioCtrl->ahiac_DriverData;
465 if( (flags & AHISF_PLAY) && card->is_playing == TRUE)
467 card->is_playing= FALSE;
469 //DebugPrintF("STOPPING\n");
470 ClearMask8(card, MT_DMA_CONTROL, MT_PLAY_START);
471 WriteMask8(card, MT_INTR_MASK_STATUS, MT_PLAY_MASK);
473 if (card->playback_buffer) {
474 pci_free_consistent(card->playback_buffer_nonaligned, AHIsubBase);
477 card->current_bytesize = 0;
478 card->current_frames = 0;
479 card->current_buffer = NULL;
481 if ( card->mix_buffer)
482 FreeVec( card->mix_buffer );
483 card->mix_buffer = NULL;
484 card->playback_interrupt_enabled = FALSE;
485 card->current_bytesize = 0;
488 if( (flags & AHISF_RECORD) && card->is_recording == TRUE)
490 card->is_recording = FALSE;
492 //DebugPrintF("STOPPING REC\n");
493 ClearMask8(card, MT_DMA_CONTROL, MT_REC_START);
494 WriteMask8(card, MT_INTR_MASK_STATUS, MT_REC_MASK);
496 if( card->record_buffer != NULL )
498 pci_free_consistent( card->record_buffer_nonaligned, AHIsubBase);
499 pci_free_consistent( card->record_buffer_nonaligned_32bit, AHIsubBase);
502 card->record_buffer = NULL;
503 card->current_record_bytesize_32bit = 0;
504 card->record_buffer_32bit = NULL;
505 card->record_interrupt_enabled = FALSE;
507 card->record_interrupt_enabled = FALSE;
512 /******************************************************************************
513 ** AHIsub_GetAttr *************************************************************
514 ******************************************************************************/
516 LONG
517 _AHIsub_GetAttr( ULONG attribute,
518 LONG argument,
519 LONG def,
520 struct TagItem* taglist,
521 struct AHIAudioCtrlDrv* AudioCtrl,
522 struct DriverBase* AHIsubBase )
524 struct CardBase* CardBase = (struct CardBase*) AHIsubBase;
525 struct CardData* card = CardBase->driverdatas[0];
526 int i;
528 switch( attribute )
530 case AHIDB_Bits:
531 return 16;
533 case AHIDB_Frequencies:
534 return FREQUENCIES;
536 case AHIDB_Frequency: // Index->Frequency
537 return (LONG) Frequencies[ argument ];
539 case AHIDB_Index: // Frequency->Index
540 if( argument <= (LONG) Frequencies[ 0 ] )
542 return 0;
545 if( argument >= (LONG) Frequencies[ FREQUENCIES - 1 ] )
547 return FREQUENCIES-1;
550 for( i = 1; i < FREQUENCIES; i++ )
552 if( (LONG) Frequencies[ i ] > argument )
554 if( ( argument - (LONG) Frequencies[ i - 1 ] ) < ( (LONG) Frequencies[ i ] - argument ) )
556 return i-1;
558 else
560 return i;
565 return 0; // Will not happen
567 case AHIDB_Author:
568 return (LONG) "Davy Wentzler";
570 case AHIDB_Copyright:
571 return (LONG) "(C) Davy Wentzler";
573 case AHIDB_Version:
574 return (LONG) LibIDString;
576 case AHIDB_Annotation:
577 return (LONG)
578 "VIA Envy24 driver";
580 case AHIDB_Record:
581 return TRUE;
583 case AHIDB_FullDuplex:
584 return TRUE;
586 case AHIDB_Realtime:
587 return TRUE;
589 case AHIDB_MaxRecordSamples:
590 return RECORD_BUFFER_SAMPLES;
592 /* formula's:
593 #include <math.h>
595 unsigned long res = (unsigned long) (0x10000 * pow (10.0, dB / 20.0));
596 double dB = 20.0 * log10(0xVALUE / 65536.0);
598 printf("dB = %f, res = %lx\n", dB, res);*/
600 case AHIDB_MinMonitorVolume:
601 return 0x00000;
603 case AHIDB_MaxMonitorVolume:
604 return 0x00000;
606 case AHIDB_MinInputGain:
607 return 0x10000; // 0.0 dB gain
609 case AHIDB_MaxInputGain:
610 if (card->SubType == MAUDIO_1010LT || card->SubType == MAUDIO_DELTA44 || card->SubType == MAUDIO_DELTA66)
611 return 0x7F17A;
612 else
613 return 0x10000; // 0 dB gain
615 case AHIDB_MinOutputVolume:
616 return 0x00010; // -72 dB / mute
618 case AHIDB_MaxOutputVolume:
619 return 0x10000; // 0 dB
621 case AHIDB_Inputs:
622 if (card->SubType == PHASE88 || card->SubType == MAUDIO_1010LT)
623 return INPUTS;
624 else if ( card->SubType == MAUDIO_2496)
625 return INPUTS_2496;
626 else if (card->SubType == MAUDIO_DELTA44)
627 return INPUTS_DELTA44;
628 else if (card->SubType == MAUDIO_DELTA66)
629 return INPUTS_DELTA66;
631 case AHIDB_Input:
632 if (card->SubType == PHASE88 || card->SubType == MAUDIO_1010LT)
634 if (argument < 0 || argument > (INPUTS - 1))
635 argument = 0;
636 return (LONG) Inputs[ argument ];
638 else if ( card->SubType == MAUDIO_2496)
640 if (argument < 0 || argument > (INPUTS_2496 - 1))
641 argument = 0;
642 return (LONG) Inputs_2496[ argument ];
644 else if (card->SubType == MAUDIO_DELTA44)
646 if (argument < 0 || argument > (INPUTS_DELTA44 - 1))
647 argument = 0;
648 return (LONG) Inputs_Delta44[ argument ];
650 else if (card->SubType == MAUDIO_DELTA66)
652 if (argument < 0 || argument > (INPUTS_DELTA66 - 1))
653 argument = 0;
654 return (LONG) Inputs_Delta66[ argument ];
658 case AHIDB_Outputs:
659 if (card->SubType == PHASE88 || card->SubType == MAUDIO_1010LT)
660 return OUTPUTS;
661 else if ( card->SubType == MAUDIO_2496)
662 return OUTPUTS_2496;
663 else if (card->SubType == MAUDIO_DELTA44)
664 return OUTPUTS_DELTA44;
665 else if (card->SubType == MAUDIO_DELTA66)
666 return OUTPUTS_DELTA66;
668 case AHIDB_Output:
669 if (card->SubType == PHASE88 || card->SubType == MAUDIO_1010LT)
670 return (LONG) Outputs[ argument ];
671 else if ( card->SubType == MAUDIO_2496)
672 return (LONG) Outputs_2496[ argument ];
673 else if (card->SubType == MAUDIO_DELTA44)
674 return (LONG) Outputs_Delta44[ argument ];
675 else if (card->SubType == MAUDIO_DELTA66)
676 return (LONG) Outputs_Delta66[ argument ];
678 default:
679 return def;
684 /******************************************************************************
685 ** AHIsub_HardwareControl *****************************************************
686 ******************************************************************************/
688 ULONG
689 _AHIsub_HardwareControl( ULONG attribute,
690 LONG argument,
691 struct AHIAudioCtrlDrv* AudioCtrl,
692 struct DriverBase* AHIsubBase )
694 #if 0
695 struct CardData* card = (struct CardData*) AudioCtrl->ahiac_DriverData;
697 switch( attribute )
699 case AHIC_MonitorVolume:
700 card->monitor_volume = argument;
701 //DebugPrintF("card->monitor_volume = %lu, %lx\n", card->monitor_volume, card->monitor_volume);
702 if( card->is_recording )
704 //UpdateMonitorMixer( card );
706 return TRUE;
708 case AHIC_MonitorVolume_Query:
709 return card->monitor_volume;
711 case AHIC_InputGain:
713 double dB;
714 unsigned char val;
716 card->input_gain = argument;
718 dB = 20.0 * log10((Fixed) argument / 65536.0);
719 val = 128 + (int) (dB * 2);
721 if (card->SubType == MAUDIO_DELTA44 || card->SubType == MAUDIO_DELTA66)
723 akm4xxx_write(card, &card->codec[0], 0, 0x04, val);
724 akm4xxx_write(card, &card->codec[0], 0, 0x05, val);
726 else if (card->SubType == MAUDIO_1010LT)
728 int chip;
730 for (chip = 0; chip < 4; chip++)
732 akm4xxx_write(card, &card->codec[chip], chip, 0x04, val);
733 akm4xxx_write(card, &card->codec[chip], chip, 0x05, val);
737 return TRUE;
740 case AHIC_InputGain_Query:
741 return card->input_gain;
743 case AHIC_OutputVolume:
745 double dB = 20.0 * log10((Fixed) argument / 65536.0);
746 unsigned int val = 127 - (unsigned int) (dB * 127.0 / -72.0);
748 card->output_volume = argument;
750 //DebugPrintF("val = %x\n", val);
752 if (card->SubType == MAUDIO_DELTA44 || card->SubType == MAUDIO_DELTA66)
754 akm4xxx_write(card, &card->codec[0], 0, 0x06, val);
755 akm4xxx_write(card, &card->codec[0], 0, 0x07, val);
757 else if (card->SubType == MAUDIO_2496)
759 akm4xxx_write(card, &card->codec[0], 0, 0x06, val);
760 akm4xxx_write(card, &card->codec[0], 0, 0x07, val);
762 else if (card->SubType == MAUDIO_1010LT)
764 int chip;
766 for (chip = 0; chip < 4; chip++)
768 akm4xxx_write(card, &card->codec[chip], chip, 0x06, val);
769 akm4xxx_write(card, &card->codec[chip], chip, 0x07, val);
773 return TRUE;
776 case AHIC_OutputVolume_Query:
777 return card->output_volume;
779 case AHIC_Input:
780 card->input = argument;
782 if( card->is_recording )
784 //UpdateMonitorMixer( card );
787 return TRUE;
789 case AHIC_Input_Query:
790 return card->input;
792 case AHIC_Output:
793 card->output = argument;
795 if( card->output == 0 )
798 else
801 return TRUE;
803 case AHIC_Output_Query:
804 return card->output;
806 default:
807 return FALSE;
809 #else
810 return FALSE;
811 #endif