/*1* Mac bong noise generator. Note - we ought to put a boingy noise2* here 8)3*4* ----------------------------------------------------------------------5* 16.11.98:6* rewrote some functions, added support for Enhanced ASC (Quadras)7* after the NetBSD asc.c console bell patch by Colin Wood/Frederick Bruck8* Juergen Mellinger ([email protected])9*/1011#include <linux/sched.h>12#include <linux/timer.h>1314#include <asm/macintosh.h>15#include <asm/mac_asc.h>1617static int mac_asc_inited;18/*19* dumb triangular wave table20*/21static __u8 mac_asc_wave_tab[ 0x800 ];2223/*24* Alan's original sine table; needs interpolating to 0x80025* (hint: interpolate or hardwire [0 -> Pi/2[, it's symmetric)26*/27static const signed char sine_data[] = {280, 39, 75, 103, 121, 127, 121, 103, 75, 39,290, -39, -75, -103, -121, -127, -121, -103, -75, -3930};3132/*33* where the ASC hides ...34*/35static volatile __u8* mac_asc_regs = ( void* )0x50F14000;3637/*38* sample rate; is this a good default value?39*/40static unsigned long mac_asc_samplespersec = 11050;41static int mac_bell_duration;42static unsigned long mac_bell_phase; /* 0..2*Pi -> 0..0x800 (wavetable size) */43static unsigned long mac_bell_phasepersample;4445/*46* some function protos47*/48static void mac_init_asc( void );49static void mac_nosound( unsigned long );50static void mac_quadra_start_bell( unsigned int, unsigned int, unsigned int );51static void mac_quadra_ring_bell( unsigned long );52static void mac_av_start_bell( unsigned int, unsigned int, unsigned int );53static void ( *mac_special_bell )( unsigned int, unsigned int, unsigned int );5455/*56* our timer to start/continue/stop the bell57*/58static DEFINE_TIMER(mac_sound_timer, mac_nosound, 0, 0);5960/*61* Sort of initialize the sound chip (called from mac_mksound on the first62* beep).63*/64static void mac_init_asc( void )65{66int i;6768/*69* do some machine specific initialization70* BTW:71* the NetBSD Quadra patch identifies the Enhanced Apple Sound Chip via72* mac_asc_regs[ 0x800 ] & 0xF0 != 073* this makes no sense here, because we have to set the default sample74* rate anyway if we want correct frequencies75*/76switch ( macintosh_config->ident )77{78case MAC_MODEL_IIFX:79/*80* The IIfx is always special ...81*/82mac_asc_regs = ( void* )0x50010000;83break;84/*85* not sure about how correct this list is86* machines with the EASC enhanced apple sound chip87*/88case MAC_MODEL_Q630:89case MAC_MODEL_P475:90mac_special_bell = mac_quadra_start_bell;91mac_asc_samplespersec = 22150;92break;93case MAC_MODEL_C660:94case MAC_MODEL_Q840:95/*96* The Quadra 660AV and 840AV use the "Singer" custom ASIC for sound I/O.97* It appears to be similar to the "AWACS" custom ASIC in the Power Mac98* [678]100. Because Singer and AWACS may have a similar hardware99* interface, this would imply that the code in drivers/sound/dmasound.c100* for AWACS could be used as a basis for Singer support. All we have to101* do is figure out how to do DMA on the 660AV/840AV through the PSC and102* figure out where the Singer hardware sits in memory. (I'd look in the103* vicinity of the AWACS location in a Power Mac [678]100 first, or the104* current location of the Apple Sound Chip--ASC--in other Macs.) The105* Power Mac [678]100 info can be found in MkLinux Mach kernel sources.106*107* Quoted from Apple's Tech Info Library, article number 16405:108* "Among desktop Macintosh computers, only the 660AV, 840AV, and Power109* Macintosh models have 16-bit audio input and output capability110* because of the AT&T DSP3210 hardware circuitry and the 16-bit Singer111* codec circuitry in the AVs. The Audio Waveform Amplifier and112* Converter (AWAC) chip in the Power Macintosh performs the same113* 16-bit I/O functionality. The PowerBook 500 series computers114* support 16-bit stereo output, but only mono input."115*116* Technical Information Library (TIL) article number 16405.117* http://support.apple.com/kb/TA32601118*119* --David Kilzer120*/121mac_special_bell = mac_av_start_bell;122break;123case MAC_MODEL_Q650:124case MAC_MODEL_Q700:125case MAC_MODEL_Q800:126case MAC_MODEL_Q900:127case MAC_MODEL_Q950:128/*129* Currently not implemented!130*/131mac_special_bell = NULL;132break;133default:134/*135* Every switch needs a default136*/137mac_special_bell = NULL;138break;139}140141/*142* init the wave table with a simple triangular wave143* A sine wave would sure be nicer here ...144*/145for ( i = 0; i < 0x400; i++ )146{147mac_asc_wave_tab[ i ] = i / 4;148mac_asc_wave_tab[ i + 0x400 ] = 0xFF - i / 4;149}150mac_asc_inited = 1;151}152153/*154* Called to make noise; current single entry to the boing driver.155* Does the job for simple ASC, calls other routines else.156* XXX Fixme:157* Should be split into asc_mksound, easc_mksound, av_mksound and158* function pointer set in mac_init_asc which would be called at159* init time.160* _This_ is rather ugly ...161*/162void mac_mksound( unsigned int freq, unsigned int length )163{164__u32 cfreq = ( freq << 5 ) / 468;165unsigned long flags;166int i;167168if ( mac_special_bell == NULL )169{170/* Do nothing */171return;172}173174if ( !mac_asc_inited )175mac_init_asc();176177if ( mac_special_bell )178{179mac_special_bell( freq, length, 128 );180return;181}182183if ( freq < 20 || freq > 20000 || length == 0 )184{185mac_nosound( 0 );186return;187}188189local_irq_save(flags);190191del_timer( &mac_sound_timer );192193for ( i = 0; i < 0x800; i++ )194mac_asc_regs[ i ] = 0;195for ( i = 0; i < 0x800; i++ )196mac_asc_regs[ i ] = mac_asc_wave_tab[ i ];197198for ( i = 0; i < 8; i++ )199*( __u32* )( ( __u32 )mac_asc_regs + ASC_CONTROL + 0x814 + 8 * i ) = cfreq;200201mac_asc_regs[ 0x807 ] = 0;202mac_asc_regs[ ASC_VOLUME ] = 128;203mac_asc_regs[ 0x805 ] = 0;204mac_asc_regs[ 0x80F ] = 0;205mac_asc_regs[ ASC_MODE ] = ASC_MODE_SAMPLE;206mac_asc_regs[ ASC_ENABLE ] = ASC_ENABLE_SAMPLE;207208mac_sound_timer.expires = jiffies + length;209add_timer( &mac_sound_timer );210211local_irq_restore(flags);212}213214/*215* regular ASC: stop whining ..216*/217static void mac_nosound( unsigned long ignored )218{219mac_asc_regs[ ASC_ENABLE ] = 0;220}221222/*223* EASC entry; init EASC, don't load wavetable, schedule 'start whining'.224*/225static void mac_quadra_start_bell( unsigned int freq, unsigned int length, unsigned int volume )226{227unsigned long flags;228229/* if the bell is already ringing, ring longer */230if ( mac_bell_duration > 0 )231{232mac_bell_duration += length;233return;234}235236mac_bell_duration = length;237mac_bell_phase = 0;238mac_bell_phasepersample = ( freq * sizeof( mac_asc_wave_tab ) ) / mac_asc_samplespersec;239/* this is reasonably big for small frequencies */240241local_irq_save(flags);242243/* set the volume */244mac_asc_regs[ 0x806 ] = volume;245246/* set up the ASC registers */247if ( mac_asc_regs[ 0x801 ] != 1 )248{249/* select mono mode */250mac_asc_regs[ 0x807 ] = 0;251/* select sampled sound mode */252mac_asc_regs[ 0x802 ] = 0;253/* ??? */254mac_asc_regs[ 0x801 ] = 1;255mac_asc_regs[ 0x803 ] |= 0x80;256mac_asc_regs[ 0x803 ] &= 0x7F;257}258259mac_sound_timer.function = mac_quadra_ring_bell;260mac_sound_timer.expires = jiffies + 1;261add_timer( &mac_sound_timer );262263local_irq_restore(flags);264}265266/*267* EASC 'start/continue whining'; I'm not sure why the above function didn't268* already load the wave table, or at least call this one...269* This piece keeps reloading the wave table until done.270*/271static void mac_quadra_ring_bell( unsigned long ignored )272{273int i, count = mac_asc_samplespersec / HZ;274unsigned long flags;275276/*277* we neither want a sound buffer overflow nor underflow, so we need to match278* the number of samples per timer interrupt as exactly as possible.279* using the asc interrupt will give better results in the future280* ...and the possibility to use a real sample (a boingy noise, maybe...)281*/282283local_irq_save(flags);284285del_timer( &mac_sound_timer );286287if ( mac_bell_duration-- > 0 )288{289for ( i = 0; i < count; i++ )290{291mac_bell_phase += mac_bell_phasepersample;292mac_asc_regs[ 0 ] = mac_asc_wave_tab[ mac_bell_phase & ( sizeof( mac_asc_wave_tab ) - 1 ) ];293}294mac_sound_timer.expires = jiffies + 1;295add_timer( &mac_sound_timer );296}297else298mac_asc_regs[ 0x801 ] = 0;299300local_irq_restore(flags);301}302303/*304* AV code - please fill in.305*/306static void mac_av_start_bell( unsigned int freq, unsigned int length, unsigned int volume )307{308}309310311