revert between 56095 -> 55830 in arch
[AROS.git] / workbench / devs / AHI / Drivers / VIA-AC97 / misc.c
blob466e38b379e91a626c3683474fda67e69d574d2a
1 /*
2 Copyright © 2005-2013, Davy Wentzler. All rights reserved.
3 Copyright © 2010-2016, The AROS Development Team. All rights reserved.
4 $Id$
5 */
7 #include <config.h>
9 #include <exec/memory.h>
10 #include <proto/expansion.h>
12 #include <proto/dos.h>
14 #include "library.h"
15 #include "regs.h"
16 #include "interrupt.h"
17 #include "hwaccess.h"
18 #include "misc.h"
19 #include "pci_wrapper.h"
21 //#define DEBUG 1
23 #ifdef __AROS__
24 #include <asm/io.h>
25 #include <aros/debug.h>
26 #define DebugPrintF bug
27 #endif
29 //SB- Some debug/err/info output stuff.
31 #define ERR(a) DebugPrintF("[VIA-AC97] Error: " a "\n")
32 #define INF(a) DebugPrintF("[VIA-AC97] Info: " a "\n")
33 #define INFL(a,b) DebugPrintF("[VIA-AC97] Info: " a " (0x%08lx).\n", (long)b)
35 #ifdef DEBUG
36 #define DBG(a) DebugPrintF( "[VIA-AC97] Debug: " a "\n" )
37 #define DBGL(a,b) DebugPrintF( "[VIA-AC97] Debug: " a " (0x%08lx).\n", (long)b )
38 #else
39 #define DBG(a)
40 #define DBGL(a,b)
41 #endif
43 /* Global in Card.c */
44 extern const UWORD InputBits[];
45 #ifdef __amigaos4__
46 extern struct DOSIFace *IDOS;
47 extern struct PCIIFace* IPCI;
48 #endif
50 /* Public functions in main.c */
51 int card_init(struct CardData *card);
52 void card_cleanup(struct CardData *card);
55 struct Device *TimerBase = NULL;
56 struct timerequest *TimerIO = NULL;
57 struct MsgPort *replymp = NULL;
58 void AddResetHandler(struct CardData *card);
60 static const unsigned long IO_PWR_MANAGEMENT = 0xdd00;
61 //static const unsigned long IO_HW_MONITOR = 0xec00;
62 static const unsigned long IO_SGD = 0xdc00;
63 static const unsigned long IO_FM = 0xe000;
64 static const unsigned long IO_MIDI = 0xe400;
66 #ifdef __AROS__
67 INTGW(static, void, playbackinterrupt, PlaybackInterrupt);
68 INTGW(static, void, recordinterrupt, RecordInterrupt);
69 INTGW(static, ULONG, cardinterrupt, CardInterrupt);
70 #endif
73 void MicroDelay(unsigned int val)
75 replymp = (struct MsgPort *) CreateMsgPort();
76 if( !replymp )
78 DebugPrintF("Could not create the reply port!\n" );
79 return;
82 TimerIO = (struct timerequest *) CreateIORequest( replymp, sizeof( struct timerequest) );
84 if( TimerIO == NULL)
86 DebugPrintF( "Out of memory.\n" );
87 return;
90 if( OpenDevice( "timer.device", UNIT_MICROHZ, (struct IORequest *) TimerIO, 0) != 0 )
92 DebugPrintF( "Unable to open 'timer.device'.\n" );
93 return;
95 else
97 TimerBase = (struct Device *) TimerIO->tr_node.io_Device;
100 if (TimerIO)
102 TimerIO->tr_node.io_Command = TR_ADDREQUEST; /* Add a request. */
103 TimerIO->tr_time.tv_secs = 0; /* 0 seconds. */
104 TimerIO->tr_time.tv_micro = val; /* 'val' micro seconds. */
105 DoIO( (struct IORequest *) TimerIO );
106 CloseDevice( (struct IORequest *) TimerIO );
107 DeleteIORequest( (struct IORequest *) TimerIO);
108 TimerIO = NULL;
111 if( replymp )
112 DeleteMsgPort(replymp);
116 /******************************************************************************
117 ** DriverData allocation ******************************************************
118 ******************************************************************************/
120 // This code used to be in _AHIsub_AllocAudio(), but since we're now
121 // handling CAMD support too, it needs to be done at driver loading
122 // time.
124 struct CardData*
125 AllocDriverData( struct PCIDevice * dev,
126 struct DriverBase* AHIsubBase )
128 struct CardData* dd;
130 // FIXME: This should be non-cachable, DMA-able memory
131 dd = AllocVec( sizeof( *dd ), MEMF_PUBLIC | MEMF_CLEAR );
133 if( dd == NULL )
135 Req( "Unable to allocate driver structure." );
136 return NULL;
139 dd->ahisubbase = AHIsubBase;
141 dd->interrupt.is_Node.ln_Type = IRQTYPE;
142 dd->interrupt.is_Node.ln_Pri = 0;
143 dd->interrupt.is_Node.ln_Name = (STRPTR) LibName;
144 #ifdef __AROS__
145 dd->interrupt.is_Code = (void(*)(void)) cardinterrupt;
146 #else
147 dd->interrupt.is_Code = (void(*)(void)) CardInterrupt;
148 #endif
149 dd->interrupt.is_Data = (APTR) dd;
151 dd->playback_interrupt.is_Node.ln_Type = IRQTYPE;
152 dd->playback_interrupt.is_Node.ln_Pri = 0;
153 dd->playback_interrupt.is_Node.ln_Name = (STRPTR) LibName;
154 #ifdef __AROS__
155 dd->playback_interrupt.is_Code = (APTR)playbackinterrupt;
156 #else
157 dd->playback_interrupt.is_Code = PlaybackInterrupt;
158 #endif
159 dd->playback_interrupt.is_Data = (APTR) dd;
161 dd->record_interrupt.is_Node.ln_Type = IRQTYPE;
162 dd->record_interrupt.is_Node.ln_Pri = 0;
163 dd->record_interrupt.is_Node.ln_Name = (STRPTR) LibName;
164 #ifdef __AROS__
165 dd->record_interrupt.is_Code = (APTR)recordinterrupt;
166 #else
167 dd->record_interrupt.is_Code = RecordInterrupt;
168 #endif
169 dd->record_interrupt.is_Data = (APTR) dd;
171 dd->pci_dev = dev;
173 outw_config(PCI_COMMAND, 0x00, dd->pci_dev);
174 //dev->WriteConfigLong( PCI_BASE_ADDRESS_0, 0xdc00 );
176 //SB- Configure IO, if required. Force IO into 16bit/ISA address space, since it
177 // apparently won't work in 32bit address range. Really ought to check this in
178 // Linux sometime...
179 unsigned long tula = ( inl_config(PCI_BASE_ADDRESS_0, dd->pci_dev) & 0xfffffffc );
180 if( ( tula == 0 ) || ( tula & 0xffff0000 ) )
182 outl_config(PCI_BASE_ADDRESS_0, IO_SGD, dd->pci_dev);
183 DBGL( "configured audio SGD IO base", IO_SGD );
186 tula = ( inl_config(PCI_BASE_ADDRESS_1, dd->pci_dev) & 0xfffffffc );
187 if( ( tula == 0 ) || ( tula & 0xffff0000 ) )
189 outl_config(PCI_BASE_ADDRESS_1, IO_FM, dd->pci_dev);
190 //DBGL( "configured audio FM IO base", IO_FM );
193 tula = ( inl_config(PCI_BASE_ADDRESS_2, dd->pci_dev) & 0xfffffffc );
194 if( ( tula == 0 ) || ( tula & 0xffff0000 ) )
196 outl_config(PCI_BASE_ADDRESS_2, IO_MIDI, dd->pci_dev);
197 //DBGL( "configured audio MIDI IO base", IO_MIDI );
200 outw_config(PCI_COMMAND, PCI_COMMAND_IO, dd->pci_dev);
202 dd->pci_master_enabled = TRUE;
204 dd->iobase = inl_config(PCI_BASE_ADDRESS_0, dd->pci_dev) & 0xfffffffe;
206 dd->length = ~( ahi_pci_get_base_size(0, dd->pci_dev) & PCI_BASE_ADDRESS_IO_MASK );
207 dd->irq = ahi_pci_get_irq(dev);
208 dd->chiprev = inb_config(PCI_REVISION_ID, dev);
209 dd->model = inw_config(PCI_SUBSYSTEM_ID, dev);
211 dd->table.area = NULL;
212 dd->table.addr = NULL;
213 dd->table.bytes = 0;
214 dd->play_idx_table = NULL;
215 dd->rec_idx_table = NULL;
217 /* Initialize chip */
218 if( card_init( dd ) < 0 )
220 DebugPrintF("Unable to initialize Card subsystem.\n");
222 FreeVec(dd);
223 return NULL;
227 ahi_pci_add_intserver(&dd->interrupt, dd->pci_dev);
228 dd->interrupt_added = TRUE;
230 dd->card_initialized = TRUE;
231 dd->input = 0;
232 dd->output = 0;
233 dd->monitor_volume = Linear2MixerGain( 0x10000, &dd->monitor_volume_bits );
234 dd->input_gain = Linear2RecordGain( 0x10000, &dd->input_gain_bits );
235 dd->output_volume = Linear2MixerGain( 0x10000, &dd->output_volume_bits );
236 SaveMixerState(dd);
238 AddResetHandler(dd);
240 return dd;
244 /******************************************************************************
245 ** DriverData deallocation ****************************************************
246 ******************************************************************************/
248 // And this code used to be in _AHIsub_FreeAudio().
250 void
251 FreeDriverData( struct CardData* dd,
252 struct DriverBase* AHIsubBase )
254 if( dd != NULL )
256 if( dd->pci_dev != NULL )
258 if( dd->card_initialized )
260 card_cleanup( dd );
263 if( dd->pci_master_enabled )
265 UWORD cmd;
267 cmd = inw_config(PCI_COMMAND, dd->pci_dev);
268 cmd &= ~( PCI_COMMAND_IO | PCI_COMMAND_MASTER );
269 outw_config(PCI_COMMAND, cmd, dd->pci_dev);
273 if( dd->reset_handler_added )
275 RemResetCallback(&dd->reset_handler);
278 if( dd->interrupt_added )
280 ahi_pci_rem_intserver(&dd->interrupt, dd->pci_dev);
283 FreeVec( dd );
288 void channel_reset(struct CardData *card)
290 pci_outb(VIA_REG_CTRL_TERMINATE /*| VIA_REG_CTRL_RESET*/, VIA_REG_OFFSET_CONTROL, card);
291 pci_inb(VIA_REG_OFFSET_CONTROL, card);
292 udelay(50);
293 /* disable interrupts */
294 pci_outb(0x00, VIA_REG_OFFSET_CONTROL, card);
295 /* clear interrupts */
296 pci_outb(0x03, VIA_REG_OFFSET_STATUS, card);
297 pci_outb(0x00, VIA_REG_OFFSET_TYPE, card); /* for via686 */
298 // pci_outl(0, VIA_REG_OFFSET_CURR_PTR, card);
301 //reset/init ac97 codec. Returns false if the primary codec isn't found/ready.
302 BOOL ac97_reset( struct PCIDevice *via686b_audio)
304 static const unsigned long reset_delay = 100; //link operation delay, should be some uS..
305 static const unsigned long codec_timeout = 50; //codec ready timeout, about half a second...
307 //cold reset..
308 //SB- Set the link to a known initial configuration.
309 //SB- Note: The 'standard' ***x reset code is quite similar to this, except it
310 // de-asserts SYNC at this point, possibly in case the link/codec is
311 // in low power mode. We don't, because if we do, the dreaded half-
312 // rate problem occurs, with ~100% reliability (..interesting).
313 // It is a bit of a worry that the 'standard' reset code fails, but
314 // perhaps it is simply because we have a completely untouched link,
315 // whereas on any 686 based PC, the link was probably confugured
316 // already in the BIOS.
318 outb_config(VIA_ACLINK_CTRL,
319 VIA_ACLINK_CTRL_ENABLE | VIA_ACLINK_CTRL_RESET,
320 via686b_audio);
321 MicroDelay( reset_delay );
323 //SB- Assert reset.
324 outb_config(VIA_ACLINK_CTRL, VIA_ACLINK_CTRL_ENABLE, via686b_audio);
325 MicroDelay( reset_delay );
327 //SB- De-assert reset, enable VRA/PCM etc.
328 outb_config( VIA_ACLINK_CTRL, VIA_ACLINK_CTRL_ENABLE |
329 VIA_ACLINK_CTRL_RESET |
330 VIA_ACLINK_CTRL_VRA |
331 VIA_ACLINK_CTRL_PCM,
332 via686b_audio);
333 MicroDelay( reset_delay );
335 //SB- Check primary codec...
336 unsigned long delay = codec_timeout;
337 while( delay-- )
339 if(inb_config( VIA_ACLINK_STAT, via686b_audio) & VIA_ACLINK_C00_READY)
341 //DBG( "AC-Link reset ok." );
342 return TRUE;
345 MicroDelay( 10000 );
348 DBG( "AC-Link reset, primary codec not ready!" );
349 return FALSE;
355 int card_init(struct CardData *card)
357 struct PCIDevice *dev = (struct PCIDevice *) card->pci_dev;
358 #if 0
359 unsigned short cod, uval;
360 unsigned char pval, byt;
361 long *ptr;
362 int teller = 0;
363 #endif
364 ULONG val;
365 struct PCIDevice *via686b_ACPI;
366 BOOL aclink = FALSE;
369 #ifdef __amigaos4__
370 via686b_ACPI = IPCI->FindDeviceTags( FDT_VendorID, 0x1106, FDT_DeviceID, 0x3057,
371 FDT_Index, 0x00,
372 TAG_DONE );
373 #else
374 via686b_ACPI = ahi_pci_find_device(0x1106, 0x3057, NULL);
375 #endif
377 if (via686b_ACPI == NULL) // try device 0x3058
379 #ifdef __amigaos4__
380 via686b_ACPI = IPCI->FindDeviceTags( FDT_VendorID, 0x1106, FDT_DeviceID, 0x3058,
381 FDT_Index, 0x00,
382 TAG_DONE );
383 #else
384 via686b_ACPI = ahi_pci_find_device(0x1106, 0x3058, NULL);
385 #endif
388 if (via686b_ACPI)
390 #ifdef __amigaos4__
391 BOOL lock;
393 lock = via686b_ACPI->Lock( PCI_LOCK_SHARED );
394 if (lock == FALSE)
396 DBG( "couldn't lock the ACPI! Trying anyway..." );
398 #endif
400 //SB- Configure power management, if it isn't already.
401 if( !( inl_config(0x48, via686b_ACPI) & 0xfffffffe ) )
403 outl_config(0x48, IO_PWR_MANAGEMENT, via686b_ACPI);
404 DBGL( "configured power management IO", IO_PWR_MANAGEMENT );
406 else
408 DBG("Power management IO already configured");
411 //SB- Enable IO (preserve other bits, but note that technically speaking
412 // we should also be clreaing PSON gating here (it's already cleared))
413 outb_config( 0x41, (inb_config(0x41, via686b_ACPI) | 0x80), via686b_ACPI);
415 //SB- Power up the 686b, if it isn't already.
416 if( !( inb_config(0x42, via686b_ACPI) & 0x40 ) )
418 //Cause a soft resume event...
419 outb(inb(IO_PWR_MANAGEMENT + 0x05) | 0x80, IO_PWR_MANAGEMENT + 0x05 );
421 //Busy loop until the soft resume completes.
422 //We have a bail out counter, but no idea how long we should wait really.
423 //..1/10th of a second wasn't long enough
424 unsigned long delay = 25; //1/2 a second, or so
426 while( --delay )
428 if( ( inb_config( 0x42, via686b_ACPI) & 0x40))
430 DBG( "powered up the 686b." );
431 break; //SUSC# state
434 Delay(1);
437 if( delay == 0 )
438 ERR( "soft resume timed out!" );
440 else
442 DBG("VIA already powered up");
445 #ifdef __amigaos4__
446 if (lock)
447 via686b_ACPI->Unlock();
449 IPCI->FreeDevice( via686b_ACPI );
450 #endif
452 else
454 ERR( "couldn't find the ACPI!" );
455 return -1;
458 //SB- Don't know if there's a codec yet?
459 // codec_write(card, 0x2, 0x8000);
460 // codec_write(card, 0x4, 0x8000);
462 //SB- Check codec..
463 aclink = ( inb_config(VIA_ACLINK_STAT, dev) & VIA_ACLINK_C00_READY );
465 //SB- If no codec, reset.
466 //SB- Note: This is a possible source of trouble. It might be safer to reset
467 // every time. Only reason not to is 'pop' avoidance on soft reboot
468 // and in case UBoot did the reset.
469 if( !aclink )
471 aclink = ac97_reset(dev);
473 else
475 //SB- Make sure VRA/PCM are enabled if we didn't use our own reset code.
477 outb_config(VIA_ACLINK_CTRL, VIA_ACLINK_CTRL_ENABLE |\
478 VIA_ACLINK_CTRL_RESET |\
479 VIA_ACLINK_CTRL_VRA |\
480 VIA_ACLINK_CTRL_PCM, dev);
483 if( aclink )
485 //INF( "initialized AC'97 codec." );
487 else
489 ERR( "sorry, you don't seem to have the AC'97 codec!" );
490 return -1;
494 Delay( 1 );
497 pval = inb_config(VIA_ACLINK_STAT, dev);
499 if (! (pval & VIA_ACLINK_C00_READY))
501 DebugPrintF("WHY?\n");
502 pci_write_config_byte(chip->pci, VIA_ACLINK_CTRL,
503 VIA_ACLINK_CTRL_ENABLE |
504 VIA_ACLINK_CTRL_RESET |
505 VIA_ACLINK_CTRL_SYNC);
506 udelay(100);
508 pci_write_config_byte(chip->pci, VIA_ACLINK_CTRL, 0x00);
509 udelay(100);
511 pci_write_config_byte(chip->pci, VIA_ACLINK_CTRL, VIA_ACLINK_CTRL_INIT);
512 udelay(100);
514 pval = inb_config(VIA_ACLINK_STAT, dd->pci_dev);
516 if (! (pval & VIA_ACLINK_C00_READY))
518 return -1;
522 while (teller < 1000)
524 pval = inb_config(VIA_ACLINK_STAT, dd->pci_dev);
525 if (pval & VIA_ACLINK_C00_READY)
526 break;
528 udelay(20);
529 teller++;
533 if ((val = pci_inl(VIA_CODEC_CMD, card)) & VIA_REG_AC97_BUSY)
534 snd_printk("AC97 codec is not ready!\n");
536 outb_config(VIA_FM_NMI_CTRL, 0, card->pci_dev);
537 pci_outl(0, VIA_REG_GPI_INTR, card);
539 channel_reset(card);
541 codec_write(card, AC97_MASTER_VOL_STEREO, 0x0000 ); // no attenuation
542 codec_write(card, AC97_AUXOUT_VOL, 0x8000 ); // volume of the rear output
543 codec_write(card, AC97_MASTER_VOL_MONO, 0x8000 );
544 codec_write(card, AC97_MASTER_TONE, 0x0f0f ); // bass/treble control (if present)
545 codec_write(card, AC97_PCBEEP_VOL, 0x8000 ); // PC beep internal speaker?
547 codec_write(card, AC97_RECORD_SELECT, 0);
548 codec_write(card, AC97_RECORD_GAIN, 0x0000 ); // 0 dB gain
551 // Analog mixer input gain registers
552 codec_write(card, AC97_PHONE_VOL, AC97_MUTE | 0x0008 );
553 codec_write(card, AC97_MIC_VOL, AC97_MUTE | 0x0048 ); // 10 dB boost
554 codec_write(card, AC97_LINEIN_VOL, AC97_MUTE | 0x0808 );
555 codec_write(card, AC97_CD_VOL, 0x0808 );
556 codec_write(card, AC97_VIDEO_VOL, AC97_MUTE | 0x0808 );
557 codec_write(card, AC97_AUX_VOL, 0x0808 );
558 codec_write(card, AC97_PCMOUT_VOL, 0x0808 );
560 DBG("card_init() was a success!");
562 return 0;
566 void card_cleanup(struct CardData *card)
572 /******************************************************************************
573 ** Misc. **********************************************************************
574 ******************************************************************************/
576 void
577 SaveMixerState( struct CardData* dd )
579 dd->ac97_mic = codec_read( dd, AC97_MIC_VOL );
580 dd->ac97_cd = codec_read( dd, AC97_CD_VOL );
581 dd->ac97_video = codec_read( dd, AC97_VIDEO_VOL );
582 dd->ac97_aux = codec_read( dd, AC97_AUX_VOL );
583 dd->ac97_linein = codec_read( dd, AC97_LINEIN_VOL );
584 dd->ac97_phone = codec_read( dd, AC97_PHONE_VOL );
588 void
589 RestoreMixerState( struct CardData* dd )
591 codec_write(dd, AC97_MIC_VOL, dd->ac97_mic );
592 codec_write(dd, AC97_CD_VOL, dd->ac97_cd );
593 codec_write(dd, AC97_VIDEO_VOL, dd->ac97_video );
594 codec_write(dd, AC97_AUX_VOL, dd->ac97_aux );
595 codec_write(dd, AC97_LINEIN_VOL, dd->ac97_linein );
596 codec_write(dd, AC97_PHONE_VOL, dd->ac97_phone );
599 void
600 UpdateMonitorMixer( struct CardData* dd )
602 int i = InputBits[ dd->input ];
603 UWORD m = dd->monitor_volume_bits & 0x801f;
604 UWORD s = dd->monitor_volume_bits;
605 UWORD mm = AC97_MUTE | 0x0008;
606 UWORD sm = AC97_MUTE | 0x0808;
608 if( i == AC97_RECMUX_STEREO_MIX ||
609 i == AC97_RECMUX_MONO_MIX )
611 // Use the original mixer settings
612 RestoreMixerState( dd );
614 else
616 codec_write(dd, AC97_MIC_VOL,
617 i == AC97_RECMUX_MIC ? m : mm );
619 codec_write(dd, AC97_CD_VOL,
620 i == AC97_RECMUX_CD ? s : sm );
622 codec_write(dd, AC97_VIDEO_VOL,
623 i == AC97_RECMUX_VIDEO ? s : sm );
625 codec_write(dd, AC97_AUX_VOL,
626 i == AC97_RECMUX_AUX ? s : sm );
628 codec_write(dd, AC97_LINEIN_VOL,
629 i == AC97_RECMUX_LINE ? s : sm );
631 codec_write(dd, AC97_PHONE_VOL,
632 i == AC97_RECMUX_PHONE ? m : mm );
637 Fixed
638 Linear2MixerGain( Fixed linear,
639 UWORD* bits )
641 static const Fixed gain[ 33 ] =
643 260904, // +12.0 dB
644 219523, // +10.5 dB
645 184706, // +9.0 dB
646 155410, // +7.5 dB
647 130762, // +6.0 dB
648 110022, // +4.5 dB
649 92572, // +3.0 dB
650 77890, // +1.5 dB
651 65536, // ±0.0 dB
652 55142, // -1.5 dB
653 46396, // -3.0 dB
654 39037, // -4.5 dB
655 32846, // -6.0 dB
656 27636, // -7.5 dB
657 23253, // -9.0 dB
658 19565, // -10.5 dB
659 16462, // -12.0 dB
660 13851, // -13.5 dB
661 11654, // -15.0 dB
662 9806, // -16.5 dB
663 8250, // -18.0 dB
664 6942, // -19.5 dB
665 5841, // -21.0 dB
666 4915, // -22.5 dB
667 4135, // -24.0 dB
668 3479, // -25.5 dB
669 2927, // -27.0 dB
670 2463, // -28.5 dB
671 2072, // -30.0 dB
672 1744, // -31.5 dB
673 1467, // -33.0 dB
674 1234, // -34.5 dB
675 0 // -oo dB
678 int v = 0;
680 while( linear < gain[ v ] )
682 ++v;
685 if( v == 32 )
687 *bits = 0x8000; // Mute
689 else
691 *bits = ( v << 8 ) | v;
694 // KPrintF( "l2mg %08lx -> %08lx (%04lx)\n", linear, gain[ v ], *bits );
695 return gain[ v ];
698 Fixed
699 Linear2RecordGain( Fixed linear,
700 UWORD* bits )
702 static const Fixed gain[ 17 ] =
704 873937, // +22.5 dB
705 735326, // +21.0 dB
706 618700, // +19.5 dB
707 520571, // +18.0 dB
708 438006, // +16.5 dB
709 368536, // +15.0 dB
710 310084, // +13.5 dB
711 260904, // +12.0 dB
712 219523, // +10.5 dB
713 184706, // +9.0 dB
714 155410, // +7.5 dB
715 130762, // +6.0 dB
716 110022, // +4.5 dB
717 92572, // +3.0 dB
718 77890, // +1.5 dB
719 65536, // ±0.0 dB
720 0 // -oo dB
723 int v = 0;
725 while( linear < gain[ v ] )
727 ++v;
730 if( v == 16 )
732 *bits = 0x8000; // Mute
734 else
736 *bits = ( ( 15 - v ) << 8 ) | ( 15 - v );
739 return gain[ v ];
743 ULONG
744 SamplerateToLinearPitch( ULONG samplingrate )
746 samplingrate = (samplingrate << 8) / 375;
747 return (samplingrate >> 1) + (samplingrate & 1);
751 #define CACHELINE_SIZE 32
753 void *pci_alloc_consistent(size_t size, APTR *NonAlignedAddress)
755 void* address;
756 unsigned long a;
758 #ifdef __amigaos4__
759 if (OpenResource("newmemory.resource"))
761 address = AllocVecTags(size, AVT_Type, MEMF_SHARED, AVT_Contiguous, TRUE, AVT_Lock, TRUE,
762 AVT_PhysicalAlignment, 32, AVT_Clear, 0, TAG_DONE);
764 else
765 #endif
767 address = AllocVec( size + CACHELINE_SIZE, MEMF_PUBLIC | MEMF_CLEAR);
769 if( address != NULL )
771 a = (unsigned long) address;
772 a = (a + CACHELINE_SIZE - 1) & ~(CACHELINE_SIZE - 1);
773 address = (void *) a;
777 *NonAlignedAddress = address;
779 return address;
783 void pci_free_consistent(void* addr)
785 FreeVec( addr );
789 #ifdef __amigaos4__
790 static ULONG ResetHandler(struct ExceptionContext *ctx, struct ExecBase *pExecBase, struct CardData *card)
791 #else
792 static ULONG ResetHandler(struct CardData *card)
793 #endif
795 unsigned char val = VIA_REG_CTRL_TERMINATE;
797 pci_outb(val, VIA_REG_OFFSET_CONTROL, card);
798 pci_outb(val, VIA_REG_OFFSET_CONTROL + RECORD, card);
800 channel_reset(card);
802 return 0UL;
806 void AddResetHandler(struct CardData *card)
808 struct Interrupt *handler = &card->reset_handler;
810 handler->is_Code = (APTR)ResetHandler;
811 handler->is_Data = (APTR) card;
812 handler->is_Node.ln_Pri = 0;
813 #ifdef __amigaos4__
814 handler->is_Node.ln_Type = NT_EXTINTERRUPT;
815 #else
816 handler->is_Node.ln_Type = NT_INTERRUPT;
817 #endif
818 handler->is_Node.ln_Name = "VIA-AC97 reset handler";
820 card->reset_handler_added = AddResetCallback(handler);