#include "Apu.h" typedef struct { unsigned int APUCON; unsigned int PARCON; unsigned int VOLCON; unsigned int APUINT; unsigned int RAMBSAD; unsigned int THAD1; unsigned int THAD2; unsigned int CURAD; unsigned int EQGAIN0; unsigned int EQGAIN1; unsigned int FMCON; unsigned int APURAMBIST; }sApu; #define KVA91_APU_address 0xfff0a000 static inline sApu * Get_Apu_Device(void) { return (sApu *)KVA91_APU_address; } #define KVA91_GPY_CE_OUTPUT 0xfff84000 #define KVA91_GPY_CE_PORT 0xfff84008 #define KVA91_GPY_CE_PIN (1<<9) #define PLLCON 0xFFF0000C #define PWDEN (1<<16) #define FBDV (0x1ff<<7) #define OTDV (0x3<<5) #define INDV (0x1f) #define CLKSEL 0xFFF00014 #define outp32(port,value) (*((unsigned int *)(port))=(value)) #define inp32(port) (*((unsigned int *)(port))) sApu *Apu; pfnFillBuffer FillBuffer; volatile unsigned char Apufg; volatile unsigned char ApuStopIndex; void Apu_SetVolume(unsigned char v) { if(v>=0x20) v=0x1f; Apu=Get_Apu_Device(); Apu->VOLCON=(0<<16)+(v<<8)+v; } void Apu_Start(void) { Apu=Get_Apu_Device(); Apu->APUCON=1; Apufg=0; } void Apu_Stop(void) { Apu=Get_Apu_Device(); Apu->APUCON=0; Apu_SetVolume(0); Apufg=1; *(volatile unsigned int*)KVA91_GPY_CE_PORT=(*(volatile unsigned int*)KVA91_GPY_CE_PORT)&~KVA91_GPY_CE_PIN; } bool Apu_Is_Busy(void) { Apu=Get_Apu_Device(); if(Apu->APUINT & 1) { if(ApuStopIndex==0) FillBuffer(0); else if(ApuStopIndex==1) Apu_Stop(); Apu->APUINT&=~1; } if(Apu->APUINT & 2) { if(ApuStopIndex==0) FillBuffer(1); else if(ApuStopIndex==2) Apu_Stop(); Apu->APUINT&=~2; } if(Apufg) { Apu_SetVolume(0); *(volatile unsigned int*)0xfff00018=(*(volatile unsigned int*)0xfff00018)|2; Apu->APUCON&=~1; Apu->APUCON|=(1<<16); *(volatile unsigned int*)KVA91_GPY_CE_PORT=(*(volatile unsigned int*)KVA91_GPY_CE_PORT)&~KVA91_GPY_CE_PIN; } return (bool)Apu->APUCON&1; } void Apu_Register_Fetch_Data(pfnFillBuffer Addr) { FillBuffer=Addr; } void Apu_Set_Buffer(unsigned int BufferAddr) { Apu=Get_Apu_Device(); Apu->RAMBSAD=BufferAddr; } void Apu_Set_Buffer_Size(unsigned char Index,unsigned short size) { Apu=Get_Apu_Device(); if(Index==0) Apu->THAD1=Apu->RAMBSAD+size; else Apu->THAD2=Apu->THAD1+size; } void Apu_Open(unsigned int sr,unsigned short chn) { unsigned int freq; unsigned int tmp; unsigned int iFBDV,iOTDV,iINDV; tmp=inp32(PLLCON); if((tmp&PWDEN)==0) { iFBDV=(tmp&FBDV)>>7; iOTDV=(tmp&OTDV)>>5; iINDV=(tmp&INDV)>>0; unsigned char uc[4]={1,2,2,4}; tmp=uc[iOTDV]; freq=27000000*(iFBDV+2)/(tmp*(iINDV+2)); } else { freq=192000000; } freq=freq/(128*sr*2); outp32(CLKSEL,(inp32(CLKSEL) & (~0x3ff))+freq-1); Apu=Get_Apu_Device(); Apu->APUCON=1<<16; Apu->PARCON|=0x30; Apu->APUCON=0; *(volatile unsigned int*)KVA91_GPY_CE_OUTPUT=(*(volatile unsigned int*)KVA91_GPY_CE_OUTPUT)|KVA91_GPY_CE_PIN; *(volatile unsigned int*)KVA91_GPY_CE_PORT=(*(volatile unsigned int*)KVA91_GPY_CE_PORT)|KVA91_GPY_CE_PIN; if(chn==1) Apu->PARCON|=1; else Apu->PARCON=Apu->PARCON&~0x1; Apu->APUINT=3<<16; Apu_SetVolume(0x1f); } void Apu_Close(void) { }