2 Copyright © 2004-2014, Davy Wentzler. All rights reserved.
9 #include <proto/expansion.h>
11 extern struct UtilityIFace
* IUtility
;
12 extern struct AHIsubIFace
* IAHIsub
;
13 extern struct MMUIFace
* IMMU
;
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>
30 #include "pci_wrapper.h"
31 #include "DriverData.h"
34 /******************************************************************************
35 ** Globals ********************************************************************
36 ******************************************************************************/
38 #define FREQUENCIES 13
40 static const ULONG Frequencies
[ FREQUENCIES
] =
57 static const ULONG FrequencyBits
[ FREQUENCIES
] =
80 static const STRPTR Inputs
[ INPUTS
] =
92 static const STRPTR Inputs_2496
[ INPUTS
] =
100 static const STRPTR Outputs
[ OUTPUTS
] =
109 #define OUTPUTS_2496 1
111 static const STRPTR Outputs_2496
[ OUTPUTS
] =
117 #define INPUTS_DELTA44 2
119 static const STRPTR Inputs_Delta44
[ INPUTS_DELTA44
] =
125 #define OUTPUTS_DELTA44 1
127 static const STRPTR Outputs_Delta44
[ OUTPUTS_DELTA44
] =
134 #define INPUTS_DELTA66 2
136 static const STRPTR Inputs_Delta66
[ INPUTS_DELTA66
] =
143 #define OUTPUTS_DELTA66 1
145 static const STRPTR Outputs_Delta66
[ OUTPUTS_DELTA66
] =
151 /******************************************************************************
152 ** AHIsub_AllocAudio **********************************************************
153 ******************************************************************************/
156 _AHIsub_AllocAudio( struct TagItem
* taglist
,
157 struct AHIAudioCtrlDrv
* AudioCtrl
,
158 struct DriverBase
* AHIsubBase
)
160 struct CardBase
* CardBase
= (struct CardBase
*) AHIsubBase
;
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
);
177 struct CardData
* card
;
180 card
= CardBase
->driverdatas
[ card_num
];
181 AudioCtrl
->ahiac_DriverData
= card
;
183 ObtainSemaphore( &CardBase
->semaphore
);
184 in_use
= ( card
->audioctrl
!= NULL
);
187 card
->audioctrl
= AudioCtrl
;
189 ReleaseSemaphore( &CardBase
->semaphore
);
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
;
217 /******************************************************************************
218 ** AHIsub_FreeAudio ***********************************************************
219 ******************************************************************************/
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
;
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 ******************************************************************************/
248 _AHIsub_Disable( struct AHIAudioCtrlDrv
* AudioCtrl
,
249 struct DriverBase
* AHIsubBase
)
251 // V6 drivers do not have to preserve all registers
257 /******************************************************************************
258 ** AHIsub_Enable **************************************************************
259 ******************************************************************************/
262 _AHIsub_Enable( struct AHIAudioCtrlDrv
* AudioCtrl
,
263 struct DriverBase
* AHIsubBase
)
265 // V6 drivers do not have to preserve all registers
271 /******************************************************************************
272 ** AHIsub_Update **************************************************************
273 ******************************************************************************/
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;
290 card
->current_bytesize
= card
->current_frames
* 2;
295 /******************************************************************************
296 ** AHIsub_Start ***************************************************************
297 ******************************************************************************/
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;
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
] )
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
);
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." );
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
;
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
);
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
;
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
);
454 /******************************************************************************
455 ** AHIsub_Stop ****************************************************************
456 ******************************************************************************/
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 ******************************************************************************/
517 _AHIsub_GetAttr( ULONG attribute
,
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];
533 case AHIDB_Frequencies
:
536 case AHIDB_Frequency
: // Index->Frequency
537 return (LONG
) Frequencies
[ argument
];
539 case AHIDB_Index
: // Frequency->Index
540 if( argument
<= (LONG
) Frequencies
[ 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
) )
565 return 0; // Will not happen
568 return (LONG
) "Davy Wentzler";
570 case AHIDB_Copyright
:
571 return (LONG
) "(C) Davy Wentzler";
574 return (LONG
) LibIDString
;
576 case AHIDB_Annotation
:
583 case AHIDB_FullDuplex
:
589 case AHIDB_MaxRecordSamples
:
590 return RECORD_BUFFER_SAMPLES
;
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
:
603 case AHIDB_MaxMonitorVolume
:
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
)
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
622 if (card
->SubType
== PHASE88
|| card
->SubType
== MAUDIO_1010LT
)
624 else if ( card
->SubType
== MAUDIO_2496
)
626 else if (card
->SubType
== MAUDIO_DELTA44
)
627 return INPUTS_DELTA44
;
628 else if (card
->SubType
== MAUDIO_DELTA66
)
629 return INPUTS_DELTA66
;
632 if (card
->SubType
== PHASE88
|| card
->SubType
== MAUDIO_1010LT
)
634 if (argument
< 0 || argument
> (INPUTS
- 1))
636 return (LONG
) Inputs
[ argument
];
638 else if ( card
->SubType
== MAUDIO_2496
)
640 if (argument
< 0 || argument
> (INPUTS_2496
- 1))
642 return (LONG
) Inputs_2496
[ argument
];
644 else if (card
->SubType
== MAUDIO_DELTA44
)
646 if (argument
< 0 || argument
> (INPUTS_DELTA44
- 1))
648 return (LONG
) Inputs_Delta44
[ argument
];
650 else if (card
->SubType
== MAUDIO_DELTA66
)
652 if (argument
< 0 || argument
> (INPUTS_DELTA66
- 1))
654 return (LONG
) Inputs_Delta66
[ argument
];
659 if (card
->SubType
== PHASE88
|| card
->SubType
== MAUDIO_1010LT
)
661 else if ( card
->SubType
== MAUDIO_2496
)
663 else if (card
->SubType
== MAUDIO_DELTA44
)
664 return OUTPUTS_DELTA44
;
665 else if (card
->SubType
== MAUDIO_DELTA66
)
666 return OUTPUTS_DELTA66
;
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
];
684 /******************************************************************************
685 ** AHIsub_HardwareControl *****************************************************
686 ******************************************************************************/
689 _AHIsub_HardwareControl( ULONG attribute
,
691 struct AHIAudioCtrlDrv
* AudioCtrl
,
692 struct DriverBase
* AHIsubBase
)
695 struct CardData
* card
= (struct CardData
*) AudioCtrl
->ahiac_DriverData
;
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 );
708 case AHIC_MonitorVolume_Query
:
709 return card
->monitor_volume
;
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
)
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
);
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
)
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
);
776 case AHIC_OutputVolume_Query
:
777 return card
->output_volume
;
780 card
->input
= argument
;
782 if( card
->is_recording
)
784 //UpdateMonitorMixer( card );
789 case AHIC_Input_Query
:
793 card
->output
= argument
;
795 if( card
->output
== 0 )
803 case AHIC_Output_Query
: