revert between 56095 -> 55830 in arch
[AROS.git] / workbench / devs / AHI / Drivers / Envy24HT / interrupt.c
blob14ffd455b9c69399e905bbc7f8698185599c6e8d
1 /*
2 Copyright © 2005-2013, Davy Wentzler. All rights reserved.
3 $Id$
4 */
6 #include <config.h>
8 #undef __USE_INLINE__
9 #include <proto/expansion.h>
10 #include <libraries/ahi_sub.h>
11 #include <proto/exec.h>
12 #include <stddef.h>
13 //#include "library.h"
14 #include "regs.h"
15 #include "interrupt.h"
16 #include "misc.h"
17 #include "pci_wrapper.h"
19 #define min(a,b) ((a)<(b)?(a):(b))
21 #ifdef __MORPHOS__
22 #undef CALLHOOK
23 #define CALLHOOK CallHookA
24 #endif
25 #include <clib/alib_protos.h>
27 //int z = 0;
29 /******************************************************************************
30 ** Hardware interrupt handler *************************************************
31 ******************************************************************************/
33 #ifdef __AMIGAOS4__
34 LONG
35 CardInterrupt( struct ExceptionContext *pContext, struct ExecBase *SysBase, struct CardData* card )
36 #else
37 ULONG
38 CardInterrupt( struct CardData* card )
39 #endif
41 struct AHIAudioCtrlDrv* AudioCtrl = card->audioctrl;
43 unsigned char intreq;
44 LONG handled = 0;
46 if ( ( intreq = INBYTE(card->iobase + CCS_INTR_STATUS ) ) != 0 )
48 //DEBUGPRINTF("INT %x\n", intreq);
50 if (intreq & CCS_INTR_PLAYREC)
52 unsigned char mtstatus = INBYTE(card->mtbase + MT_INTR_STATUS);
54 if( (mtstatus & MT_PDMA0) && AudioCtrl != NULL && card->is_playing)
56 unsigned long diff = INLONG(card->mtbase + MT_DMAI_PB_ADDRESS) - (unsigned long) card->playback_buffer_phys;
58 OUTBYTE(card->mtbase + MT_INTR_STATUS, mtstatus | MT_PDMA0); // clear interrupt
60 /*if (z == 0)
61 DEBUGPRINTF("MT_PDMA0, diff = %lu, %lu\n", diff, card->current_frames);
62 z++;
63 if (z == 5)
64 z = 0;*/
66 if (diff >= card->current_bytesize) //card->flip == 0) // just played buf 1
68 card->flip = 1;
69 card->current_buffer = card->playback_buffer;
70 card->spdif_out_current_buffer = card->spdif_out_buffer;
72 else // just played buf 2
74 card->flip = 0;
75 card->current_buffer = (APTR) ((long) card->playback_buffer + card->current_bytesize);
76 card->spdif_out_current_buffer = (APTR) ((long) card->spdif_out_buffer + card->current_bytesize / 2);
79 card->playback_interrupt_enabled = FALSE;
80 CAUSE( &card->playback_interrupt );
83 if( ((mtstatus & MT_RDMA0) || (mtstatus & MT_RDMA1)) && AudioCtrl != NULL && card->is_recording)
85 OUTBYTE(card->mtbase + MT_INTR_STATUS, mtstatus | MT_RDMA0 | MT_RDMA1); // clear interrupt
87 /*if (z == 0)
88 DEBUGPRINTF("MT_RDMA%d\n", mtstatus);
89 z++;
90 if (z == 50)
91 z = 0;*/
93 if( card->record_interrupt_enabled )
95 /* Invoke softint to convert and feed AHI with the new sample data */
97 if (card->recflip == 0) // just played buf 1
99 card->recflip = 1;
100 card->current_record_buffer = card->record_buffer;
101 card->current_record_buffer_32bit = card->record_buffer_32bit;
103 else // just played buf 2
105 card->recflip = 0;
106 card->current_record_buffer = (APTR) ((long) card->record_buffer + card->current_record_bytesize_32bit / 2);
107 card->current_record_buffer_32bit = (APTR) ((long) card->record_buffer_32bit + card->current_record_bytesize_32bit);
110 card->record_interrupt_enabled = FALSE;
111 CAUSE( &card->record_interrupt );
115 if( (mtstatus & MT_DMA_FIFO) && AudioCtrl != NULL )
117 unsigned char status = INBYTE(card->mtbase + MT_DMA_UNDERRUN);
119 //DEBUGPRINTF("FIFO %x\n", status);
120 WriteMask8(card, card->mtbase, MT_INTR_STATUS, MT_DMA_FIFO); // clear it
122 OUTBYTE(card->mtbase + MT_DMA_UNDERRUN, status);
123 WriteMask8(card, card->mtbase, MT_INTR_MASK, MT_DMA_FIFO);
127 OUTBYTE(card->mtbase + MT_INTR_STATUS, mtstatus); // clear interrupt
128 handled = 1;
132 return handled;
136 /******************************************************************************
137 ** Playback interrupt handler *************************************************
138 ******************************************************************************/
140 #ifdef __AMIGAOS4__
141 void
142 PlaybackInterrupt( struct ExceptionContext *pContext, struct ExecBase *SysBase, struct CardData* card )
143 #else
144 void
145 PlaybackInterrupt( struct CardData* card )
146 #endif
148 struct AHIAudioCtrlDrv* AudioCtrl = card->audioctrl;
150 if( card->mix_buffer != NULL && card->current_buffer != NULL && card->is_playing)
152 BOOL skip_mix;
154 WORD* src;
155 int i;
156 LONG* srclong, *dstlong, *spdif_dstlong, left, right;
157 int frames = card->current_frames;
159 skip_mix = CALLHOOK( AudioCtrl->ahiac_PreTimerFunc, (Object*) AudioCtrl, 0 );
160 CALLHOOK( AudioCtrl->ahiac_PlayerFunc, (Object*) AudioCtrl, NULL );
162 //DEBUGPRINTF("skip_mix = %d\n", skip_mix);
164 if( ! skip_mix )
166 CALLHOOK( AudioCtrl->ahiac_MixerFunc, (Object*) AudioCtrl, card->mix_buffer );
169 /* Now translate and transfer to the DMA buffer */
171 src = card->mix_buffer;
173 srclong = (LONG*) card->mix_buffer;
174 dstlong = (LONG*) card->current_buffer;
175 spdif_dstlong = card->spdif_out_current_buffer;
177 i = frames;
178 #if defined(__amigaos4__) || defined(__MORPHOS__)
179 if (AudioCtrl->ahiac_Flags & AHIACF_HIFI)
181 while( i > 0 )
183 left = ((*srclong & 0xFF000000) >> 24) | ((*srclong & 0x00FF0000) >> 8) | ((*srclong & 0x0000FF00) << 8);
184 *dstlong++ = *spdif_dstlong++ = left;
185 srclong++;
187 right = ((*srclong & 0xFF000000) >> 24) | ((*srclong & 0x00FF0000) >> 8) | ((*srclong & 0x0000FF00) << 8);
188 *dstlong++ = *spdif_dstlong++ = right;
189 srclong++;
191 *dstlong++ = left; // L & R of 2nd stereo channel that is unused
192 *dstlong++ = right;
194 --i;
197 else
199 while( i > 0 )
201 *dstlong++ = *spdif_dstlong++ = (*src & 0xFF00) >> 16; srclong++;
202 *dstlong++ = *spdif_dstlong++ = (*srclong & 0xFF000000) >> 16; srclong++;
204 *dstlong++ = 0; // L & R of 2nd stereo channel that is unused
205 *dstlong++ = 0;
206 --i;
209 #ifdef __AMIGAOS4__
210 IExec->CacheClearE(card->current_buffer, (ULONG) dstlong - (ULONG) card->current_buffer, CACRF_ClearD);
211 IExec->CacheClearE(card->spdif_out_current_buffer, (ULONG) spdif_dstlong - (ULONG) card->spdif_out_current_buffer, CACRF_ClearD);
212 #endif
213 #else
214 if (AudioCtrl->ahiac_Flags & AHIACF_HIFI)
216 while( i > 0 )
218 left = *srclong;
219 *dstlong++ = *spdif_dstlong++ = left;
220 srclong++;
222 right = *srclong;
223 *dstlong++ = *spdif_dstlong++ = right;
224 srclong++;
226 *dstlong++ = left; // L & R of 2nd stereo channel that is unused
227 *dstlong++ = right;
229 --i;
232 else
234 while( i > 0 )
236 *dstlong++ = *spdif_dstlong++ = (*src); src++;
237 *dstlong++ = *spdif_dstlong++ = (*src); src++;
239 *dstlong++ = 0; // L & R of 2nd stereo channel that is unused
240 *dstlong++ = 0;
241 --i;
244 #endif
246 CALLHOOK( AudioCtrl->ahiac_PostTimerFunc, (Object*) AudioCtrl, 0 );
249 card->playback_interrupt_enabled = TRUE;
253 /******************************************************************************
254 ** Record interrupt handler ***************************************************
255 ******************************************************************************/
257 #ifdef __AMIGAOS4__
258 void
259 RecordInterrupt( struct ExceptionContext *pContext, struct ExecBase *SysBase, struct CardData* card )
260 #else
261 void
262 RecordInterrupt( struct CardData* card )
263 #endif
265 struct AHIAudioCtrlDrv* AudioCtrl = card->audioctrl;
266 int i = 0, frames = card->current_record_bytesize_32bit / 4;
268 if (card->input_is_24bits)
270 struct AHIRecordMessage rm =
272 AHIST_S32S,
273 card->current_record_buffer_32bit,
274 RECORD_BUFFER_SAMPLES
277 #if defined(__amigaos4__) || defined(__MORPHOS__)
278 long *srclong = card->current_record_buffer_32bit;
280 while( i < frames )
282 *srclong = ((*srclong & 0x00FF0000) >> 8) | ((*srclong & 0x0000FF00) << 8) | ((*srclong & 0x000000FF) << 24);
284 ++i;
285 ++srclong;
287 #endif
289 CALLHOOK( AudioCtrl->ahiac_SamplerFunc, (Object*) AudioCtrl, &rm );
291 else
293 struct AHIRecordMessage rm =
295 AHIST_S16S,
296 card->current_record_buffer,
297 RECORD_BUFFER_SAMPLES
300 long *src = card->current_record_buffer_32bit;
301 WORD* dst = card->current_record_buffer;
303 #if defined(__amigaos4__) || defined(__MORPHOS__)
304 while( i < frames )
306 *dst = ( ( *src & 0x000000FF ) << 8 ) | ( ( *src & 0x0000FF00 ) >> 8 );
308 ++i;
309 ++src;
310 ++dst;
312 #else
313 while( i < frames )
315 *dst = (*src) >> 16;
317 ++i;
318 ++src;
319 ++dst;
321 #endif
323 CALLHOOK( AudioCtrl->ahiac_SamplerFunc, (Object*) AudioCtrl, &rm );
326 card->record_interrupt_enabled = TRUE;