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.
20 #if !defined(__AROS__)
22 #include <proto/expansion.h>
23 extern struct UtilityIFace
* IUtility
;
24 extern struct AHIsubIFace
* IAHIsub
;
25 extern struct MMUIFace
* IMMU
;
28 #include <devices/ahi.h>
29 #include <exec/memory.h>
30 #include <libraries/ahi_sub.h>
32 #include <proto/ahi_sub.h>
33 #include <proto/exec.h>
34 #include <proto/dos.h>
35 #include <proto/utility.h>
39 #include <aros/debug.h>
40 #define DebugPrintF bug
47 #include "pci_wrapper.h"
48 //#include "DriverData.h"
50 extern void rate_set_dac2(struct SB128_DATA
*card
, unsigned long rate
);
51 extern void rate_set_adc(struct SB128_DATA
*card
, unsigned long rate
);
53 /******************************************************************************
54 ** Globals ********************************************************************
55 ******************************************************************************/
57 #define FREQUENCIES 11
59 static const ULONG Frequencies
[ FREQUENCIES
] =
62 8000, /* ยต- and A-Law */
76 static const STRPTR Inputs
[ INPUTS
] =
86 /* Not static since it's used in misc.c too */
87 const UWORD InputBits
[ INPUTS
] =
93 AC97_RECMUX_STEREO_MIX
,
100 static const STRPTR Outputs
[ OUTPUTS
] =
106 /******************************************************************************
107 ** AHIsub_AllocAudio **********************************************************
108 ******************************************************************************/
111 _AHIsub_AllocAudio( struct TagItem
* taglist
,
112 struct AHIAudioCtrlDrv
* AudioCtrl
,
113 struct DriverBase
* AHIsubBase
)
115 struct SB128Base
* SB128Base
= (struct SB128Base
*) AHIsubBase
;
121 card_num
= ( GetTagData( AHIDB_AudioID
, 0, taglist
) & 0x0000f000 ) >> 12;
123 if( card_num
>= SB128Base
->cards_found
||
124 SB128Base
->driverdatas
[ card_num
] == NULL
)
126 DebugPrintF("no data for card = %ld\n", card_num
);
127 Req( "No Card Data for card %ld.", card_num
);
132 struct SB128_DATA
* card
;
134 struct PCIDevice
*dev
;
136 card
= SB128Base
->driverdatas
[ card_num
];
137 AudioCtrl
->ahiac_DriverData
= card
;
139 ObtainSemaphore( &SB128Base
->semaphore
);
140 in_use
= ( card
->audioctrl
!= NULL
);
143 card
->audioctrl
= AudioCtrl
;
145 ReleaseSemaphore( &SB128Base
->semaphore
);
153 card
->playback_interrupt_enabled
= FALSE
;
154 card
->record_interrupt_enabled
= FALSE
;
155 /* Clears playback/record interrupts */
156 pci_outl((pci_inl(SB128_SCON
, card
)) & SB128_IRQ_MASK
, SB128_SCON
, card
);
158 for( i
= 1; i
< FREQUENCIES
; i
++ )
160 if( (ULONG
) Frequencies
[ i
] > AudioCtrl
->ahiac_MixFreq
)
162 if ( ( AudioCtrl
->ahiac_MixFreq
- (LONG
) Frequencies
[ i
- 1 ] ) < ( (LONG
) Frequencies
[ i
] - AudioCtrl
->ahiac_MixFreq
) )
177 ret
= AHISF_KNOWHIFI
| AHISF_KNOWSTEREO
| AHISF_MIXING
| AHISF_TIMING
;
180 for( i
= 0; i
< FREQUENCIES
; ++i
)
182 if( AudioCtrl
->ahiac_MixFreq
== Frequencies
[ i
] )
184 ret
|= AHISF_CANRECORD
;
194 /******************************************************************************
195 ** AHIsub_FreeAudio ***********************************************************
196 ******************************************************************************/
199 _AHIsub_FreeAudio( struct AHIAudioCtrlDrv
* AudioCtrl
,
200 struct DriverBase
* AHIsubBase
)
202 struct SB128Base
* SB128Base
= (struct SB128Base
*) AHIsubBase
;
203 struct SB128_DATA
* card
= (struct SB128_DATA
*) AudioCtrl
->ahiac_DriverData
;
207 ObtainSemaphore( &SB128Base
->semaphore
);
208 if( card
->audioctrl
== AudioCtrl
)
210 /* Release it if we own it. */
211 card
->audioctrl
= NULL
;
213 ReleaseSemaphore( &SB128Base
->semaphore
);
215 AudioCtrl
->ahiac_DriverData
= NULL
;
220 /******************************************************************************
221 ** AHIsub_Disable *************************************************************
222 ******************************************************************************/
225 _AHIsub_Disable( struct AHIAudioCtrlDrv
* AudioCtrl
,
226 struct DriverBase
* AHIsubBase
)
228 struct SB128Base
* SB128Base
= (struct SB128Base
*) AHIsubBase
;
230 /* V6 drivers do not have to preserve all registers */
236 /******************************************************************************
237 ** AHIsub_Enable **************************************************************
238 ******************************************************************************/
241 _AHIsub_Enable( struct AHIAudioCtrlDrv
* AudioCtrl
,
242 struct DriverBase
* AHIsubBase
)
244 struct SB128Base
* SB128Base
= (struct SB128Base
*) AHIsubBase
;
246 /* V6 drivers do not have to preserve all registers */
252 /******************************************************************************
253 ** AHIsub_Start ***************************************************************
254 ******************************************************************************/
257 _AHIsub_Start( ULONG flags
,
258 struct AHIAudioCtrlDrv
* AudioCtrl
,
259 struct DriverBase
* AHIsubBase
)
261 struct SB128Base
* SB128Base
= (struct SB128Base
*) AHIsubBase
;
262 struct SB128_DATA
* card
= (struct SB128_DATA
*) AudioCtrl
->ahiac_DriverData
;
263 struct PCIDevice
*dev
= card
->pci_dev
;
264 unsigned long PlayCtrlFlags
= 0, RecCtrlFlags
= 0;
265 ULONG dma_buffer_size
= 0;
267 unsigned long scon
= 0;
270 for( i
= 0; i
< FREQUENCIES
; ++i
)
272 if( AudioCtrl
->ahiac_MixFreq
== Frequencies
[ i
] )
279 if( flags
& AHISF_PLAY
)
282 ULONG dma_sample_frame_size
;
285 unsigned short cod
, ChannelsFlag
;
289 /* Update cached/syncronized variables */
291 AHIsub_Update( AHISF_PLAY
, AudioCtrl
);
293 /* Allocate a new mixing buffer. Note: The buffer must be cleared, since
294 it might not be filled by the mixer software interrupt because of
295 pretimer/posttimer! */
297 card
->mix_buffer
= AllocVec( AudioCtrl
->ahiac_BuffSize
,
298 MEMF_PUBLIC
| MEMF_CLEAR
);
300 if( card
->mix_buffer
== NULL
)
302 Req( "Unable to allocate %ld bytes for mixing buffer.",
303 AudioCtrl
->ahiac_BuffSize
);
307 /* Allocate a buffer large enough for 16-bit double-buffered
308 playback (mono or stereo) */
310 if( AudioCtrl
->ahiac_Flags
& AHIACF_STEREO
)
312 dma_sample_frame_size
= 4;
313 dma_buffer_size
= AudioCtrl
->ahiac_MaxBuffSamples
* dma_sample_frame_size
;
314 ChannelsFlag
= SB128_STEREO
;
318 dma_sample_frame_size
= 2;
319 dma_buffer_size
= AudioCtrl
->ahiac_MaxBuffSamples
* dma_sample_frame_size
;
322 card
->playback_buffer
= pci_alloc_consistent(dma_buffer_size
* 2, &card
->playback_buffer_nonaligned
, 128);
324 if (!card
->playback_buffer
)
326 Req( "Unable to allocate playback buffer." );
330 /* Enable Playback interrupt */
331 pci_outl((pci_inl(SB128_SCON
, card
) | SB128_DAC2_INTEN
), SB128_SCON
, card
);
333 card
->current_bytesize
= dma_buffer_size
;
334 card
->current_frames
= AudioCtrl
->ahiac_MaxBuffSamples
;
335 card
->current_buffer
= card
->playback_buffer
+ card
->current_bytesize
;
336 card
->playback_interrupt_enabled
= TRUE
;
340 /* Select the DAC2 Memory Page */
341 pci_outl(SB128_PAGE_DAC
, SB128_MEMPAGE
, card
);
343 /* Buffer address and length (in longwords) is set */
344 stack
= SuperState();
345 // card->playback_buffer_phys = IMMU->GetPhysicalAddress(card->playback_buffer);
346 card
->playback_buffer_phys
= card
->playback_buffer
;
349 pci_outl((unsigned long)(card
->playback_buffer_phys
), SB128_DAC2_FRAME
, card
);
350 pci_outl((((dma_buffer_size
* 2) >> 2) - 1) & 0xFFFF, SB128_DAC2_COUNT
, card
);
352 /* Playback format is always 16 Bit, Stereo, but checks exist in case of a Mono mode (not possible). */
353 PlayCtrlFlags
= (SB128_16BIT
| ChannelsFlag
) << 2;
356 if (card
->currentPlayFreq
!= freqbit
)
358 rate_set_dac2(card
, Frequencies
[freqbit
]);
359 card
->currentPlayFreq
= freqbit
;
361 card
->is_playing
= TRUE
;
364 if( flags
& AHISF_RECORD
)
368 card
->current_record_bytesize
= RECORD_BUFFER_SAMPLES
* 4;
370 /* Allocate a new recording buffer (page aligned!) */
371 card
->record_buffer
= pci_alloc_consistent(card
->current_record_bytesize
* 2, &card
->record_buffer_nonaligned
, 128);
373 if( card
->record_buffer
== NULL
)
375 Req( "Unable to allocate %ld bytes for the recording buffer.", card
->current_record_bytesize
);
379 SaveMixerState( card
);
380 UpdateMonitorMixer( card
);
382 /* Enable record interrupt */
383 pci_outl((pci_inl(SB128_SCON
, card
) | SB128_ADC_INTEN
), SB128_SCON
, card
);
385 card
->record_interrupt_enabled
= TRUE
;
389 /* Select the ADC Memory Page */
390 pci_outl(SB128_PAGE_ADC
, SB128_MEMPAGE
, card
);
392 /* Buffer address and length (in longwords) is set */
393 stack
= SuperState();
394 // card->record_buffer_phys = IMMU->GetPhysicalAddress(card->record_buffer);
395 card
->record_buffer_phys
= card
->record_buffer
;
398 pci_outl((unsigned long) card
->record_buffer_phys
, SB128_ADC_FRAME
, card
);
399 pci_outl((((card
->current_record_bytesize
* 2) >> 2) - 1) & 0xFFFF, SB128_ADC_COUNT
, card
);
401 card
->is_recording
= TRUE
;
402 card
->current_record_buffer
= card
->record_buffer
+ card
->current_record_bytesize
;
404 /* Record format is always 16 Bit, Stereo */
405 RecCtrlFlags
= (SB128_16BIT
| SB128_STEREO
) << 4;
408 if (card
->currentRecFreq
!= freqbit
)
410 rate_set_adc(card
, Frequencies
[freqbit
]);
411 card
->currentRecFreq
= freqbit
;
415 if( flags
& AHISF_PLAY
)
417 /* Set Sample Count per Interrupt */
418 if (PlayCtrlFlags
& 0x04)
420 pci_outl(((dma_buffer_size
>> 2) - 1) & 0xFFFF, SB128_DAC2_SCOUNT
, card
);
424 pci_outl(((dma_buffer_size
>> 1) - 1) & 0xFFFF, SB128_DAC2_SCOUNT
, card
);
426 /* Set format, ENDINC set to 2 */
427 pci_outl((pci_inl(SB128_SCON
, card
) | PlayCtrlFlags
| 2 << 19), SB128_SCON
, card
);
428 /* Start playback! */
429 pci_outl((pci_inl(SB128_CONTROL
, card
) | CTRL_DAC2_EN
), SB128_CONTROL
, card
);
432 if( flags
& AHISF_RECORD
)
434 /* Set Sample Count per Interrupt */
435 pci_outl(((card
->current_record_bytesize
>> 2) - 1) & 0xFFFF, SB128_ADC_SCOUNT
, card
);
437 pci_outl((pci_inl(SB128_SCON
, card
) | RecCtrlFlags
), SB128_SCON
, card
);
438 /* Start recording! */
439 pci_outl((pci_inl(SB128_CONTROL
, card
) | CTRL_ADC_EN
), SB128_CONTROL
, card
);
446 /******************************************************************************
447 ** AHIsub_Update **************************************************************
448 ******************************************************************************/
451 _AHIsub_Update( ULONG flags
,
452 struct AHIAudioCtrlDrv
* AudioCtrl
,
453 struct DriverBase
* AHIsubBase
)
455 struct SB128Base
* SB128Base
= (struct SB128Base
*) AHIsubBase
;
456 struct SB128_DATA
* card
= (struct SB128_DATA
*) AudioCtrl
->ahiac_DriverData
;
458 card
->current_frames
= AudioCtrl
->ahiac_BuffSamples
;
460 if( AudioCtrl
->ahiac_Flags
& AHIACF_STEREO
)
462 card
->current_bytesize
= card
->current_frames
* 4;
466 card
->current_bytesize
= card
->current_frames
* 2;
471 /******************************************************************************
472 ** AHIsub_Stop ****************************************************************
473 ******************************************************************************/
476 _AHIsub_Stop( ULONG flags
,
477 struct AHIAudioCtrlDrv
* AudioCtrl
,
478 struct DriverBase
* AHIsubBase
)
480 struct SB128Base
* SB128Base
= (struct SB128Base
*) AHIsubBase
;
481 struct SB128_DATA
* card
= (struct SB128_DATA
*) AudioCtrl
->ahiac_DriverData
;
482 struct PCIDevice
*dev
= card
->pci_dev
;
485 if( flags
& AHISF_PLAY
)
487 unsigned long play_ctl
;
488 card
->is_playing
= FALSE
;
490 play_ctl
= pci_inl(SB128_CONTROL
, card
);
491 play_ctl
&= ~(CTRL_DAC2_EN
);
493 pci_outl(play_ctl
, SB128_CONTROL
, card
);
495 /* Clear and mask interrupts */
496 pci_outl((pci_inl(SB128_SCON
, card
)) & SB128_IRQ_MASK
, SB128_SCON
, card
);
498 if (card
->current_bytesize
> 0)
499 pci_free_consistent(card
->playback_buffer_nonaligned
);
501 card
->current_bytesize
= 0;
502 card
->current_frames
= 0;
503 card
->current_buffer
= NULL
;
505 if ( card
->mix_buffer
)
506 FreeVec( card
->mix_buffer
);
507 card
->mix_buffer
= NULL
;
508 card
->playback_interrupt_enabled
= FALSE
;
509 card
->current_bytesize
= 0;
512 if( flags
& AHISF_RECORD
)
514 unsigned long rec_ctl
, val
;
516 rec_ctl
= pci_inl(SB128_CONTROL
, card
);
517 rec_ctl
&= ~(CTRL_ADC_EN
);
519 pci_outl(rec_ctl
, SB128_CONTROL
, card
);
521 /* Clear and mask interrupts */
522 pci_outl((pci_inl(SB128_SCON
, card
)) & SB128_IRQ_MASK
, SB128_SCON
, card
);
524 if( card
->is_recording
)
526 /* Do not restore mixer unless they have been saved */
527 RestoreMixerState( card
);
530 if( card
->record_buffer
!= NULL
)
532 pci_free_consistent( card
->record_buffer_nonaligned
);
535 card
->record_buffer
= NULL
;
536 card
->current_record_bytesize
= 0;
538 card
->is_recording
= FALSE
;
539 card
->record_interrupt_enabled
= FALSE
;
546 /******************************************************************************
547 ** AHIsub_GetAttr *************************************************************
548 ******************************************************************************/
551 _AHIsub_GetAttr( ULONG attribute
,
554 struct TagItem
* taglist
,
555 struct AHIAudioCtrlDrv
* AudioCtrl
,
556 struct DriverBase
* AHIsubBase
)
558 struct SB128Base
* SB128Base
= (struct SB128Base
*) AHIsubBase
;
567 case AHIDB_Frequencies
:
570 case AHIDB_Frequency
: /* Index->Frequency */
571 return (LONG
) Frequencies
[ argument
];
573 case AHIDB_Index
: /* Frequency->Index */
574 if( argument
<= (LONG
) Frequencies
[ 0 ] )
579 if( argument
>= (LONG
) Frequencies
[ FREQUENCIES
- 1 ] )
581 return FREQUENCIES
-1;
584 for( i
= 1; i
< FREQUENCIES
; i
++ )
586 if( (LONG
) Frequencies
[ i
] > argument
)
588 if( ( argument
- (LONG
) Frequencies
[ i
- 1 ] ) < ( (LONG
) Frequencies
[ i
] - argument
) )
599 return 0; /* Will not happen */
602 return (LONG
) "Ross Vumbaca";
604 case AHIDB_Copyright
:
605 return (LONG
) "(C) Ross Vumbaca";
608 return (LONG
) LibIDString
;
610 case AHIDB_Annotation
:
612 "AROS SB128/ES137x Audio driver";
617 case AHIDB_FullDuplex
:
623 case AHIDB_MaxRecordSamples
:
624 return RECORD_BUFFER_SAMPLES
;
629 unsigned long res = (unsigned long) (0x10000 * pow (10.0, dB / 20.0));
630 double dB = 20.0 * log10(0xVALUE / 65536.0);
632 printf("dB = %f, res = %lx\n", dB, res);*/
634 case AHIDB_MinMonitorVolume
:
637 case AHIDB_MaxMonitorVolume
:
640 case AHIDB_MinInputGain
:
641 return 0x10000; /* 0.0 dB gain */
643 case AHIDB_MaxInputGain
:
644 return 0xD55D0; /* 22.5 dB gain */
646 case AHIDB_MinOutputVolume
:
647 return 0x004d2; /* -34.5 dB / mute */
649 case AHIDB_MaxOutputVolume
:
650 return 0x3fb27; /* 12 dB */
656 return (LONG
) Inputs
[ argument
];
662 return (LONG
) Outputs
[ argument
];
670 /******************************************************************************
671 ** AHIsub_HardwareControl *****************************************************
672 ******************************************************************************/
675 _AHIsub_HardwareControl( ULONG attribute
,
677 struct AHIAudioCtrlDrv
* AudioCtrl
,
678 struct DriverBase
* AHIsubBase
)
680 struct SB128Base
* SB128Base
= (struct SB128Base
*) AHIsubBase
;
681 struct SB128_DATA
* card
= (struct SB128_DATA
*) AudioCtrl
->ahiac_DriverData
;
685 case AHIC_MonitorVolume
:
686 card
->monitor_volume
= Linear2MixerGain( (Fixed
) argument
, &card
->monitor_volume_bits
);
687 if( card
->is_recording
)
689 UpdateMonitorMixer( card
);
693 case AHIC_MonitorVolume_Query
:
694 return card
->monitor_volume
;
697 card
->input_gain
= Linear2RecordGain( (Fixed
) argument
, &card
->input_gain_bits
);
700 /* Not supported on ES1370 */
703 codec_write(card
, AC97_RECORD_GAIN
, card
->input_gain_bits
);
706 case AHIC_InputGain_Query
:
707 return card
->input_gain
;
709 case AHIC_OutputVolume
:
710 card
->output_volume
= Linear2MixerGain( (Fixed
) argument
, &card
->output_volume_bits
);
713 ak4531_ac97_write(card
, AC97_PCMOUT_VOL
, card
->output_volume_bits
);
716 codec_write(card
, AC97_PCMOUT_VOL
, card
->output_volume_bits
);
719 case AHIC_OutputVolume_Query
:
720 return card
->output_volume
;
723 card
->input
= argument
;
726 ak4531_ac97_write(card
, AC97_RECORD_SELECT
, InputBits
[ card
->input
] );
729 codec_write(card
, AC97_RECORD_SELECT
, InputBits
[ card
->input
] );
731 if( card
->is_recording
)
733 UpdateMonitorMixer( card
);
737 case AHIC_Input_Query
:
741 card
->output
= argument
;
743 if( card
->output
== 0 )
751 case AHIC_Output_Query
: