3 The contents of this file are subject to the AROS Public License Version 1.1 (the "License"); 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
6 Software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTY OF
7 ANY KIND, either express or implied. See the License for the specific language governing rights and
8 limitations under the License.
10 The Original Code is (C) Copyright 2004-2011 Ross Vumbaca.
12 The Initial Developer of the Original Code is Ross Vumbaca.
18 #if !defined(__AROS__)
20 #include <proto/expansion.h>
21 extern struct UtilityIFace
* IUtility
;
22 extern struct AHIsubIFace
* IAHIsub
;
23 extern struct MMUIFace
* IMMU
;
26 #include <devices/ahi.h>
27 #include <exec/memory.h>
28 #include <libraries/ahi_sub.h>
30 #include <proto/ahi_sub.h>
31 #include <proto/exec.h>
32 #include <proto/dos.h>
33 #include <proto/utility.h>
36 #include <aros/debug.h>
43 #include "pci_wrapper.h"
45 extern void rate_set_dac2(struct SB128_DATA
*card
, unsigned long rate
);
46 extern void rate_set_adc(struct SB128_DATA
*card
, unsigned long rate
);
48 /******************************************************************************
49 ** Globals ********************************************************************
50 ******************************************************************************/
52 #define FREQUENCIES 11
54 static const ULONG Frequencies
[ FREQUENCIES
] =
57 8000, /* ยต- and A-Law */
71 static const STRPTR Inputs
[ INPUTS
] =
81 /* Not static since it's used in misc.c too */
82 const UWORD InputBits
[ INPUTS
] =
88 AC97_RECMUX_STEREO_MIX
,
95 static const STRPTR Outputs
[ OUTPUTS
] =
101 /******************************************************************************
102 ** AHIsub_AllocAudio **********************************************************
103 ******************************************************************************/
106 _AHIsub_AllocAudio( struct TagItem
* taglist
,
107 struct AHIAudioCtrlDrv
* AudioCtrl
,
108 struct DriverBase
* AHIsubBase
)
110 struct SB128Base
* SB128Base
= (struct SB128Base
*) AHIsubBase
;
116 card_num
= ( GetTagData( AHIDB_AudioID
, 0, taglist
) & 0x0000f000 ) >> 12;
118 if( card_num
>= SB128Base
->cards_found
||
119 SB128Base
->driverdatas
[ card_num
] == NULL
)
121 Req( "No Card Data for card %ld.", card_num
);
126 struct SB128_DATA
* card
;
129 card
= SB128Base
->driverdatas
[ card_num
];
130 AudioCtrl
->ahiac_DriverData
= card
;
132 ObtainSemaphore( &SB128Base
->semaphore
);
133 in_use
= ( card
->audioctrl
!= NULL
);
136 card
->audioctrl
= AudioCtrl
;
138 ReleaseSemaphore( &SB128Base
->semaphore
);
145 card
->playback_interrupt_enabled
= FALSE
;
146 card
->record_interrupt_enabled
= FALSE
;
147 /* Clears playback/record interrupts */
148 pci_outl((pci_inl(SB128_SCON
, card
)) & SB128_IRQ_MASK
, SB128_SCON
, card
);
151 ret
= AHISF_KNOWHIFI
| AHISF_KNOWSTEREO
| AHISF_MIXING
| AHISF_TIMING
;
154 for( i
= 0; i
< FREQUENCIES
; ++i
)
156 if( AudioCtrl
->ahiac_MixFreq
== Frequencies
[ i
] )
158 ret
|= AHISF_CANRECORD
;
168 /******************************************************************************
169 ** AHIsub_FreeAudio ***********************************************************
170 ******************************************************************************/
173 _AHIsub_FreeAudio( struct AHIAudioCtrlDrv
* AudioCtrl
,
174 struct DriverBase
* AHIsubBase
)
176 struct SB128Base
* SB128Base
= (struct SB128Base
*) AHIsubBase
;
177 struct SB128_DATA
* card
= (struct SB128_DATA
*) AudioCtrl
->ahiac_DriverData
;
181 ObtainSemaphore( &SB128Base
->semaphore
);
182 if( card
->audioctrl
== AudioCtrl
)
184 /* Release it if we own it. */
185 card
->audioctrl
= NULL
;
187 ReleaseSemaphore( &SB128Base
->semaphore
);
189 AudioCtrl
->ahiac_DriverData
= NULL
;
194 /******************************************************************************
195 ** AHIsub_Disable *************************************************************
196 ******************************************************************************/
199 _AHIsub_Disable( struct AHIAudioCtrlDrv
* AudioCtrl
,
200 struct DriverBase
* AHIsubBase
)
202 /* V6 drivers do not have to preserve all registers */
208 /******************************************************************************
209 ** AHIsub_Enable **************************************************************
210 ******************************************************************************/
213 _AHIsub_Enable( struct AHIAudioCtrlDrv
* AudioCtrl
,
214 struct DriverBase
* AHIsubBase
)
216 /* V6 drivers do not have to preserve all registers */
222 /******************************************************************************
223 ** AHIsub_Start ***************************************************************
224 ******************************************************************************/
227 _AHIsub_Start( ULONG flags
,
228 struct AHIAudioCtrlDrv
* AudioCtrl
,
229 struct DriverBase
* AHIsubBase
)
231 struct SB128_DATA
* card
= (struct SB128_DATA
*) AudioCtrl
->ahiac_DriverData
;
232 unsigned long PlayCtrlFlags
= 0, RecCtrlFlags
= 0;
233 ULONG dma_buffer_size
= 0;
237 for( i
= 0; i
< FREQUENCIES
; ++i
)
239 if( AudioCtrl
->ahiac_MixFreq
== Frequencies
[ i
] )
246 if( flags
& AHISF_PLAY
)
249 ULONG dma_sample_frame_size
;
250 unsigned short ChannelsFlag
;
254 /* Update cached/syncronized variables */
256 AHIsub_Update( AHISF_PLAY
, AudioCtrl
);
258 /* Allocate a new mixing buffer. Note: The buffer must be cleared, since
259 it might not be filled by the mixer software interrupt because of
260 pretimer/posttimer! */
262 card
->mix_buffer
= AllocVec( AudioCtrl
->ahiac_BuffSize
,
263 MEMF_PUBLIC
| MEMF_CLEAR
);
265 if( card
->mix_buffer
== NULL
)
267 Req( "Unable to allocate %ld bytes for mixing buffer.",
268 AudioCtrl
->ahiac_BuffSize
);
272 /* Allocate a buffer large enough for 16-bit double-buffered
273 playback (mono or stereo) */
275 if( AudioCtrl
->ahiac_Flags
& AHIACF_STEREO
)
277 dma_sample_frame_size
= 4;
278 dma_buffer_size
= AudioCtrl
->ahiac_MaxBuffSamples
* dma_sample_frame_size
;
279 ChannelsFlag
= SB128_STEREO
;
283 dma_sample_frame_size
= 2;
284 dma_buffer_size
= AudioCtrl
->ahiac_MaxBuffSamples
* dma_sample_frame_size
;
287 card
->playback_buffer
= pci_alloc_consistent(dma_buffer_size
* 2, &card
->playback_buffer_nonaligned
, 128);
289 if (!card
->playback_buffer
)
291 Req( "Unable to allocate playback buffer." );
295 /* Enable Playback interrupt */
296 pci_outl((pci_inl(SB128_SCON
, card
) | SB128_DAC2_INTEN
), SB128_SCON
, card
);
298 card
->current_bytesize
= dma_buffer_size
;
299 card
->current_frames
= AudioCtrl
->ahiac_MaxBuffSamples
;
300 card
->current_buffer
= card
->playback_buffer
+ card
->current_bytesize
;
301 card
->playback_interrupt_enabled
= TRUE
;
305 /* Select the DAC2 Memory Page */
306 pci_outl(SB128_PAGE_DAC
, SB128_MEMPAGE
, card
);
308 /* Buffer address and length (in longwords) is set */
309 stack
= SuperState();
310 // card->playback_buffer_phys = IMMU->GetPhysicalAddress(card->playback_buffer);
311 card
->playback_buffer_phys
= card
->playback_buffer
;
314 pci_outl((unsigned long)(card
->playback_buffer_phys
), SB128_DAC2_FRAME
, card
);
315 pci_outl((((dma_buffer_size
* 2) >> 2) - 1) & 0xFFFF, SB128_DAC2_COUNT
, card
);
317 /* Playback format is always 16 Bit, Stereo, but checks exist in case of a Mono mode (not possible). */
318 PlayCtrlFlags
= (SB128_16BIT
| ChannelsFlag
) << 2;
321 if (card
->currentPlayFreq
!= freqbit
)
323 rate_set_dac2(card
, Frequencies
[freqbit
]);
324 card
->currentPlayFreq
= freqbit
;
326 card
->is_playing
= TRUE
;
329 if( flags
& AHISF_RECORD
)
331 card
->current_record_bytesize
= RECORD_BUFFER_SAMPLES
* 4;
333 /* Allocate a new recording buffer (page aligned!) */
334 card
->record_buffer
= pci_alloc_consistent(card
->current_record_bytesize
* 2, &card
->record_buffer_nonaligned
, 128);
336 if( card
->record_buffer
== NULL
)
338 Req( "Unable to allocate %ld bytes for the recording buffer.", card
->current_record_bytesize
);
342 SaveMixerState( card
);
343 UpdateMonitorMixer( card
);
345 /* Enable record interrupt */
346 pci_outl((pci_inl(SB128_SCON
, card
) | SB128_ADC_INTEN
), SB128_SCON
, card
);
348 card
->record_interrupt_enabled
= TRUE
;
352 /* Select the ADC Memory Page */
353 pci_outl(SB128_PAGE_ADC
, SB128_MEMPAGE
, card
);
355 /* Buffer address and length (in longwords) is set */
356 stack
= SuperState();
357 // card->record_buffer_phys = IMMU->GetPhysicalAddress(card->record_buffer);
358 card
->record_buffer_phys
= card
->record_buffer
;
361 pci_outl((unsigned long) card
->record_buffer_phys
, SB128_ADC_FRAME
, card
);
362 pci_outl((((card
->current_record_bytesize
* 2) >> 2) - 1) & 0xFFFF, SB128_ADC_COUNT
, card
);
364 card
->is_recording
= TRUE
;
365 card
->current_record_buffer
= card
->record_buffer
+ card
->current_record_bytesize
;
367 /* Record format is always 16 Bit, Stereo */
368 RecCtrlFlags
= (SB128_16BIT
| SB128_STEREO
) << 4;
371 if (card
->currentRecFreq
!= freqbit
)
373 rate_set_adc(card
, Frequencies
[freqbit
]);
374 card
->currentRecFreq
= freqbit
;
378 if( flags
& AHISF_PLAY
)
380 /* Set Sample Count per Interrupt */
381 if (PlayCtrlFlags
& 0x04)
383 pci_outl(((dma_buffer_size
>> 2) - 1) & 0xFFFF, SB128_DAC2_SCOUNT
, card
);
387 pci_outl(((dma_buffer_size
>> 1) - 1) & 0xFFFF, SB128_DAC2_SCOUNT
, card
);
389 /* Set format, ENDINC set to 2 */
390 pci_outl((pci_inl(SB128_SCON
, card
) | PlayCtrlFlags
| 2 << 19), SB128_SCON
, card
);
391 /* Start playback! */
392 pci_outl((pci_inl(SB128_CONTROL
, card
) | CTRL_DAC2_EN
), SB128_CONTROL
, card
);
395 if( flags
& AHISF_RECORD
)
397 /* Set Sample Count per Interrupt */
398 pci_outl(((card
->current_record_bytesize
>> 2) - 1) & 0xFFFF, SB128_ADC_SCOUNT
, card
);
400 pci_outl((pci_inl(SB128_SCON
, card
) | RecCtrlFlags
), SB128_SCON
, card
);
401 /* Start recording! */
402 pci_outl((pci_inl(SB128_CONTROL
, card
) | CTRL_ADC_EN
), SB128_CONTROL
, card
);
409 /******************************************************************************
410 ** AHIsub_Update **************************************************************
411 ******************************************************************************/
414 _AHIsub_Update( ULONG flags
,
415 struct AHIAudioCtrlDrv
* AudioCtrl
,
416 struct DriverBase
* AHIsubBase
)
418 struct SB128_DATA
* card
= (struct SB128_DATA
*) AudioCtrl
->ahiac_DriverData
;
420 card
->current_frames
= AudioCtrl
->ahiac_BuffSamples
;
422 if( AudioCtrl
->ahiac_Flags
& AHIACF_STEREO
)
424 card
->current_bytesize
= card
->current_frames
* 4;
428 card
->current_bytesize
= card
->current_frames
* 2;
433 /******************************************************************************
434 ** AHIsub_Stop ****************************************************************
435 ******************************************************************************/
438 _AHIsub_Stop( ULONG flags
,
439 struct AHIAudioCtrlDrv
* AudioCtrl
,
440 struct DriverBase
* AHIsubBase
)
442 struct SB128_DATA
* card
= (struct SB128_DATA
*) AudioCtrl
->ahiac_DriverData
;
444 if( flags
& AHISF_PLAY
)
446 unsigned long play_ctl
;
447 card
->is_playing
= FALSE
;
449 play_ctl
= pci_inl(SB128_CONTROL
, card
);
450 play_ctl
&= ~(CTRL_DAC2_EN
);
452 pci_outl(play_ctl
, SB128_CONTROL
, card
);
454 /* Clear and mask interrupts */
455 pci_outl((pci_inl(SB128_SCON
, card
)) & SB128_IRQ_MASK
, SB128_SCON
, card
);
457 if (card
->current_bytesize
> 0)
458 pci_free_consistent(card
->playback_buffer_nonaligned
);
460 card
->current_bytesize
= 0;
461 card
->current_frames
= 0;
462 card
->current_buffer
= NULL
;
464 if ( card
->mix_buffer
)
465 FreeVec( card
->mix_buffer
);
466 card
->mix_buffer
= NULL
;
467 card
->playback_interrupt_enabled
= FALSE
;
468 card
->current_bytesize
= 0;
471 if( flags
& AHISF_RECORD
)
473 unsigned long rec_ctl
;
475 rec_ctl
= pci_inl(SB128_CONTROL
, card
);
476 rec_ctl
&= ~(CTRL_ADC_EN
);
478 pci_outl(rec_ctl
, SB128_CONTROL
, card
);
480 /* Clear and mask interrupts */
481 pci_outl((pci_inl(SB128_SCON
, card
)) & SB128_IRQ_MASK
, SB128_SCON
, card
);
483 if( card
->is_recording
)
485 /* Do not restore mixer unless they have been saved */
486 RestoreMixerState( card
);
489 if( card
->record_buffer
!= NULL
)
491 pci_free_consistent( card
->record_buffer_nonaligned
);
494 card
->record_buffer
= NULL
;
495 card
->current_record_bytesize
= 0;
497 card
->is_recording
= FALSE
;
498 card
->record_interrupt_enabled
= FALSE
;
505 /******************************************************************************
506 ** AHIsub_GetAttr *************************************************************
507 ******************************************************************************/
510 _AHIsub_GetAttr( ULONG attribute
,
513 struct TagItem
* taglist
,
514 struct AHIAudioCtrlDrv
* AudioCtrl
,
515 struct DriverBase
* AHIsubBase
)
524 case AHIDB_Frequencies
:
527 case AHIDB_Frequency
: /* Index->Frequency */
528 return (LONG
) Frequencies
[ argument
];
530 case AHIDB_Index
: /* Frequency->Index */
531 if( argument
<= (LONG
) Frequencies
[ 0 ] )
536 if( argument
>= (LONG
) Frequencies
[ FREQUENCIES
- 1 ] )
538 return FREQUENCIES
-1;
541 for( i
= 1; i
< FREQUENCIES
; i
++ )
543 if( (LONG
) Frequencies
[ i
] > argument
)
545 if( ( argument
- (LONG
) Frequencies
[ i
- 1 ] ) < ( (LONG
) Frequencies
[ i
] - argument
) )
556 return 0; /* Will not happen */
559 return (LONG
) "Ross Vumbaca";
561 case AHIDB_Copyright
:
562 return (LONG
) "(C) Ross Vumbaca";
565 return (LONG
) LibIDString
;
567 case AHIDB_Annotation
:
569 "AROS SB128/ES137x Audio driver";
574 case AHIDB_FullDuplex
:
580 case AHIDB_MaxRecordSamples
:
581 return RECORD_BUFFER_SAMPLES
;
586 unsigned long res = (unsigned long) (0x10000 * pow (10.0, dB / 20.0));
587 double dB = 20.0 * log10(0xVALUE / 65536.0);
589 printf("dB = %f, res = %lx\n", dB, res);*/
591 case AHIDB_MinMonitorVolume
:
594 case AHIDB_MaxMonitorVolume
:
597 case AHIDB_MinInputGain
:
598 return 0x10000; /* 0.0 dB gain */
600 case AHIDB_MaxInputGain
:
601 return 0xD55D0; /* 22.5 dB gain */
603 case AHIDB_MinOutputVolume
:
604 return 0x004d2; /* -34.5 dB / mute */
606 case AHIDB_MaxOutputVolume
:
607 return 0x3fb27; /* 12 dB */
613 return (LONG
) Inputs
[ argument
];
619 return (LONG
) Outputs
[ argument
];
627 /******************************************************************************
628 ** AHIsub_HardwareControl *****************************************************
629 ******************************************************************************/
632 _AHIsub_HardwareControl( ULONG attribute
,
634 struct AHIAudioCtrlDrv
* AudioCtrl
,
635 struct DriverBase
* AHIsubBase
)
637 struct SB128_DATA
* card
= (struct SB128_DATA
*) AudioCtrl
->ahiac_DriverData
;
641 case AHIC_MonitorVolume
:
642 card
->monitor_volume
= Linear2MixerGain( (Fixed
) argument
, &card
->monitor_volume_bits
);
643 if( card
->is_recording
)
645 UpdateMonitorMixer( card
);
649 case AHIC_MonitorVolume_Query
:
650 return card
->monitor_volume
;
653 card
->input_gain
= Linear2RecordGain( (Fixed
) argument
, &card
->input_gain_bits
);
656 /* Not supported on ES1370 */
659 codec_write(card
, AC97_RECORD_GAIN
, card
->input_gain_bits
);
662 case AHIC_InputGain_Query
:
663 return card
->input_gain
;
665 case AHIC_OutputVolume
:
666 card
->output_volume
= Linear2MixerGain( (Fixed
) argument
, &card
->output_volume_bits
);
669 ak4531_ac97_write(card
, AC97_PCMOUT_VOL
, card
->output_volume_bits
);
672 codec_write(card
, AC97_PCMOUT_VOL
, card
->output_volume_bits
);
675 case AHIC_OutputVolume_Query
:
676 return card
->output_volume
;
679 card
->input
= argument
;
682 ak4531_ac97_write(card
, AC97_RECORD_SELECT
, InputBits
[ card
->input
] );
685 codec_write(card
, AC97_RECORD_SELECT
, InputBits
[ card
->input
] );
687 if( card
->is_recording
)
689 UpdateMonitorMixer( card
);
693 case AHIC_Input_Query
:
697 card
->output
= argument
;
699 if( card
->output
== 0 )
707 case AHIC_Output_Query
: