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.
14 #if !defined(__AROS__)
16 #include <proto/expansion.h>
19 #include <devices/ahi.h>
20 #include <exec/memory.h>
21 #include <libraries/ahi_sub.h>
23 #include <proto/ahi_sub.h>
24 #include <proto/exec.h>
25 #include <proto/dos.h>
26 #include <proto/utility.h>
30 #include <aros/debug.h>
31 #define DebugPrintF bug
39 #include "pci_wrapper.h"
43 /******************************************************************************
44 ** Globals ********************************************************************
45 ******************************************************************************/
49 static const ULONG Frequencies
[ FREQUENCIES
] =
52 8000, // ยต- and A-Law
61 static const ULONG FrequencyBits
[ FREQUENCIES
] =
75 static const STRPTR Inputs
[ INPUTS
] =
85 /* Not static since it's used in misc.c too */
86 const UWORD InputBits
[ INPUTS
] =
93 AC97_RECMUX_STEREO_MIX
,
101 static const STRPTR Outputs
[ OUTPUTS
] =
107 /******************************************************************************
108 ** AHIsub_AllocAudio **********************************************************
109 ******************************************************************************/
112 _AHIsub_AllocAudio( struct TagItem
* taglist
,
113 struct AHIAudioCtrlDrv
* AudioCtrl
,
114 struct DriverBase
* AHIsubBase
)
116 struct CMI8738Base
* CMI8738Base
= (struct CMI8738Base
*) AHIsubBase
;
122 bug("[CMI8738]: %s()\n", __PRETTY_FUNCTION__
);
124 card_num
= ( GetTagData( AHIDB_AudioID
, 0, taglist
) & 0x0000f000 ) >> 12;
126 if( card_num
>= CMI8738Base
->cards_found
||
127 CMI8738Base
->driverdatas
[ card_num
] == NULL
)
129 DebugPrintF("no date for card = %ld\n", card_num
);
130 Req( "No CMI8738_DATA for card %ld.", card_num
);
135 struct CMI8738_DATA
* card
;
138 card
= CMI8738Base
->driverdatas
[ card_num
];
139 AudioCtrl
->ahiac_DriverData
= card
;
141 ObtainSemaphore( &CMI8738Base
->semaphore
);
142 in_use
= ( card
->audioctrl
!= NULL
);
145 card
->audioctrl
= AudioCtrl
;
147 ReleaseSemaphore( &CMI8738Base
->semaphore
);
154 card
->playback_interrupt_enabled
= FALSE
;
155 card
->record_interrupt_enabled
= FALSE
;
158 ret
= AHISF_KNOWHIFI
| AHISF_KNOWSTEREO
| AHISF_MIXING
| AHISF_TIMING
;
160 for( i
= 0; i
< FREQUENCIES
; ++i
)
162 if( AudioCtrl
->ahiac_MixFreq
== Frequencies
[ i
] )
164 ret
|= AHISF_CANRECORD
;
174 /******************************************************************************
175 ** AHIsub_FreeAudio ***********************************************************
176 ******************************************************************************/
179 _AHIsub_FreeAudio( struct AHIAudioCtrlDrv
* AudioCtrl
,
180 struct DriverBase
* AHIsubBase
)
182 struct CMI8738Base
* CMI8738Base
= (struct CMI8738Base
*) AHIsubBase
;
183 struct CMI8738_DATA
* card
= (struct CMI8738_DATA
*) AudioCtrl
->ahiac_DriverData
;
185 bug("[CMI8738]: %s()\n", __PRETTY_FUNCTION__
);
189 ObtainSemaphore( &CMI8738Base
->semaphore
);
190 if( card
->audioctrl
== AudioCtrl
)
192 // Release it if we own it.
193 card
->audioctrl
= NULL
;
195 ReleaseSemaphore( &CMI8738Base
->semaphore
);
197 AudioCtrl
->ahiac_DriverData
= NULL
;
202 /******************************************************************************
203 ** AHIsub_Disable *************************************************************
204 ******************************************************************************/
207 _AHIsub_Disable( struct AHIAudioCtrlDrv
* AudioCtrl
,
208 struct DriverBase
* AHIsubBase
)
210 bug("[CMI8738]: %s()\n", __PRETTY_FUNCTION__
);
212 // V6 drivers do not have to preserve all registers
218 /******************************************************************************
219 ** AHIsub_Enable **************************************************************
220 ******************************************************************************/
223 _AHIsub_Enable( struct AHIAudioCtrlDrv
* AudioCtrl
,
224 struct DriverBase
* AHIsubBase
)
226 bug("[CMI8738]: %s()\n", __PRETTY_FUNCTION__
);
228 // V6 drivers do not have to preserve all registers
234 /******************************************************************************
235 ** AHIsub_Start ***************************************************************
236 ******************************************************************************/
239 _AHIsub_Start( ULONG flags
,
240 struct AHIAudioCtrlDrv
* AudioCtrl
,
241 struct DriverBase
* AHIsubBase
)
243 #if !defined(__AROS__)
244 struct CMI8738Base
* CMI8738Base
= (struct CMI8738Base
*) AHIsubBase
;
247 struct CMI8738_DATA
* card
= (struct CMI8738_DATA
*) AudioCtrl
->ahiac_DriverData
;
248 struct PCIDevice
*dev
= card
->pci_dev
;
249 ULONG dma_buffer_size
= 0;
252 bug("[CMI8738]: %s()\n", __PRETTY_FUNCTION__
);
254 /* Stop playback/recording, free old buffers (if any) */
255 //IAHIsub->AHIsub_Stop( flags, AudioCtrl );
257 for( i
= 0; i
< FREQUENCIES
; ++i
)
259 if( AudioCtrl
->ahiac_MixFreq
== Frequencies
[ i
] )
266 card
->mixerstate
= cmimix_rd(dev
, card
, CMPCI_SB16_MIXER_OUTMIX
);
268 if( flags
& AHISF_PLAY
)
270 ULONG dma_sample_frame_size
;
271 unsigned short ChannelsFlag
= CMPCI_REG_FORMAT_16BIT
;
273 //WriteMask(dev, card, CMPCI_REG_FUNC_0, CMPCI_REG_CH0_RESET | CMPCI_REG_CH1_RESET);
274 //ClearMask(dev, card, CMPCI_REG_FUNC_0, CMPCI_REG_CH0_RESET | CMPCI_REG_CH1_RESET);
276 /* Allocate a new mixing buffer. Note: The buffer must be cleared, since
277 it might not be filled by the mixer software interrupt because of
278 pretimer/posttimer! */
280 card
->mix_buffer
= AllocVec( AudioCtrl
->ahiac_BuffSize
, MEMF_PUBLIC
| MEMF_CLEAR
);
282 if( card
->mix_buffer
== NULL
)
284 Req( "Unable to allocate %ld bytes for mixing buffer.", AudioCtrl
->ahiac_BuffSize
);
288 /* Allocate a buffer large enough for 16-bit double-buffered
289 playback (mono or stereo) */
291 if( AudioCtrl
->ahiac_Flags
& AHIACF_STEREO
)
293 dma_sample_frame_size
= 4;
294 dma_buffer_size
= AudioCtrl
->ahiac_MaxBuffSamples
* dma_sample_frame_size
;
295 ChannelsFlag
|= CMPCI_REG_FORMAT_STEREO
;
299 dma_sample_frame_size
= 2;
300 dma_buffer_size
= AudioCtrl
->ahiac_MaxBuffSamples
* dma_sample_frame_size
;
303 //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);
305 card
->playback_buffer
= pci_alloc_consistent(dma_buffer_size
* 2, &card
->playback_buffer_nonaligned
, 128);
307 if (!card
->playback_buffer
)
309 Req( "Unable to allocate playback buffer." );
313 card
->current_bytesize
= dma_buffer_size
;
314 card
->current_frames
= AudioCtrl
->ahiac_MaxBuffSamples
;
315 card
->current_buffer
= card
->playback_buffer
+ card
->current_bytesize
;
316 card
->playback_interrupt_enabled
= TRUE
;
321 WritePartialMask(dev
, card
, CMPCI_REG_FUNC_1
, CMPCI_REG_DAC_FS_SHIFT
, CMPCI_REG_DAC_FS_MASK
, FrequencyBits
[freqbit
]);
322 WritePartialMask(dev
, card
, CMPCI_REG_CHANNEL_FORMAT
, CMPCI_REG_CH0_FORMAT_SHIFT
, CMPCI_REG_CH0_FORMAT_MASK
, ChannelsFlag
);
323 WriteMask(dev
, card
, CMPCI_REG_CHANNEL_FORMAT
, (13 << 1));
325 #if !defined(__AROS__)
326 if (IFakeDMA
== NULL
)
328 stack
= SuperState();
329 card
->playback_buffer_phys
= IMMU
->GetPhysicalAddress(card
->playback_buffer
);
334 card
->playback_buffer_phys
= card
->playback_buffer
;
336 bug("[CMI8738] %s: Playback buffer @ 0x%p\n", __PRETTY_FUNCTION__
, card
->playback_buffer
);
338 pci_outl((ULONG
)card
->playback_buffer_phys
, CMPCI_REG_DMA0_BASE
, card
);
339 pci_outw((dma_buffer_size
/ dma_sample_frame_size
) * 2 - 1, CMPCI_REG_DMA0_LENGTH
, card
);
340 pci_outw((dma_buffer_size
/ dma_sample_frame_size
) - 1, CMPCI_REG_DMA0_INTLEN
, card
);
342 card
->is_playing
= TRUE
;
345 if( flags
& AHISF_RECORD
)
349 card
->current_record_bytesize
= RECORD_BUFFER_SAMPLES
* 4;
351 /* Allocate a new recording buffer (page aligned!) */
352 card
->record_buffer
= pci_alloc_consistent(card
->current_record_bytesize
* 2, &card
->record_buffer_nonaligned
, 128);
354 if( card
->record_buffer
== NULL
)
356 Req( "Unable to allocate %ld bytes for the recording buffer.", card
->current_record_bytesize
, 128);
360 SaveMixerState( card
);
361 UpdateMonitorMixer( card
);
366 cmimix_wr(dev
, card
, CMPCI_SB16_MIXER_OUTMIX
, card
->mixerstate
| CMPCI_SB16_SW_LINE
);
370 cmimix_wr(dev
, card
, CMPCI_SB16_MIXER_OUTMIX
, card
->mixerstate
| CMPCI_SB16_SW_MIC
);
374 cmimix_wr(dev
, card
, CMPCI_SB16_MIXER_OUTMIX
, card
->mixerstate
| CMPCI_SB16_SW_CD
);
378 byte
= pci_inb(CMPCI_REG_MIXER25
, card
);
380 pci_outb(byte
, CMPCI_REG_MIXER25
, card
); // unmute Aux
387 card
->record_interrupt_enabled
= TRUE
;
391 WritePartialMask(dev
, card
, CMPCI_REG_FUNC_1
, CMPCI_REG_ADC_FS_SHIFT
, CMPCI_REG_ADC_FS_MASK
, FrequencyBits
[freqbit
]);
392 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
);
394 #if !defined(__AROS__)
395 if (IFakeDMA
== NULL
)
397 stack
= SuperState();
398 card
->record_buffer_phys
= IMMU
->GetPhysicalAddress(card
->record_buffer
);
403 card
->record_buffer_phys
= card
->record_buffer
;
405 pci_outl((ULONG
)card
->record_buffer_phys
, CMPCI_REG_DMA1_BASE
, card
);
407 pci_outw((card
->current_record_bytesize
/ 4) * 2 - 1, CMPCI_REG_DMA1_LENGTH
, card
);
409 pci_outw((card
->current_record_bytesize
/ 4) - 1, CMPCI_REG_DMA1_INTLEN
, card
);
411 card
->current_record_buffer
= card
->record_buffer
+ card
->current_record_bytesize
;
412 card
->is_recording
= TRUE
;
415 if( flags
& AHISF_PLAY
)
418 WriteMask(dev
, card
, CMPCI_REG_FUNC_0
, CMPCI_REG_CH0_ENABLE
);
419 WriteMask(dev
, card
, CMPCI_REG_INTR_CTRL
, CMPCI_REG_CH0_INTR_ENABLE
);
422 if( flags
& AHISF_RECORD
)
424 WriteMask(dev
, card
, CMPCI_REG_FUNC_0
, CMPCI_REG_CH1_ENABLE
);
425 WriteMask(dev
, card
, CMPCI_REG_INTR_CTRL
, CMPCI_REG_CH1_INTR_ENABLE
);
432 /******************************************************************************
433 ** AHIsub_Update **************************************************************
434 ******************************************************************************/
437 _AHIsub_Update( ULONG flags
,
438 struct AHIAudioCtrlDrv
* AudioCtrl
,
439 struct DriverBase
* AHIsubBase
)
442 struct CMI8738_DATA
* card
= (struct CMI8738_DATA
*) AudioCtrl
->ahiac_DriverData
;
445 bug("[CMI8738]: %s()\n", __PRETTY_FUNCTION__
);
448 card
->current_frames
= AudioCtrl
->ahiac_BuffSamples
;
450 if( AudioCtrl
->ahiac_Flags
& AHIACF_STEREO
)
452 card
->current_bytesize
= card
->current_frames
* 4;
456 card
->current_bytesize
= card
->current_frames
* 2;
462 /******************************************************************************
463 ** AHIsub_Stop ****************************************************************
464 ******************************************************************************/
467 _AHIsub_Stop( ULONG flags
,
468 struct AHIAudioCtrlDrv
* AudioCtrl
,
469 struct DriverBase
* AHIsubBase
)
471 struct CMI8738_DATA
* card
= (struct CMI8738_DATA
*) AudioCtrl
->ahiac_DriverData
;
472 struct PCIDevice
*dev
= card
->pci_dev
;
474 bug("[CMI8738]: %s()\n", __PRETTY_FUNCTION__
);
476 if( flags
& AHISF_PLAY
)
478 card
->is_playing
= FALSE
;
480 ClearMask(dev
, card
, CMPCI_REG_INTR_CTRL
, CMPCI_REG_CH0_INTR_ENABLE
);
481 ClearMask(dev
, card
, CMPCI_REG_FUNC_0
, CMPCI_REG_CH0_ENABLE
);
483 if (card
->current_bytesize
> 0)
484 pci_free_consistent(card
->playback_buffer_nonaligned
);
486 card
->current_bytesize
= 0;
487 card
->current_frames
= 0;
488 card
->current_buffer
= NULL
;
490 if ( card
->mix_buffer
)
491 FreeVec( card
->mix_buffer
);
493 card
->mix_buffer
= NULL
;
494 card
->playback_interrupt_enabled
= FALSE
;
495 card
->current_bytesize
= 0;
496 //DebugPrintF("#IRQ's = %ld\n", z);
499 if( flags
& AHISF_RECORD
&& card
->is_recording
)
503 ClearMask(dev
, card
, CMPCI_REG_INTR_CTRL
, CMPCI_REG_CH1_INTR_ENABLE
);
504 ClearMask(dev
, card
, CMPCI_REG_FUNC_0
, CMPCI_REG_CH1_ENABLE
);
509 cmimix_wr(dev
, card
, CMPCI_SB16_MIXER_OUTMIX
, card
->mixerstate
);
513 cmimix_wr(dev
, card
, CMPCI_SB16_MIXER_OUTMIX
, card
->mixerstate
);
517 cmimix_wr(dev
, card
, CMPCI_SB16_MIXER_OUTMIX
, card
->mixerstate
);
521 byte
= pci_inb(CMPCI_REG_MIXER25
, card
);
522 pci_outb(byte
& ~0x30, CMPCI_REG_MIXER25
, card
); // mute Aux
529 if( card
->record_buffer
!= NULL
)
531 pci_free_consistent( card
->record_buffer_nonaligned
);
534 card
->record_buffer
= NULL
;
535 card
->current_record_bytesize
= 0;
537 card
->is_recording
= FALSE
;
538 card
->record_interrupt_enabled
= FALSE
;
543 /******************************************************************************
544 ** AHIsub_GetAttr *************************************************************
545 ******************************************************************************/
548 _AHIsub_GetAttr( ULONG attribute
,
551 struct TagItem
* taglist
,
552 struct AHIAudioCtrlDrv
* AudioCtrl
,
553 struct DriverBase
* AHIsubBase
)
555 struct CMI8738Base
* CMI8738Base
= (struct CMI8738Base
*) AHIsubBase
;
558 bug("[CMI8738]: %s()\n", __PRETTY_FUNCTION__
);
560 struct CMI8738_DATA
* card
= (struct CMI8738_DATA
*) AudioCtrl
->ahiac_DriverData
;
563 int card_num
= ( GetTagData( AHIDB_AudioID
, 0, taglist
) & 0x0000f000 ) >> 12;
565 if( card_num
<= CMI8738Base
->cards_found
||
566 CMI8738Base
->driverdatas
[ card_num
] != NULL
)
567 card
= CMI8738Base
->driverdatas
[ card_num
];
569 bug("[CMI8738] %s: card data @ 0x%p\n", __PRETTY_FUNCTION__
, card
);
576 case AHIDB_MaxChannels
:
578 return card
->channels
;
581 case AHIDB_Frequencies
:
584 case AHIDB_Frequency
: // Index->Frequency
585 return (LONG
) Frequencies
[ argument
];
587 case AHIDB_Index
: // Frequency->Index
588 if( argument
<= (LONG
) Frequencies
[ 0 ] )
593 if( argument
>= (LONG
) Frequencies
[ FREQUENCIES
- 1 ] )
595 return FREQUENCIES
-1;
598 for( i
= 1; i
< FREQUENCIES
; i
++ )
600 if( (LONG
) Frequencies
[ i
] > argument
)
602 if( ( argument
- (LONG
) Frequencies
[ i
- 1 ] ) < ( (LONG
) Frequencies
[ i
] - argument
) )
613 return 0; // Will not happen
616 return (LONG
) "Davy Wentzler";
618 case AHIDB_Copyright
:
619 return (LONG
) "(C) 2011 The AROS Dev Team";
622 return (LONG
) LibIDString
;
624 case AHIDB_Annotation
:
625 return (LONG
) "AROS CMI8738 Audio driver";
630 case AHIDB_FullDuplex
:
636 case AHIDB_MaxRecordSamples
:
637 return RECORD_BUFFER_SAMPLES
;
642 unsigned long res = (unsigned long) (0x10000 * pow (10.0, dB / 20.0));
643 double dB = 20.0 * log10(0xVALUE / 65536.0);
645 printf("dB = %f, res = %lx\n", dB, res);*/
647 case AHIDB_MinMonitorVolume
:
650 case AHIDB_MaxMonitorVolume
:
653 case AHIDB_MinInputGain
:
654 return 0x10000; // 0.0 dB gain
656 case AHIDB_MaxInputGain
:
657 return 0x10000; // 0 dB gain
659 case AHIDB_MinOutputVolume
:
660 return 0x34; // -62 dB
662 case AHIDB_MaxOutputVolume
:
663 return 0x10000; // 0 dB
669 return (LONG
) Inputs
[ argument
];
675 return (LONG
) Outputs
[ argument
];
683 /******************************************************************************
684 ** AHIsub_HardwareControl *****************************************************
685 ******************************************************************************/
688 _AHIsub_HardwareControl( ULONG attribute
,
690 struct AHIAudioCtrlDrv
* AudioCtrl
,
691 struct DriverBase
* AHIsubBase
)
693 struct CMI8738_DATA
* card
= (struct CMI8738_DATA
*) AudioCtrl
->ahiac_DriverData
;
694 struct PCIDevice
*dev
= card
->pci_dev
;
697 bug("[CMI8738]: %s()\n", __PRETTY_FUNCTION__
);
701 case AHIC_MonitorVolume
:
702 card
->monitor_volume
= Linear2MixerGain( (Fixed
) argument
, &card
->monitor_volume_bits
);
703 //DebugPrintF("card->monitor_volume = %lu, %lx\n", card->monitor_volume, card->monitor_volume);
704 if( card
->is_recording
)
706 UpdateMonitorMixer( card
);
710 case AHIC_MonitorVolume_Query
:
711 return card
->monitor_volume
;
714 card
->input_gain
= Linear2RecordGain( (Fixed
) argument
, &card
->input_gain_bits
);
715 //codec_write(card, AC97_RECORD_GAIN, card->input_gain_bits );
718 case AHIC_InputGain_Query
:
719 return card
->input_gain
;
721 case AHIC_OutputVolume
:
723 double dB
= 20.0 * log10((Fixed
) argument
/ 65536.0);
724 unsigned int val
= 0xFF - ( ((unsigned int)(-dB
/2)) << 3);
725 cmimix_wr(dev
, card
, 0x30, val
);
726 cmimix_wr(dev
, card
, 0x31, val
);
729 case AHIC_OutputVolume_Query
:
730 return card
->output_volume
;
733 card
->input
= argument
;
738 cmimix_wr(dev
, card
, CMPCI_SB16_MIXER_ADCMIX_L
, (CMPCI_SB16_MIXER_LINE_SRC_R
<< 1) );
739 cmimix_wr(dev
, card
, CMPCI_SB16_MIXER_ADCMIX_R
, CMPCI_SB16_MIXER_LINE_SRC_R
);
743 cmimix_wr(dev
, card
, CMPCI_SB16_MIXER_ADCMIX_L
, CMPCI_SB16_MIXER_MIC_SRC
);
744 cmimix_wr(dev
, card
, CMPCI_SB16_MIXER_ADCMIX_R
, CMPCI_SB16_MIXER_MIC_SRC
);
748 cmimix_wr(dev
, card
, CMPCI_SB16_MIXER_ADCMIX_L
, (CMPCI_SB16_MIXER_CD_SRC_R
<< 1) );
749 cmimix_wr(dev
, card
, CMPCI_SB16_MIXER_ADCMIX_R
, CMPCI_SB16_MIXER_CD_SRC_R
);
753 byte
= pci_inb(CMPCI_REG_MIXER25
, card
);
754 pci_outb(byte
| 0xC0, CMPCI_REG_MIXER25
, card
); // rec source Aux
765 if( card
->is_recording
)
767 UpdateMonitorMixer( card
);
772 case AHIC_Input_Query
:
776 card
->output
= argument
;
778 if( card
->output
== 0 )
780 ClearMask(dev
, card
, CMPCI_REG_FUNC_1
, CMPCI_REG_SPDIFOUT_DAC
| CMPCI_REG_SPDIF0_ENABLE
);
781 ClearMask(dev
, card
, CMPCI_REG_LEGACY_CTRL
, CMPCI_REG_XSPDIF_ENABLE
);
785 WriteMask(dev
, card
, CMPCI_REG_FUNC_1
, CMPCI_REG_SPDIFOUT_DAC
| CMPCI_REG_SPDIF0_ENABLE
);
786 WriteMask(dev
, card
, CMPCI_REG_LEGACY_CTRL
, CMPCI_REG_XSPDIF_ENABLE
);
790 case AHIC_Output_Query
: