Importing CMI8738-20072011
[AROS.git] / workbench / devs / AHI / Drivers / CMI8738 / interrupt.c
blob0547fa1c28be1e1320b9cdd440607e2167969950
1 /*
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.
12 #include <config.h>
14 #undef __USE_INLINE__
15 #include <proto/expansion.h>
16 #include <libraries/ahi_sub.h>
17 #include <proto/exec.h>
18 #include <stddef.h>
19 #include "library.h"
20 #include "regs.h"
21 #include "interrupt.h"
22 #include "misc.h"
24 #define min(a,b) ((a)<(b)?(a):(b))
26 int z = 0;
29 //struct tester t[10];
32 /******************************************************************************
33 ** Hardware interrupt handler *************************************************
34 ******************************************************************************/
37 LONG
38 CardInterrupt( struct ExceptionContext *pContext, struct ExecBase *SysBase, struct CardData* card )
40 struct AHIAudioCtrlDrv* AudioCtrl = card->audioctrl;
41 struct DriverBase* AHIsubBase = (struct DriverBase*) card->ahisubbase;
42 struct PCIDevice *dev = (struct PCIDevice * ) card->pci_dev;
44 ULONG intreq;
45 LONG handled = 0;
47 while ( (( intreq = ( dev->InLong(card->iobase + CMPCI_REG_INTR_STATUS ) ) ) & CMPCI_REG_ANY_INTR )!= 0 )
49 //IExec->DebugPrintF("INT %lx\n", intreq);
50 if( intreq & CMPCI_REG_CH0_INTR && AudioCtrl != NULL )
52 unsigned long diff = dev->InLong(card->iobase + CMPCI_REG_DMA0_BASE) - (unsigned long) card->playback_buffer_phys;
54 ClearMask(dev, card, CMPCI_REG_INTR_CTRL, CMPCI_REG_CH0_INTR_ENABLE);
57 z++;
58 if (z < 10)
60 t[z].diff = diff;
61 t[z].flip = card->flip;
62 t[z].oldflip = card->oldflip;
63 }*/
65 /*if ((diff > 50 && diff < card->current_bytesize) ||
66 (diff > card->current_bytesize + 50 && diff < 2 * card->current_bytesize))
67 IExec->DebugPrintF("Delayed IRQ %lu %lu\n", diff % card->current_bytesize, card->current_bytesize);*/
70 if (diff >= card->current_bytesize) //card->flip == 0) // just played buf 1
72 if (card->flip == 1)
73 IExec->DebugPrintF("A:Missed IRQ! diff = %lu\n", diff);
75 card->flip = 1;
76 card->current_buffer = card->playback_buffer;
78 else // just played buf 2
80 if (card->flip == 0)
81 IExec->DebugPrintF("B:Missed IRQ! diff = %lu\n", diff);
83 card->flip = 0;
84 card->current_buffer = (APTR) ((long) card->playback_buffer + card->current_bytesize);
87 /*z++;
88 if (z == 25)
89 z = 0;*/
91 card->playback_interrupt_enabled = FALSE;
92 IExec->Cause( &card->playback_interrupt );
95 if( intreq & CMPCI_REG_CH1_INTR && AudioCtrl != NULL )
97 ClearMask(dev, card, CMPCI_REG_INTR_CTRL, CMPCI_REG_CH1_INTR_ENABLE);
99 /*if (z == 0)
100 IExec->DebugPrintF("rec\n");*/
101 z++;
102 /*if (z == 30)
103 z = 0;*/
105 if( card->record_interrupt_enabled )
107 /* Invoke softint to convert and feed AHI with the new sample data */
109 if (card->recflip == 0) // just played buf 1
111 card->recflip = 1;
112 card->current_record_buffer = card->record_buffer;
114 else // just played buf 2
116 card->recflip = 0;
117 card->current_record_buffer = (APTR) ((long) card->record_buffer + card->current_record_bytesize);
120 card->record_interrupt_enabled = FALSE;
121 IExec->Cause( &card->record_interrupt );
125 handled = 1;
129 return handled;
133 /******************************************************************************
134 ** Playback interrupt handler *************************************************
135 ******************************************************************************/
137 void
138 PlaybackInterrupt( struct ExceptionContext *pContext, struct ExecBase *SysBase, struct CardData* card )
140 struct AHIAudioCtrlDrv* AudioCtrl = card->audioctrl;
141 struct DriverBase* AHIsubBase = (struct DriverBase*) card->ahisubbase;
142 struct PCIDevice *dev = (struct PCIDevice * ) card->pci_dev;
144 if( card->mix_buffer != NULL && card->current_buffer != NULL )
146 BOOL skip_mix;
148 WORD* src;
149 WORD* dst;
150 size_t skip;
151 size_t samples;
152 int i;
154 skip_mix = IUtility->CallHookPkt( AudioCtrl->ahiac_PreTimerFunc, (Object*) AudioCtrl, 0 );
155 IUtility->CallHookPkt( AudioCtrl->ahiac_PlayerFunc, (Object*) AudioCtrl, NULL );
157 //IExec->DebugPrintF("skip_mix = %d\n", skip_mix);
159 if( ! skip_mix )
161 IUtility->CallHookPkt( AudioCtrl->ahiac_MixerFunc, (Object*) AudioCtrl, card->mix_buffer );
164 /* Now translate and transfer to the DMA buffer */
167 skip = ( AudioCtrl->ahiac_Flags & AHIACF_HIFI ) ? 2 : 1;
168 samples = card->current_bytesize >> 1;
170 src = card->mix_buffer;
171 dst = card->current_buffer;
173 i = samples;
175 while( i > 0 )
177 *dst = ( ( *src & 0xff ) << 8 ) | ( ( *src & 0xff00 ) >> 8 );
179 src += skip;
180 dst += 1;
182 --i;
185 IExec->CacheClearE( card->current_buffer, (ULONG) dst - (ULONG) card->current_buffer, CACRF_ClearD );
187 IUtility->CallHookPkt( AudioCtrl->ahiac_PostTimerFunc, (Object*) AudioCtrl, 0 );
190 WriteMask(dev, card, CMPCI_REG_INTR_CTRL, CMPCI_REG_CH0_INTR_ENABLE);
191 card->playback_interrupt_enabled = TRUE;
195 /******************************************************************************
196 ** Record interrupt handler ***************************************************
197 ******************************************************************************/
199 void
200 RecordInterrupt( struct ExceptionContext *pContext, struct ExecBase *SysBase, struct CardData* card )
202 struct AHIAudioCtrlDrv* AudioCtrl = card->audioctrl;
203 struct DriverBase* AHIsubBase = (struct DriverBase*) card->ahisubbase;
204 struct PCIDevice *dev = (struct PCIDevice * ) card->pci_dev;
206 struct AHIRecordMessage rm =
208 AHIST_S16S,
209 card->current_record_buffer,
210 RECORD_BUFFER_SAMPLES
213 int i = 0, shorts = card->current_record_bytesize / 2;
214 WORD* ptr = (WORD *) card->current_record_buffer;
217 IExec->CacheClearE( card->current_record_buffer, card->current_record_bytesize, CACRF_ClearD);
219 while( i < shorts )
221 *ptr = ( ( *ptr & 0xff ) << 8 ) | ( ( *ptr & 0xff00 ) >> 8 );
223 ++i;
224 ++ptr;
227 IUtility->CallHookPkt( AudioCtrl->ahiac_SamplerFunc, (Object*) AudioCtrl, &rm );
229 IExec->CacheClearE( card->current_record_buffer, card->current_record_bytesize, CACRF_ClearD);
232 WriteMask(dev, card, CMPCI_REG_INTR_CTRL, CMPCI_REG_CH1_INTR_ENABLE);
233 card->record_interrupt_enabled = TRUE;