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>
18 #include <libraries/ahi_sub.h>
19 #include <proto/exec.h>
23 #include "interrupt.h"
25 #include "pci_wrapper.h"
27 #include <aros/debug.h>
28 #define DebugPrintF bug
31 #define min(a,b) ((a)<(b)?(a):(b))
36 //struct tester t[10];
39 /******************************************************************************
40 ** Hardware interrupt handler *************************************************
41 ******************************************************************************/
45 CardInterrupt( struct CMI8738_DATA
* card
)
47 struct AHIAudioCtrlDrv
* AudioCtrl
= card
->audioctrl
;
48 struct PCIDevice
*dev
= (struct PCIDevice
* ) card
->pci_dev
;
53 bug("[CMI8738]: %s(card @ 0x%p)\n", __PRETTY_FUNCTION__
, card
);
54 bug("[CMI8738] %s: AHIAudioCtrlDrv @ 0x%p\n", __PRETTY_FUNCTION__
, AudioCtrl
);
57 // while (((intreq = pci_inl(CMPCI_REG_INTR_STATUS, card)) & CMPCI_REG_ANY_INTR) != 0)
59 intreq
= pci_inl(CMPCI_REG_INTR_STATUS
, card
);
61 bug("[CMI8738] %s: INTR_STATUS = %08x\n", __PRETTY_FUNCTION__
, intreq
);
63 if (((intreq
& CMPCI_REG_ANY_INTR
) == 0) || (AudioCtrl
== NULL
))
66 //DebugPrintF("INT %lx\n", intreq);
67 if( intreq
& CMPCI_REG_CH0_INTR
)
69 unsigned long diff
= pci_inl(CMPCI_REG_DMA0_BASE
, card
) - (unsigned long) card
->playback_buffer_phys
;
71 ClearMask(dev
, card
, CMPCI_REG_INTR_CTRL
, CMPCI_REG_CH0_INTR_ENABLE
);
78 t[z].flip = card->flip;
79 t[z].oldflip = card->oldflip;
82 /*if ((diff > 50 && diff < card->current_bytesize) ||
83 (diff > card->current_bytesize + 50 && diff < 2 * card->current_bytesize))
84 DebugPrintF("Delayed IRQ %lu %lu\n", diff % card->current_bytesize, card->current_bytesize);*/
87 if (diff
>= card
->current_bytesize
) //card->flip == 0) // just played buf 1
91 DebugPrintF("A:Missed IRQ! diff = %lu\n", diff
);
95 card
->current_buffer
= card
->playback_buffer
;
97 else // just played buf 2
101 DebugPrintF("B:Missed IRQ! diff = %lu\n", diff
);
105 card
->current_buffer
= (APTR
) ((long) card
->playback_buffer
+ card
->current_bytesize
);
112 card
->playback_interrupt_enabled
= FALSE
;
113 Cause( &card
->playback_interrupt
);
116 if( intreq
& CMPCI_REG_CH1_INTR
)
118 ClearMask(dev
, card
, CMPCI_REG_INTR_CTRL
, CMPCI_REG_CH1_INTR_ENABLE
);
121 DebugPrintF("rec\n");*/
126 if( card
->record_interrupt_enabled
)
128 /* Invoke softint to convert and feed AHI with the new sample data */
130 if (card
->recflip
== 0) // just played buf 1
133 card
->current_record_buffer
= card
->record_buffer
;
135 else // just played buf 2
138 card
->current_record_buffer
= (APTR
) ((long) card
->record_buffer
+ card
->current_record_bytesize
);
141 card
->record_interrupt_enabled
= FALSE
;
142 Cause( &card
->record_interrupt
);
154 /******************************************************************************
155 ** Playback interrupt handler *************************************************
156 ******************************************************************************/
159 PlaybackInterrupt( struct CMI8738_DATA
* card
)
161 struct AHIAudioCtrlDrv
* AudioCtrl
= card
->audioctrl
;
162 struct DriverBase
* AHIsubBase
= (struct DriverBase
*) card
->ahisubbase
;
163 struct PCIDevice
*dev
= (struct PCIDevice
* ) card
->pci_dev
;
165 bug("[CMI8738]: %s()\n", __PRETTY_FUNCTION__
);
167 if( card
->mix_buffer
!= NULL
&& card
->current_buffer
!= NULL
)
177 skip_mix
= CallHookPkt( AudioCtrl
->ahiac_PreTimerFunc
, (Object
*) AudioCtrl
, 0 );
178 CallHookPkt( AudioCtrl
->ahiac_PlayerFunc
, (Object
*) AudioCtrl
, NULL
);
180 //DebugPrintF("skip_mix = %d\n", skip_mix);
184 CallHookPkt( AudioCtrl
->ahiac_MixerFunc
, (Object
*) AudioCtrl
, card
->mix_buffer
);
187 /* Now translate and transfer to the DMA buffer */
190 skip
= ( AudioCtrl
->ahiac_Flags
& AHIACF_HIFI
) ? 2 : 1;
191 samples
= card
->current_bytesize
>> 1;
193 src
= card
->mix_buffer
;
194 #if !defined(__AMIGAOS4__) && !AROS_BIG_ENDIAN
198 dst
= card
->current_buffer
;
206 *dst
= ( ( *src
& 0xff ) << 8 ) | ( ( *src
& 0xff00 ) >> 8 );
208 *dst
= AROS_WORD2LE(*src
);
217 CacheClearE( card
->current_buffer
, (ULONG
) dst
- (ULONG
) card
->current_buffer
, CACRF_ClearD
);
219 CallHookPkt( AudioCtrl
->ahiac_PostTimerFunc
, (Object
*) AudioCtrl
, 0 );
222 WriteMask(dev
, card
, CMPCI_REG_INTR_CTRL
, CMPCI_REG_CH0_INTR_ENABLE
);
223 card
->playback_interrupt_enabled
= TRUE
;
227 /******************************************************************************
228 ** Record interrupt handler ***************************************************
229 ******************************************************************************/
232 RecordInterrupt( struct CMI8738_DATA
* card
)
234 struct AHIAudioCtrlDrv
* AudioCtrl
= card
->audioctrl
;
235 struct DriverBase
* AHIsubBase
= (struct DriverBase
*) card
->ahisubbase
;
236 struct PCIDevice
*dev
= (struct PCIDevice
* ) card
->pci_dev
;
238 bug("[CMI8738]: %s()\n", __PRETTY_FUNCTION__
);
240 struct AHIRecordMessage rm
=
243 card
->current_record_buffer
,
244 RECORD_BUFFER_SAMPLES
247 int i
= 0, shorts
= card
->current_record_bytesize
/ 2;
248 WORD
* ptr
= (WORD
*) card
->current_record_buffer
;
251 CacheClearE( card
->current_record_buffer
, card
->current_record_bytesize
, CACRF_ClearD
);
255 #if defined(__AMIGAOS4__) || AROS_BIG_ENDIAN
256 *ptr
= ( ( *ptr
& 0xff ) << 8 ) | ( ( *ptr
& 0xff00 ) >> 8 );
262 CallHookPkt( AudioCtrl
->ahiac_SamplerFunc
, (Object
*) AudioCtrl
, &rm
);
264 CacheClearE( card
->current_record_buffer
, card
->current_record_bytesize
, CACRF_ClearD
);
267 WriteMask(dev
, card
, CMPCI_REG_INTR_CTRL
, CMPCI_REG_CH1_INTR_ENABLE
);
268 card
->record_interrupt_enabled
= TRUE
;