2 Copyright © 2005-2013, Davy Wentzler. All rights reserved.
3 Copyright © 2010-2014, 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
)
128 struct CardBase
* CardBase
= (struct CardBase
*) AHIsubBase
;
134 // FIXME: This should be non-cachable, DMA-able memory
135 dd
= AllocVec( sizeof( *dd
), MEMF_PUBLIC
| MEMF_CLEAR
);
139 Req( "Unable to allocate driver structure." );
143 dd
->ahisubbase
= AHIsubBase
;
145 dd
->interrupt
.is_Node
.ln_Type
= IRQTYPE
;
146 dd
->interrupt
.is_Node
.ln_Pri
= 0;
147 dd
->interrupt
.is_Node
.ln_Name
= (STRPTR
) LibName
;
149 dd
->interrupt
.is_Code
= (void(*)(void)) cardinterrupt
;
151 dd
->interrupt
.is_Code
= (void(*)(void)) CardInterrupt
;
153 dd
->interrupt
.is_Data
= (APTR
) dd
;
155 dd
->playback_interrupt
.is_Node
.ln_Type
= IRQTYPE
;
156 dd
->playback_interrupt
.is_Node
.ln_Pri
= 0;
157 dd
->playback_interrupt
.is_Node
.ln_Name
= (STRPTR
) LibName
;
159 dd
->playback_interrupt
.is_Code
= playbackinterrupt
;
161 dd
->playback_interrupt
.is_Code
= PlaybackInterrupt
;
163 dd
->playback_interrupt
.is_Data
= (APTR
) dd
;
165 dd
->record_interrupt
.is_Node
.ln_Type
= IRQTYPE
;
166 dd
->record_interrupt
.is_Node
.ln_Pri
= 0;
167 dd
->record_interrupt
.is_Node
.ln_Name
= (STRPTR
) LibName
;
169 dd
->record_interrupt
.is_Code
= recordinterrupt
;
171 dd
->record_interrupt
.is_Code
= RecordInterrupt
;
173 dd
->record_interrupt
.is_Data
= (APTR
) dd
;
177 outw_config(PCI_COMMAND
, 0x00, dd
->pci_dev
);
178 //dev->WriteConfigLong( PCI_BASE_ADDRESS_0, 0xdc00 );
180 //SB- Configure IO, if required. Force IO into 16bit/ISA address space, since it
181 // apparently won't work in 32bit address range. Really ought to check this in
183 unsigned long tula
= ( inl_config(PCI_BASE_ADDRESS_0
, dd
->pci_dev
) & 0xfffffffc );
184 if( ( tula
== 0 ) || ( tula
& 0xffff0000 ) )
186 outl_config(PCI_BASE_ADDRESS_0
, IO_SGD
, dd
->pci_dev
);
187 DBGL( "configured audio SGD IO base", IO_SGD
);
190 tula
= ( inl_config(PCI_BASE_ADDRESS_1
, dd
->pci_dev
) & 0xfffffffc );
191 if( ( tula
== 0 ) || ( tula
& 0xffff0000 ) )
193 outl_config(PCI_BASE_ADDRESS_1
, IO_FM
, dd
->pci_dev
);
194 //DBGL( "configured audio FM IO base", IO_FM );
197 tula
= ( inl_config(PCI_BASE_ADDRESS_2
, dd
->pci_dev
) & 0xfffffffc );
198 if( ( tula
== 0 ) || ( tula
& 0xffff0000 ) )
200 outl_config(PCI_BASE_ADDRESS_2
, IO_MIDI
, dd
->pci_dev
);
201 //DBGL( "configured audio MIDI IO base", IO_MIDI );
204 outw_config(PCI_COMMAND
, PCI_COMMAND_IO
, dd
->pci_dev
);
206 dd
->pci_master_enabled
= TRUE
;
208 dd
->iobase
= inl_config(PCI_BASE_ADDRESS_0
, dd
->pci_dev
) & 0xfffffffe;
210 dd
->length
= ~( ahi_pci_get_base_size(0, dd
->pci_dev
) & PCI_BASE_ADDRESS_IO_MASK
);
211 dd
->irq
= ahi_pci_get_irq(dev
);
212 dd
->chiprev
= inb_config(PCI_REVISION_ID
, dev
);
213 dd
->model
= inw_config(PCI_SUBSYSTEM_ID
, dev
);
215 dd
->table
.area
= NULL
;
216 dd
->table
.addr
= NULL
;
218 dd
->play_idx_table
= NULL
;
219 dd
->rec_idx_table
= NULL
;
221 /* Initialize chip */
222 if( card_init( dd
) < 0 )
224 DebugPrintF("Unable to initialize Card subsystem.\n");
231 ahi_pci_add_intserver(&dd
->interrupt
, dd
->pci_dev
);
232 dd
->interrupt_added
= TRUE
;
234 dd
->card_initialized
= TRUE
;
237 dd
->monitor_volume
= Linear2MixerGain( 0x10000, &dd
->monitor_volume_bits
);
238 dd
->input_gain
= Linear2RecordGain( 0x10000, &dd
->input_gain_bits
);
239 dd
->output_volume
= Linear2MixerGain( 0x10000, &dd
->output_volume_bits
);
248 /******************************************************************************
249 ** DriverData deallocation ****************************************************
250 ******************************************************************************/
252 // And this code used to be in _AHIsub_FreeAudio().
255 FreeDriverData( struct CardData
* dd
,
256 struct DriverBase
* AHIsubBase
)
260 if( dd
->pci_dev
!= NULL
)
262 if( dd
->card_initialized
)
267 if( dd
->pci_master_enabled
)
271 cmd
= inw_config(PCI_COMMAND
, dd
->pci_dev
);
272 cmd
&= ~( PCI_COMMAND_IO
| PCI_COMMAND_MASTER
);
273 outw_config(PCI_COMMAND
, cmd
, dd
->pci_dev
);
277 if( dd
->reset_handler_added
)
279 RemResetCallback(&dd
->reset_handler
);
282 if( dd
->interrupt_added
)
284 ahi_pci_rem_intserver(&dd
->interrupt
, dd
->pci_dev
);
292 void channel_reset(struct CardData
*card
)
294 struct PCIDevice
*dev
= (struct PCIDevice
*) card
->pci_dev
;
296 pci_outb(VIA_REG_CTRL_TERMINATE
/*| VIA_REG_CTRL_RESET*/, VIA_REG_OFFSET_CONTROL
, card
);
297 pci_inb(VIA_REG_OFFSET_CONTROL
, card
);
299 /* disable interrupts */
300 pci_outb(0x00, VIA_REG_OFFSET_CONTROL
, card
);
301 /* clear interrupts */
302 pci_outb(0x03, VIA_REG_OFFSET_STATUS
, card
);
303 pci_outb(0x00, VIA_REG_OFFSET_TYPE
, card
); /* for via686 */
304 // pci_outl(0, VIA_REG_OFFSET_CURR_PTR, card);
307 //reset/init ac97 codec. Returns false if the primary codec isn't found/ready.
308 BOOL
ac97_reset( struct PCIDevice
*via686b_audio
)
310 static const unsigned long reset_delay
= 100; //link operation delay, should be some uS..
311 static const unsigned long codec_timeout
= 50; //codec ready timeout, about half a second...
314 //SB- Set the link to a known initial configuration.
315 //SB- Note: The 'standard' ***x reset code is quite similar to this, except it
316 // de-asserts SYNC at this point, possibly in case the link/codec is
317 // in low power mode. We don't, because if we do, the dreaded half-
318 // rate problem occurs, with ~100% reliability (..interesting).
319 // It is a bit of a worry that the 'standard' reset code fails, but
320 // perhaps it is simply because we have a completely untouched link,
321 // whereas on any 686 based PC, the link was probably confugured
322 // already in the BIOS.
324 outb_config(VIA_ACLINK_CTRL
,
325 VIA_ACLINK_CTRL_ENABLE
| VIA_ACLINK_CTRL_RESET
,
327 MicroDelay( reset_delay
);
330 outb_config(VIA_ACLINK_CTRL
, VIA_ACLINK_CTRL_ENABLE
, via686b_audio
);
331 MicroDelay( reset_delay
);
333 //SB- De-assert reset, enable VRA/PCM etc.
334 outb_config( VIA_ACLINK_CTRL
, VIA_ACLINK_CTRL_ENABLE
|
335 VIA_ACLINK_CTRL_RESET
|
336 VIA_ACLINK_CTRL_VRA
|
339 MicroDelay( reset_delay
);
341 //SB- Check primary codec...
342 unsigned long delay
= codec_timeout
;
345 if(inb_config( VIA_ACLINK_STAT
, via686b_audio
) & VIA_ACLINK_C00_READY
)
347 //DBG( "AC-Link reset ok." );
354 DBG( "AC-Link reset, primary codec not ready!" );
361 int card_init(struct CardData
*card
)
363 struct PCIDevice
*dev
= (struct PCIDevice
*) card
->pci_dev
;
364 unsigned short cod
, uval
;
365 unsigned char pval
, byt
;
369 struct PCIDevice
*via686b_ACPI
;
374 via686b_ACPI
= IPCI
->FindDeviceTags( FDT_VendorID
, 0x1106, FDT_DeviceID
, 0x3057,
378 via686b_ACPI
= ahi_pci_find_device(0x1106, 0x3057, NULL
);
381 if (via686b_ACPI
== NULL
) // try device 0x3058
384 via686b_ACPI
= IPCI
->FindDeviceTags( FDT_VendorID
, 0x1106, FDT_DeviceID
, 0x3058,
388 via686b_ACPI
= ahi_pci_find_device(0x1106, 0x3058, NULL
);
397 lock
= via686b_ACPI
->Lock( PCI_LOCK_SHARED
);
400 DBG( "couldn't lock the ACPI! Trying anyway..." );
404 //SB- Configure power management, if it isn't already.
405 if( !( inl_config(0x48, via686b_ACPI
) & 0xfffffffe ) )
407 outl_config(0x48, IO_PWR_MANAGEMENT
, via686b_ACPI
);
408 DBGL( "configured power management IO", IO_PWR_MANAGEMENT
);
412 DBG("Power management IO already configured");
415 //SB- Enable IO (preserve other bits, but note that technically speaking
416 // we should also be clreaing PSON gating here (it's already cleared))
417 outb_config( 0x41, (inb_config(0x41, via686b_ACPI
) | 0x80), via686b_ACPI
);
419 //SB- Power up the 686b, if it isn't already.
420 if( !( inb_config(0x42, via686b_ACPI
) & 0x40 ) )
422 //Cause a soft resume event...
423 outb(inb(IO_PWR_MANAGEMENT
+ 0x05) | 0x80, IO_PWR_MANAGEMENT
+ 0x05 );
425 //Busy loop until the soft resume completes.
426 //We have a bail out counter, but no idea how long we should wait really.
427 //..1/10th of a second wasn't long enough
428 unsigned long delay
= 25; //1/2 a second, or so
432 if( ( inb_config( 0x42, via686b_ACPI
) & 0x40))
434 DBG( "powered up the 686b." );
442 ERR( "soft resume timed out!" );
446 DBG("VIA already powered up");
451 via686b_ACPI
->Unlock();
453 IPCI
->FreeDevice( via686b_ACPI
);
458 ERR( "couldn't find the ACPI!" );
462 //SB- Don't know if there's a codec yet?
463 // codec_write(card, 0x2, 0x8000);
464 // codec_write(card, 0x4, 0x8000);
467 aclink
= ( inb_config(VIA_ACLINK_STAT
, dev
) & VIA_ACLINK_C00_READY
);
469 //SB- If no codec, reset.
470 //SB- Note: This is a possible source of trouble. It might be safer to reset
471 // every time. Only reason not to is 'pop' avoidance on soft reboot
472 // and in case UBoot did the reset.
475 aclink
= ac97_reset(dev
);
479 //SB- Make sure VRA/PCM are enabled if we didn't use our own reset code.
481 outb_config(VIA_ACLINK_CTRL
, VIA_ACLINK_CTRL_ENABLE
|\
482 VIA_ACLINK_CTRL_RESET
|\
483 VIA_ACLINK_CTRL_VRA
|\
484 VIA_ACLINK_CTRL_PCM
, dev
);
489 //INF( "initialized AC'97 codec." );
493 ERR( "sorry, you don't seem to have the AC'97 codec!" );
501 pval = inb_config(VIA_ACLINK_STAT, dev);
503 if (! (pval & VIA_ACLINK_C00_READY))
505 DebugPrintF("WHY?\n");
506 pci_write_config_byte(chip->pci, VIA_ACLINK_CTRL,
507 VIA_ACLINK_CTRL_ENABLE |
508 VIA_ACLINK_CTRL_RESET |
509 VIA_ACLINK_CTRL_SYNC);
512 pci_write_config_byte(chip->pci, VIA_ACLINK_CTRL, 0x00);
515 pci_write_config_byte(chip->pci, VIA_ACLINK_CTRL, VIA_ACLINK_CTRL_INIT);
518 pval = inb_config(VIA_ACLINK_STAT, dd->pci_dev);
520 if (! (pval & VIA_ACLINK_C00_READY))
526 while (teller < 1000)
528 pval = inb_config(VIA_ACLINK_STAT, dd->pci_dev);
529 if (pval & VIA_ACLINK_C00_READY)
537 if ((val
= pci_inl(VIA_CODEC_CMD
, card
)) & VIA_REG_AC97_BUSY
)
538 snd_printk("AC97 codec is not ready!\n");
540 outb_config(VIA_FM_NMI_CTRL
, 0, card
->pci_dev
);
541 pci_outl(0, VIA_REG_GPI_INTR
, card
);
545 codec_write(card
, AC97_MASTER_VOL_STEREO
, 0x0000 ); // no attenuation
546 codec_write(card
, AC97_AUXOUT_VOL
, 0x8000 ); // volume of the rear output
547 codec_write(card
, AC97_MASTER_VOL_MONO
, 0x8000 );
548 codec_write(card
, AC97_MASTER_TONE
, 0x0f0f ); // bass/treble control (if present)
549 codec_write(card
, AC97_PCBEEP_VOL
, 0x8000 ); // PC beep internal speaker?
551 codec_write(card
, AC97_RECORD_SELECT
, 0);
552 codec_write(card
, AC97_RECORD_GAIN
, 0x0000 ); // 0 dB gain
555 // Analog mixer input gain registers
556 codec_write(card
, AC97_PHONE_VOL
, AC97_MUTE
| 0x0008 );
557 codec_write(card
, AC97_MIC_VOL
, AC97_MUTE
| 0x0048 ); // 10 dB boost
558 codec_write(card
, AC97_LINEIN_VOL
, AC97_MUTE
| 0x0808 );
559 codec_write(card
, AC97_CD_VOL
, 0x0808 );
560 codec_write(card
, AC97_VIDEO_VOL
, AC97_MUTE
| 0x0808 );
561 codec_write(card
, AC97_AUX_VOL
, 0x0808 );
562 codec_write(card
, AC97_PCMOUT_VOL
, 0x0808 );
564 DBG("card_init() was a success!");
570 void card_cleanup(struct CardData
*card
)
576 /******************************************************************************
577 ** Misc. **********************************************************************
578 ******************************************************************************/
581 SaveMixerState( struct CardData
* dd
)
583 dd
->ac97_mic
= codec_read( dd
, AC97_MIC_VOL
);
584 dd
->ac97_cd
= codec_read( dd
, AC97_CD_VOL
);
585 dd
->ac97_video
= codec_read( dd
, AC97_VIDEO_VOL
);
586 dd
->ac97_aux
= codec_read( dd
, AC97_AUX_VOL
);
587 dd
->ac97_linein
= codec_read( dd
, AC97_LINEIN_VOL
);
588 dd
->ac97_phone
= codec_read( dd
, AC97_PHONE_VOL
);
593 RestoreMixerState( struct CardData
* dd
)
595 codec_write(dd
, AC97_MIC_VOL
, dd
->ac97_mic
);
596 codec_write(dd
, AC97_CD_VOL
, dd
->ac97_cd
);
597 codec_write(dd
, AC97_VIDEO_VOL
, dd
->ac97_video
);
598 codec_write(dd
, AC97_AUX_VOL
, dd
->ac97_aux
);
599 codec_write(dd
, AC97_LINEIN_VOL
, dd
->ac97_linein
);
600 codec_write(dd
, AC97_PHONE_VOL
, dd
->ac97_phone
);
604 UpdateMonitorMixer( struct CardData
* dd
)
606 int i
= InputBits
[ dd
->input
];
607 UWORD m
= dd
->monitor_volume_bits
& 0x801f;
608 UWORD s
= dd
->monitor_volume_bits
;
609 UWORD mm
= AC97_MUTE
| 0x0008;
610 UWORD sm
= AC97_MUTE
| 0x0808;
612 if( i
== AC97_RECMUX_STEREO_MIX
||
613 i
== AC97_RECMUX_MONO_MIX
)
615 // Use the original mixer settings
616 RestoreMixerState( dd
);
620 codec_write(dd
, AC97_MIC_VOL
,
621 i
== AC97_RECMUX_MIC
? m
: mm
);
623 codec_write(dd
, AC97_CD_VOL
,
624 i
== AC97_RECMUX_CD
? s
: sm
);
626 codec_write(dd
, AC97_VIDEO_VOL
,
627 i
== AC97_RECMUX_VIDEO
? s
: sm
);
629 codec_write(dd
, AC97_AUX_VOL
,
630 i
== AC97_RECMUX_AUX
? s
: sm
);
632 codec_write(dd
, AC97_LINEIN_VOL
,
633 i
== AC97_RECMUX_LINE
? s
: sm
);
635 codec_write(dd
, AC97_PHONE_VOL
,
636 i
== AC97_RECMUX_PHONE
? m
: mm
);
642 Linear2MixerGain( Fixed linear
,
645 static const Fixed gain
[ 33 ] =
684 while( linear
< gain
[ v
] )
691 *bits
= 0x8000; // Mute
695 *bits
= ( v
<< 8 ) | v
;
698 // KPrintF( "l2mg %08lx -> %08lx (%04lx)\n", linear, gain[ v ], *bits );
703 Linear2RecordGain( Fixed linear
,
706 static const Fixed gain
[ 17 ] =
729 while( linear
< gain
[ v
] )
736 *bits
= 0x8000; // Mute
740 *bits
= ( ( 15 - v
) << 8 ) | ( 15 - v
);
748 SamplerateToLinearPitch( ULONG samplingrate
)
750 samplingrate
= (samplingrate
<< 8) / 375;
751 return (samplingrate
>> 1) + (samplingrate
& 1);
755 #define CACHELINE_SIZE 32
757 void *pci_alloc_consistent(size_t size
, APTR
*NonAlignedAddress
)
763 if (OpenResource("newmemory.resource"))
765 address
= AllocVecTags(size
, AVT_Type
, MEMF_SHARED
, AVT_Contiguous
, TRUE
, AVT_Lock
, TRUE
,
766 AVT_PhysicalAlignment
, 32, AVT_Clear
, 0, TAG_DONE
);
771 address
= AllocVec( size
+ CACHELINE_SIZE
, MEMF_PUBLIC
| MEMF_CLEAR
);
773 if( address
!= NULL
)
775 a
= (unsigned long) address
;
776 a
= (a
+ CACHELINE_SIZE
- 1) & ~(CACHELINE_SIZE
- 1);
777 address
= (void *) a
;
781 *NonAlignedAddress
= address
;
787 void pci_free_consistent(void* addr
)
794 static ULONG
ResetHandler(struct ExceptionContext
*ctx
, struct ExecBase
*pExecBase
, struct CardData
*card
)
796 static ULONG
ResetHandler(struct CardData
*card
)
799 struct PCIDevice
*dev
= card
->pci_dev
;
801 unsigned char val
= VIA_REG_CTRL_TERMINATE
;
803 pci_outb(val
, VIA_REG_OFFSET_CONTROL
, card
);
804 pci_outb(val
, VIA_REG_OFFSET_CONTROL
+ RECORD
, card
);
812 void AddResetHandler(struct CardData
*card
)
814 struct Interrupt
*handler
= &card
->reset_handler
;
816 handler
->is_Code
= (APTR
)ResetHandler
;
817 handler
->is_Data
= (APTR
) card
;
818 handler
->is_Node
.ln_Pri
= 0;
820 handler
->is_Node
.ln_Type
= NT_EXTINTERRUPT
;
822 handler
->is_Node
.ln_Type
= NT_INTERRUPT
;
824 handler
->is_Node
.ln_Name
= "VIA-AC97 reset handler";
826 card
->reset_handler_added
= AddResetCallback(handler
);