2 Copyright © 2005-2013, Davy Wentzler. All rights reserved.
3 Copyright © 2010-2016, The AROS Development Team. All rights reserved.
9 #include <exec/memory.h>
10 #include <proto/expansion.h>
12 #include <proto/dos.h>
16 #include "interrupt.h"
19 #include "pci_wrapper.h"
25 #include <aros/debug.h>
26 #define DebugPrintF bug
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)
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 )
43 /* Global in Card.c */
44 extern const UWORD InputBits
[];
46 extern struct DOSIFace
*IDOS
;
47 extern struct PCIIFace
* IPCI
;
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;
67 INTGW(static, void, playbackinterrupt
, PlaybackInterrupt
);
68 INTGW(static, void, recordinterrupt
, RecordInterrupt
);
69 INTGW(static, ULONG
, cardinterrupt
, CardInterrupt
);
73 void MicroDelay(unsigned int val
)
75 replymp
= (struct MsgPort
*) CreateMsgPort();
78 DebugPrintF("Could not create the reply port!\n" );
82 TimerIO
= (struct timerequest
*) CreateIORequest( replymp
, sizeof( struct timerequest
) );
86 DebugPrintF( "Out of memory.\n" );
90 if( OpenDevice( "timer.device", UNIT_MICROHZ
, (struct IORequest
*) TimerIO
, 0) != 0 )
92 DebugPrintF( "Unable to open 'timer.device'.\n" );
97 TimerBase
= (struct Device
*) TimerIO
->tr_node
.io_Device
;
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
);
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
125 AllocDriverData( struct PCIDevice
* dev
,
126 struct DriverBase
* AHIsubBase
)
130 // FIXME: This should be non-cachable, DMA-able memory
131 dd
= AllocVec( sizeof( *dd
), MEMF_PUBLIC
| MEMF_CLEAR
);
135 Req( "Unable to allocate driver structure." );
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
;
145 dd
->interrupt
.is_Code
= (void(*)(void)) cardinterrupt
;
147 dd
->interrupt
.is_Code
= (void(*)(void)) CardInterrupt
;
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
;
155 dd
->playback_interrupt
.is_Code
= (APTR
)playbackinterrupt
;
157 dd
->playback_interrupt
.is_Code
= PlaybackInterrupt
;
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
;
165 dd
->record_interrupt
.is_Code
= (APTR
)recordinterrupt
;
167 dd
->record_interrupt
.is_Code
= RecordInterrupt
;
169 dd
->record_interrupt
.is_Data
= (APTR
) dd
;
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
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
;
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");
227 ahi_pci_add_intserver(&dd
->interrupt
, dd
->pci_dev
);
228 dd
->interrupt_added
= TRUE
;
230 dd
->card_initialized
= TRUE
;
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
);
244 /******************************************************************************
245 ** DriverData deallocation ****************************************************
246 ******************************************************************************/
248 // And this code used to be in _AHIsub_FreeAudio().
251 FreeDriverData( struct CardData
* dd
,
252 struct DriverBase
* AHIsubBase
)
256 if( dd
->pci_dev
!= NULL
)
258 if( dd
->card_initialized
)
263 if( dd
->pci_master_enabled
)
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
);
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
);
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...
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
,
321 MicroDelay( reset_delay
);
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
|
333 MicroDelay( reset_delay
);
335 //SB- Check primary codec...
336 unsigned long delay
= codec_timeout
;
339 if(inb_config( VIA_ACLINK_STAT
, via686b_audio
) & VIA_ACLINK_C00_READY
)
341 //DBG( "AC-Link reset ok." );
348 DBG( "AC-Link reset, primary codec not ready!" );
355 int card_init(struct CardData
*card
)
357 struct PCIDevice
*dev
= (struct PCIDevice
*) card
->pci_dev
;
359 unsigned short cod
, uval
;
360 unsigned char pval
, byt
;
365 struct PCIDevice
*via686b_ACPI
;
370 via686b_ACPI
= IPCI
->FindDeviceTags( FDT_VendorID
, 0x1106, FDT_DeviceID
, 0x3057,
374 via686b_ACPI
= ahi_pci_find_device(0x1106, 0x3057, NULL
);
377 if (via686b_ACPI
== NULL
) // try device 0x3058
380 via686b_ACPI
= IPCI
->FindDeviceTags( FDT_VendorID
, 0x1106, FDT_DeviceID
, 0x3058,
384 via686b_ACPI
= ahi_pci_find_device(0x1106, 0x3058, NULL
);
393 lock
= via686b_ACPI
->Lock( PCI_LOCK_SHARED
);
396 DBG( "couldn't lock the ACPI! Trying anyway..." );
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
);
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
428 if( ( inb_config( 0x42, via686b_ACPI
) & 0x40))
430 DBG( "powered up the 686b." );
438 ERR( "soft resume timed out!" );
442 DBG("VIA already powered up");
447 via686b_ACPI
->Unlock();
449 IPCI
->FreeDevice( via686b_ACPI
);
454 ERR( "couldn't find the ACPI!" );
458 //SB- Don't know if there's a codec yet?
459 // codec_write(card, 0x2, 0x8000);
460 // codec_write(card, 0x4, 0x8000);
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.
471 aclink
= ac97_reset(dev
);
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
);
485 //INF( "initialized AC'97 codec." );
489 ERR( "sorry, you don't seem to have the AC'97 codec!" );
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);
508 pci_write_config_byte(chip->pci, VIA_ACLINK_CTRL, 0x00);
511 pci_write_config_byte(chip->pci, VIA_ACLINK_CTRL, VIA_ACLINK_CTRL_INIT);
514 pval = inb_config(VIA_ACLINK_STAT, dd->pci_dev);
516 if (! (pval & VIA_ACLINK_C00_READY))
522 while (teller < 1000)
524 pval = inb_config(VIA_ACLINK_STAT, dd->pci_dev);
525 if (pval & VIA_ACLINK_C00_READY)
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
);
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!");
566 void card_cleanup(struct CardData
*card
)
572 /******************************************************************************
573 ** Misc. **********************************************************************
574 ******************************************************************************/
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
);
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
);
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
);
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
);
638 Linear2MixerGain( Fixed linear
,
641 static const Fixed gain
[ 33 ] =
680 while( linear
< gain
[ v
] )
687 *bits
= 0x8000; // Mute
691 *bits
= ( v
<< 8 ) | v
;
694 // KPrintF( "l2mg %08lx -> %08lx (%04lx)\n", linear, gain[ v ], *bits );
699 Linear2RecordGain( Fixed linear
,
702 static const Fixed gain
[ 17 ] =
725 while( linear
< gain
[ v
] )
732 *bits
= 0x8000; // Mute
736 *bits
= ( ( 15 - v
) << 8 ) | ( 15 - v
);
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
)
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
);
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
;
783 void pci_free_consistent(void* addr
)
790 static ULONG
ResetHandler(struct ExceptionContext
*ctx
, struct ExecBase
*pExecBase
, struct CardData
*card
)
792 static ULONG
ResetHandler(struct CardData
*card
)
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
);
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;
814 handler
->is_Node
.ln_Type
= NT_EXTINTERRUPT
;
816 handler
->is_Node
.ln_Type
= NT_INTERRUPT
;
818 handler
->is_Node
.ln_Name
= "VIA-AC97 reset handler";
820 card
->reset_handler_added
= AddResetCallback(handler
);