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.
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>
30 #include "library_card.h"
33 #include "DriverData.h"
35 extern struct UtilityIFace
* IUtility
;
36 extern struct AHIsubIFace
* IAHIsub
;
37 extern struct MMUIFace
* IMMU
;
40 /******************************************************************************
41 ** Globals ********************************************************************
42 ******************************************************************************/
46 static const ULONG Frequencies
[ FREQUENCIES
] =
49 8000, // ยต- and A-Law
59 static const ULONG FrequencyBits
[ FREQUENCIES
] =
76 static const STRPTR Inputs
[ INPUTS
] =
86 /* Not static since it's used in misc.c too */
87 const UWORD InputBits
[ INPUTS
] =
94 AC97_RECMUX_STEREO_MIX
,
103 static const STRPTR Outputs
[ OUTPUTS
] =
111 /******************************************************************************
112 ** AHIsub_AllocAudio **********************************************************
113 ******************************************************************************/
116 _AHIsub_AllocAudio( struct TagItem
* taglist
,
117 struct AHIAudioCtrlDrv
* AudioCtrl
,
118 struct DriverBase
* AHIsubBase
)
120 struct CardBase
* CardBase
= (struct CardBase
*) AHIsubBase
;
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
);
137 struct CardData
* card
;
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
);
148 card
->audioctrl
= AudioCtrl
;
150 IExec
->ReleaseSemaphore( &CardBase
->semaphore
);
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
) )
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
;
197 /******************************************************************************
198 ** AHIsub_FreeAudio ***********************************************************
199 ******************************************************************************/
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
;
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 ******************************************************************************/
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
239 /******************************************************************************
240 ** AHIsub_Enable **************************************************************
241 ******************************************************************************/
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
255 /******************************************************************************
256 ** AHIsub_Start ***************************************************************
257 ******************************************************************************/
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;
270 unsigned long phys_addr
;
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
] )
285 card
->mixerstate
= cmimix_rd(dev
, card
, CMPCI_SB16_MIXER_OUTMIX
);
287 if( flags
& AHISF_PLAY
)
289 ULONG dma_sample_frame_size
;
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
);
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
;
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." );
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
;
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
);
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
)
367 ULONG ChannelsFlag
= CMPCI_REG_FORMAT_16BIT
;
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
);
381 SaveMixerState( card
);
382 UpdateMonitorMixer( card
);
389 cmimix_wr(dev
, card
, CMPCI_SB16_MIXER_OUTMIX
, card
->mixerstate
| CMPCI_SB16_SW_LINE
);
393 cmimix_wr(dev
, card
, CMPCI_SB16_MIXER_OUTMIX
, card
->mixerstate
| CMPCI_SB16_SW_MIC
);
397 cmimix_wr(dev
, card
, CMPCI_SB16_MIXER_OUTMIX
, card
->mixerstate
| CMPCI_SB16_SW_CD
);
401 byte
= dev
->InByte(card
->iobase
+ CMPCI_REG_MIXER25
);
403 dev
->OutByte(card
->iobase
+ CMPCI_REG_MIXER25
, byte
); // unmute Aux
410 card
->record_interrupt_enabled
= TRUE
;
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
);
424 card
->record_buffer_phys
= card
->record_buffer
;
427 dev
->OutLong(card
->iobase
+ CMPCI_REG_DMA1_BASE
, card
->record_buffer_phys
);
429 dev
->OutWord(card
->iobase
+ CMPCI_REG_DMA1_LENGTH
, (card
->current_record_bytesize
/ 4) * 2 - 1);
431 dev
->OutWord(card
->iobase
+ CMPCI_REG_DMA1_INTLEN
, (card
->current_record_bytesize
/ 4) - 1);
433 card
->current_record_buffer
= card
->record_buffer
+ card
->current_record_bytesize
;
434 card
->is_recording
= TRUE
;
437 if( flags
& AHISF_PLAY
)
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
);
454 /******************************************************************************
455 ** AHIsub_Update **************************************************************
456 ******************************************************************************/
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
;
466 card
->current_frames
= AudioCtrl
->ahiac_BuffSamples
;
468 if( AudioCtrl
->ahiac_Flags
& AHIACF_STEREO
)
470 card
->current_bytesize
= card
->current_frames
* 4;
474 card
->current_bytesize
= card
->current_frames
* 2;
480 /******************************************************************************
481 ** AHIsub_Stop ****************************************************************
482 ******************************************************************************/
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
;
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
);
529 cmimix_wr(dev
, card
, CMPCI_SB16_MIXER_OUTMIX
, card
->mixerstate
);
533 cmimix_wr(dev
, card
, CMPCI_SB16_MIXER_OUTMIX
, card
->mixerstate
);
537 cmimix_wr(dev
, card
, CMPCI_SB16_MIXER_OUTMIX
, card
->mixerstate
);
541 byte
= dev
->InByte(card
->iobase
+ CMPCI_REG_MIXER25
);
542 dev
->OutByte(card
->iobase
+ CMPCI_REG_MIXER25
, byte
& ~0x30); // mute Aux
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 ******************************************************************************/
570 _AHIsub_GetAttr( ULONG attribute
,
573 struct TagItem
* taglist
,
574 struct AHIAudioCtrlDrv
* AudioCtrl
,
575 struct DriverBase
* AHIsubBase
)
577 struct CardBase
* CardBase
= (struct CardBase
*) AHIsubBase
;
586 case AHIDB_Frequencies
:
589 case AHIDB_Frequency
: // Index->Frequency
590 return (LONG
) Frequencies
[ argument
];
592 case AHIDB_Index
: // Frequency->Index
593 if( argument
<= (LONG
) Frequencies
[ 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
) )
618 return 0; // Will not happen
621 return (LONG
) "Davy Wentzler";
623 case AHIDB_Copyright
:
624 return (LONG
) "(C) Davy Wentzler";
627 return (LONG
) LibIDString
;
629 case AHIDB_Annotation
:
631 "OS4 PPC native driver";
636 case AHIDB_FullDuplex
:
642 case AHIDB_MaxRecordSamples
:
643 return RECORD_BUFFER_SAMPLES
;
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
:
656 case AHIDB_MaxMonitorVolume
:
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
675 return (LONG
) Inputs
[ argument
];
681 return (LONG
) Outputs
[ argument
];
689 /******************************************************************************
690 ** AHIsub_HardwareControl *****************************************************
691 ******************************************************************************/
694 _AHIsub_HardwareControl( ULONG attribute
,
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
;
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
);
715 case AHIC_MonitorVolume_Query
:
716 return card
->monitor_volume
;
719 card
->input_gain
= Linear2RecordGain( (Fixed
) argument
, &card
->input_gain_bits
);
720 //codec_write(card, AC97_RECORD_GAIN, card->input_gain_bits );
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
);
734 case AHIC_OutputVolume_Query
:
735 return card
->output_volume
;
738 card
->input
= argument
;
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
);
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
);
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
);
758 byte
= dev
->InByte(card
->iobase
+ CMPCI_REG_MIXER25
);
759 dev
->OutByte(card
->iobase
+ CMPCI_REG_MIXER25
, byte
| 0xC0); // rec source Aux
770 if( card
->is_recording
)
772 UpdateMonitorMixer( card
);
777 case AHIC_Input_Query
:
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
);
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
);
795 case AHIC_Output_Query
: