2005-04-17 02:20:36 +04:00
/*
2006-10-04 01:01:26 +04:00
* sound / oss / sb_common . c
2005-04-17 02:20:36 +04:00
*
* Common routines for Sound Blaster compatible cards .
*
*
* Copyright ( C ) by Hannu Savolainen 1993 - 1997
*
* OSS / Free for Linux is distributed under the GNU GENERAL PUBLIC LICENSE ( GPL )
* Version 2 ( June 1991 ) . See the " COPYING " file distributed with this software
* for more info .
*
*
* Daniel J . Rodriksson : Modified sbintr to handle 8 and 16 bit interrupts
* for full duplex support ( only sb16 by now )
* Rolf Fokkens : Added ( BETA ? ) support for ES1887 chips .
* ( fokkensr @ vertis . nl ) Which means : You can adjust the recording levels .
*
* 2000 / 01 / 18 - separated sb_card and sb_common -
* Jeff Garzik < jgarzik @ pobox . com >
*
* 2000 / 09 / 18 - got rid of attach_uart401
* Arnaldo Carvalho de Melo < acme @ conectiva . com . br >
*
* 2001 / 01 / 26 - replaced CLI / STI with spinlocks
* Chris Rankin < rankinc @ zipworld . com . au >
*/
# include <linux/init.h>
# include <linux/interrupt.h>
# include <linux/module.h>
# include <linux/delay.h>
# include <linux/spinlock.h>
# include "sound_config.h"
# include "sound_firmware.h"
# include "mpu401.h"
# include "sb_mixer.h"
# include "sb.h"
# include "sb_ess.h"
/*
* global module flag
*/
int sb_be_quiet ;
static sb_devc * detected_devc ; /* For communication from probe to init */
static sb_devc * last_devc ; /* For MPU401 initialization */
static unsigned char jazz_irq_bits [ ] = {
0 , 0 , 2 , 3 , 0 , 1 , 0 , 4 , 0 , 2 , 5 , 0 , 0 , 0 , 0 , 6
} ;
static unsigned char jazz_dma_bits [ ] = {
0 , 1 , 0 , 2 , 0 , 3 , 0 , 4
} ;
void * smw_free ;
/*
* Jazz16 chipset specific control variables
*/
static int jazz16_base ; /* Not detected */
static unsigned char jazz16_bits ; /* I/O relocation bits */
static DEFINE_SPINLOCK ( jazz16_lock ) ;
/*
* Logitech Soundman Wave specific initialization code
*/
# ifdef SMW_MIDI0001_INCLUDED
# include "smw-midi0001.h"
# else
static unsigned char * smw_ucode ;
static int smw_ucodeLen ;
# endif
static sb_devc * last_sb ; /* Last sb loaded */
int sb_dsp_command ( sb_devc * devc , unsigned char val )
{
int i ;
unsigned long limit ;
limit = jiffies + HZ / 10 ; /* Timeout */
/*
* Note ! the i < 500000 is an emergency exit . The sb_dsp_command ( ) is sometimes
* called while interrupts are disabled . This means that the timer is
* disabled also . However the timeout situation is a abnormal condition .
* Normally the DSP should be ready to accept commands after just couple of
* loops .
*/
for ( i = 0 ; i < 500000 & & ( limit - jiffies ) > 0 ; i + + )
{
if ( ( inb ( DSP_STATUS ) & 0x80 ) = = 0 )
{
outb ( ( val ) , DSP_COMMAND ) ;
return 1 ;
}
}
printk ( KERN_WARNING " Sound Blaster: DSP command(%x) timeout. \n " , val ) ;
return 0 ;
}
int sb_dsp_get_byte ( sb_devc * devc )
{
int i ;
for ( i = 1000 ; i ; i - - )
{
if ( inb ( DSP_DATA_AVAIL ) & 0x80 )
return inb ( DSP_READ ) ;
}
return 0xffff ;
}
static void sb_intr ( sb_devc * devc )
{
int status ;
unsigned char src = 0xff ;
if ( devc - > model = = MDL_SB16 )
{
src = sb_getmixer ( devc , IRQ_STAT ) ; /* Interrupt source register */
if ( src & 4 ) /* MPU401 interrupt */
if ( devc - > midi_irq_cookie )
uart401intr ( devc - > irq , devc - > midi_irq_cookie , NULL ) ;
if ( ! ( src & 3 ) )
return ; /* Not a DSP interrupt */
}
if ( devc - > intr_active & & ( ! devc - > fullduplex | | ( src & 0x01 ) ) )
{
switch ( devc - > irq_mode )
{
case IMODE_OUTPUT :
DMAbuf_outputintr ( devc - > dev , 1 ) ;
break ;
case IMODE_INPUT :
DMAbuf_inputintr ( devc - > dev ) ;
break ;
case IMODE_INIT :
break ;
case IMODE_MIDI :
sb_midi_interrupt ( devc ) ;
break ;
default :
/* printk(KERN_WARN "Sound Blaster: Unexpected interrupt\n"); */
;
}
}
else if ( devc - > intr_active_16 & & ( src & 0x02 ) )
{
switch ( devc - > irq_mode_16 )
{
case IMODE_OUTPUT :
DMAbuf_outputintr ( devc - > dev , 1 ) ;
break ;
case IMODE_INPUT :
DMAbuf_inputintr ( devc - > dev ) ;
break ;
case IMODE_INIT :
break ;
default :
/* printk(KERN_WARN "Sound Blaster: Unexpected interrupt\n"); */
;
}
}
/*
* Acknowledge interrupts
*/
if ( src & 0x01 )
status = inb ( DSP_DATA_AVAIL ) ;
if ( devc - > model = = MDL_SB16 & & src & 0x02 )
status = inb ( DSP_DATA_AVL16 ) ;
}
static void pci_intr ( sb_devc * devc )
{
int src = inb ( devc - > pcibase + 0x1A ) ;
src & = 3 ;
if ( src )
sb_intr ( devc ) ;
}
static irqreturn_t sbintr ( int irq , void * dev_id , struct pt_regs * dummy )
{
sb_devc * devc = dev_id ;
devc - > irq_ok = 1 ;
switch ( devc - > model ) {
case MDL_ESSPCI :
pci_intr ( devc ) ;
break ;
case MDL_ESS :
ess_intr ( devc ) ;
break ;
default :
sb_intr ( devc ) ;
break ;
}
return IRQ_HANDLED ;
}
int sb_dsp_reset ( sb_devc * devc )
{
int loopc ;
DEB ( printk ( " Entered sb_dsp_reset() \n " ) ) ;
if ( devc - > model = = MDL_ESS ) return ess_dsp_reset ( devc ) ;
/* This is only for non-ESS chips */
outb ( 1 , DSP_RESET ) ;
udelay ( 10 ) ;
outb ( 0 , DSP_RESET ) ;
udelay ( 30 ) ;
for ( loopc = 0 ; loopc < 1000 & & ! ( inb ( DSP_DATA_AVAIL ) & 0x80 ) ; loopc + + ) ;
if ( inb ( DSP_READ ) ! = 0xAA )
{
DDB ( printk ( " sb: No response to RESET \n " ) ) ;
return 0 ; /* Sorry */
}
DEB ( printk ( " sb_dsp_reset() OK \n " ) ) ;
return 1 ;
}
static void dsp_get_vers ( sb_devc * devc )
{
int i ;
unsigned long flags ;
DDB ( printk ( " Entered dsp_get_vers() \n " ) ) ;
spin_lock_irqsave ( & devc - > lock , flags ) ;
devc - > major = devc - > minor = 0 ;
sb_dsp_command ( devc , 0xe1 ) ; /* Get version */
for ( i = 100000 ; i ; i - - )
{
if ( inb ( DSP_DATA_AVAIL ) & 0x80 )
{
if ( devc - > major = = 0 )
devc - > major = inb ( DSP_READ ) ;
else
{
devc - > minor = inb ( DSP_READ ) ;
break ;
}
}
}
spin_unlock_irqrestore ( & devc - > lock , flags ) ;
DDB ( printk ( " DSP version %d.%02d \n " , devc - > major , devc - > minor ) ) ;
}
static int sb16_set_dma_hw ( sb_devc * devc )
{
int bits ;
if ( devc - > dma8 ! = 0 & & devc - > dma8 ! = 1 & & devc - > dma8 ! = 3 )
{
printk ( KERN_ERR " SB16: Invalid 8 bit DMA (%d) \n " , devc - > dma8 ) ;
return 0 ;
}
bits = ( 1 < < devc - > dma8 ) ;
if ( devc - > dma16 > = 5 & & devc - > dma16 < = 7 )
bits | = ( 1 < < devc - > dma16 ) ;
sb_setmixer ( devc , DMA_NR , bits ) ;
return 1 ;
}
static void sb16_set_mpu_port ( sb_devc * devc , struct address_info * hw_config )
{
/*
* This routine initializes new MIDI port setup register of SB Vibra ( CT2502 ) .
*/
unsigned char bits = sb_getmixer ( devc , 0x84 ) & ~ 0x06 ;
switch ( hw_config - > io_base )
{
case 0x300 :
sb_setmixer ( devc , 0x84 , bits | 0x04 ) ;
break ;
case 0x330 :
sb_setmixer ( devc , 0x84 , bits | 0x00 ) ;
break ;
default :
sb_setmixer ( devc , 0x84 , bits | 0x02 ) ; /* Disable MPU */
printk ( KERN_ERR " SB16: Invalid MIDI I/O port %x \n " , hw_config - > io_base ) ;
}
}
static int sb16_set_irq_hw ( sb_devc * devc , int level )
{
int ival ;
switch ( level )
{
case 5 :
ival = 2 ;
break ;
case 7 :
ival = 4 ;
break ;
case 9 :
ival = 1 ;
break ;
case 10 :
ival = 8 ;
break ;
default :
printk ( KERN_ERR " SB16: Invalid IRQ%d \n " , level ) ;
return 0 ;
}
sb_setmixer ( devc , IRQ_NR , ival ) ;
return 1 ;
}
static void relocate_Jazz16 ( sb_devc * devc , struct address_info * hw_config )
{
unsigned char bits = 0 ;
unsigned long flags ;
if ( jazz16_base ! = 0 & & jazz16_base ! = hw_config - > io_base )
return ;
switch ( hw_config - > io_base )
{
case 0x220 :
bits = 1 ;
break ;
case 0x240 :
bits = 2 ;
break ;
case 0x260 :
bits = 3 ;
break ;
default :
return ;
}
bits = jazz16_bits = bits < < 5 ;
jazz16_base = hw_config - > io_base ;
/*
* Magic wake up sequence by writing to 0x201 ( aka Joystick port )
*/
spin_lock_irqsave ( & jazz16_lock , flags ) ;
outb ( ( 0xAF ) , 0x201 ) ;
outb ( ( 0x50 ) , 0x201 ) ;
outb ( ( bits ) , 0x201 ) ;
spin_unlock_irqrestore ( & jazz16_lock , flags ) ;
}
static int init_Jazz16 ( sb_devc * devc , struct address_info * hw_config )
{
char name [ 100 ] ;
/*
* First try to check that the card has Jazz16 chip . It identifies itself
* by returning 0x12 as response to DSP command 0xfa .
*/
if ( ! sb_dsp_command ( devc , 0xfa ) )
return 0 ;
if ( sb_dsp_get_byte ( devc ) ! = 0x12 )
return 0 ;
/*
* OK so far . Now configure the IRQ and DMA channel used by the card .
*/
if ( hw_config - > irq < 1 | | hw_config - > irq > 15 | | jazz_irq_bits [ hw_config - > irq ] = = 0 )
{
printk ( KERN_ERR " Jazz16: Invalid interrupt (IRQ%d) \n " , hw_config - > irq ) ;
return 0 ;
}
if ( hw_config - > dma < 0 | | hw_config - > dma > 3 | | jazz_dma_bits [ hw_config - > dma ] = = 0 )
{
printk ( KERN_ERR " Jazz16: Invalid 8 bit DMA (DMA%d) \n " , hw_config - > dma ) ;
return 0 ;
}
if ( hw_config - > dma2 < 0 )
{
printk ( KERN_ERR " Jazz16: No 16 bit DMA channel defined \n " ) ;
return 0 ;
}
if ( hw_config - > dma2 < 5 | | hw_config - > dma2 > 7 | | jazz_dma_bits [ hw_config - > dma2 ] = = 0 )
{
printk ( KERN_ERR " Jazz16: Invalid 16 bit DMA (DMA%d) \n " , hw_config - > dma2 ) ;
return 0 ;
}
devc - > dma16 = hw_config - > dma2 ;
if ( ! sb_dsp_command ( devc , 0xfb ) )
return 0 ;
if ( ! sb_dsp_command ( devc , jazz_dma_bits [ hw_config - > dma ] |
( jazz_dma_bits [ hw_config - > dma2 ] < < 4 ) ) )
return 0 ;
if ( ! sb_dsp_command ( devc , jazz_irq_bits [ hw_config - > irq ] ) )
return 0 ;
/*
* Now we have configured a standard Jazz16 device .
*/
devc - > model = MDL_JAZZ ;
strcpy ( name , " Jazz16 " ) ;
hw_config - > name = " Jazz16 " ;
devc - > caps | = SB_NO_MIDI ;
return 1 ;
}
static void relocate_ess1688 ( sb_devc * devc )
{
unsigned char bits ;
switch ( devc - > base )
{
case 0x220 :
bits = 0x04 ;
break ;
case 0x230 :
bits = 0x05 ;
break ;
case 0x240 :
bits = 0x06 ;
break ;
case 0x250 :
bits = 0x07 ;
break ;
default :
return ; /* Wrong port */
}
DDB ( printk ( " Doing ESS1688 address selection \n " ) ) ;
/*
* ES1688 supports two alternative ways for software address config .
* First try the so called Read - Sequence - Key method .
*/
/* Reset the sequence logic */
inb ( 0x229 ) ;
inb ( 0x229 ) ;
inb ( 0x229 ) ;
/* Perform the read sequence */
inb ( 0x22b ) ;
inb ( 0x229 ) ;
inb ( 0x22b ) ;
inb ( 0x229 ) ;
inb ( 0x229 ) ;
inb ( 0x22b ) ;
inb ( 0x229 ) ;
/* Select the base address by reading from it. Then probe using the port. */
inb ( devc - > base ) ;
if ( sb_dsp_reset ( devc ) ) /* Bingo */
return ;
#if 0 /* This causes system lockups (Nokia 386/25 at least) */
/*
* The last resort is the system control register method .
*/
outb ( ( 0x00 ) , 0xfb ) ; /* 0xFB is the unlock register */
outb ( ( 0x00 ) , 0xe0 ) ; /* Select index 0 */
outb ( ( bits ) , 0xe1 ) ; /* Write the config bits */
outb ( ( 0x00 ) , 0xf9 ) ; /* 0xFB is the lock register */
# endif
}
int sb_dsp_detect ( struct address_info * hw_config , int pci , int pciio , struct sb_module_options * sbmo )
{
sb_devc sb_info ;
sb_devc * devc = & sb_info ;
memset ( ( char * ) & sb_info , 0 , sizeof ( sb_info ) ) ; /* Zero everything */
/* Copy module options in place */
if ( sbmo ) memcpy ( & devc - > sbmo , sbmo , sizeof ( struct sb_module_options ) ) ;
sb_info . my_mididev = - 1 ;
sb_info . my_mixerdev = - 1 ;
sb_info . dev = - 1 ;
/*
* Initialize variables
*/
DDB ( printk ( " sb_dsp_detect(%x) entered \n " , hw_config - > io_base ) ) ;
spin_lock_init ( & devc - > lock ) ;
devc - > type = hw_config - > card_subtype ;
devc - > base = hw_config - > io_base ;
devc - > irq = hw_config - > irq ;
devc - > dma8 = hw_config - > dma ;
devc - > dma16 = - 1 ;
devc - > pcibase = pciio ;
if ( pci = = SB_PCI_ESSMAESTRO )
{
devc - > model = MDL_ESSPCI ;
devc - > caps | = SB_PCI_IRQ ;
hw_config - > driver_use_1 | = SB_PCI_IRQ ;
hw_config - > card_subtype = MDL_ESSPCI ;
}
if ( pci = = SB_PCI_YAMAHA )
{
devc - > model = MDL_YMPCI ;
devc - > caps | = SB_PCI_IRQ ;
hw_config - > driver_use_1 | = SB_PCI_IRQ ;
hw_config - > card_subtype = MDL_YMPCI ;
printk ( " Yamaha PCI mode. \n " ) ;
}
if ( devc - > sbmo . acer )
{
unsigned long flags ;
spin_lock_irqsave ( & devc - > lock , flags ) ;
inb ( devc - > base + 0x09 ) ;
inb ( devc - > base + 0x09 ) ;
inb ( devc - > base + 0x09 ) ;
inb ( devc - > base + 0x0b ) ;
inb ( devc - > base + 0x09 ) ;
inb ( devc - > base + 0x0b ) ;
inb ( devc - > base + 0x09 ) ;
inb ( devc - > base + 0x09 ) ;
inb ( devc - > base + 0x0b ) ;
inb ( devc - > base + 0x09 ) ;
inb ( devc - > base + 0x00 ) ;
spin_unlock_irqrestore ( & devc - > lock , flags ) ;
}
/*
* Detect the device
*/
if ( sb_dsp_reset ( devc ) )
dsp_get_vers ( devc ) ;
else
devc - > major = 0 ;
if ( devc - > type = = 0 | | devc - > type = = MDL_JAZZ | | devc - > type = = MDL_SMW )
if ( devc - > major = = 0 | | ( devc - > major = = 3 & & devc - > minor = = 1 ) )
relocate_Jazz16 ( devc , hw_config ) ;
if ( devc - > major = = 0 & & ( devc - > type = = MDL_ESS | | devc - > type = = 0 ) )
relocate_ess1688 ( devc ) ;
if ( ! sb_dsp_reset ( devc ) )
{
DDB ( printk ( " SB reset failed \n " ) ) ;
# ifdef MODULE
printk ( KERN_INFO " sb: dsp reset failed. \n " ) ;
# endif
return 0 ;
}
if ( devc - > major = = 0 )
dsp_get_vers ( devc ) ;
if ( devc - > major = = 3 & & devc - > minor = = 1 )
{
if ( devc - > type = = MDL_AZTECH ) /* SG Washington? */
{
if ( sb_dsp_command ( devc , 0x09 ) )
if ( sb_dsp_command ( devc , 0x00 ) ) /* Enter WSS mode */
{
int i ;
/* Have some delay */
for ( i = 0 ; i < 10000 ; i + + )
inb ( DSP_DATA_AVAIL ) ;
devc - > caps = SB_NO_AUDIO | SB_NO_MIDI ; /* Mixer only */
devc - > model = MDL_AZTECH ;
}
}
}
if ( devc - > type = = MDL_ESSPCI )
devc - > model = MDL_ESSPCI ;
if ( devc - > type = = MDL_YMPCI )
{
printk ( " YMPCI selected \n " ) ;
devc - > model = MDL_YMPCI ;
}
/*
* Save device information for sb_dsp_init ( )
*/
detected_devc = ( sb_devc * ) kmalloc ( sizeof ( sb_devc ) , GFP_KERNEL ) ;
if ( detected_devc = = NULL )
{
printk ( KERN_ERR " sb: Can't allocate memory for device information \n " ) ;
return 0 ;
}
memcpy ( detected_devc , devc , sizeof ( sb_devc ) ) ;
MDB ( printk ( KERN_INFO " SB %d.%02d detected OK (%x) \n " , devc - > major , devc - > minor , hw_config - > io_base ) ) ;
return 1 ;
}
int sb_dsp_init ( struct address_info * hw_config , struct module * owner )
{
sb_devc * devc ;
char name [ 100 ] ;
extern int sb_be_quiet ;
int mixer22 , mixer30 ;
/*
* Check if we had detected a SB device earlier
*/
DDB ( printk ( " sb_dsp_init(%x) entered \n " , hw_config - > io_base ) ) ;
name [ 0 ] = 0 ;
if ( detected_devc = = NULL )
{
MDB ( printk ( " No detected device \n " ) ) ;
return 0 ;
}
devc = detected_devc ;
detected_devc = NULL ;
if ( devc - > base ! = hw_config - > io_base )
{
DDB ( printk ( " I/O port mismatch \n " ) ) ;
release_region ( devc - > base , 16 ) ;
return 0 ;
}
/*
* Now continue initialization of the device
*/
devc - > caps = hw_config - > driver_use_1 ;
if ( ! ( ( devc - > caps & SB_NO_AUDIO ) & & ( devc - > caps & SB_NO_MIDI ) ) & & hw_config - > irq > 0 )
{ /* IRQ setup */
/*
* ESS PCI cards do shared PCI IRQ stuff . Since they
* will get shared PCI irq lines we must cope .
*/
2006-07-02 06:29:46 +04:00
int i = ( devc - > caps & SB_PCI_IRQ ) ? IRQF_SHARED : 0 ;
2005-04-17 02:20:36 +04:00
if ( request_irq ( hw_config - > irq , sbintr , i , " soundblaster " , devc ) < 0 )
{
printk ( KERN_ERR " SB: Can't allocate IRQ%d \n " , hw_config - > irq ) ;
release_region ( devc - > base , 16 ) ;
return 0 ;
}
devc - > irq_ok = 0 ;
if ( devc - > major = = 4 )
if ( ! sb16_set_irq_hw ( devc , devc - > irq ) ) /* Unsupported IRQ */
{
free_irq ( devc - > irq , devc ) ;
release_region ( devc - > base , 16 ) ;
return 0 ;
}
if ( ( devc - > type = = 0 | | devc - > type = = MDL_ESS ) & &
devc - > major = = 3 & & devc - > minor = = 1 )
{ /* Handle various chipsets which claim they are SB Pro compatible */
if ( ( devc - > type ! = 0 & & devc - > type ! = MDL_ESS ) | |
! ess_init ( devc , hw_config ) )
{
if ( ( devc - > type ! = 0 & & devc - > type ! = MDL_JAZZ & &
devc - > type ! = MDL_SMW ) | | ! init_Jazz16 ( devc , hw_config ) )
{
DDB ( printk ( " This is a genuine SB Pro \n " ) ) ;
}
}
}
if ( devc - > major = = 4 & & devc - > minor < = 11 ) /* Won't work */
devc - > irq_ok = 1 ;
else
{
int n ;
for ( n = 0 ; n < 3 & & devc - > irq_ok = = 0 ; n + + )
{
if ( sb_dsp_command ( devc , 0xf2 ) ) /* Cause interrupt immediately */
{
int i ;
for ( i = 0 ; ! devc - > irq_ok & & i < 10000 ; i + + ) ;
}
}
if ( ! devc - > irq_ok )
printk ( KERN_WARNING " sb: Interrupt test on IRQ%d failed - Probable IRQ conflict \n " , devc - > irq ) ;
else
{
DDB ( printk ( " IRQ test OK (IRQ%d) \n " , devc - > irq ) ) ;
}
}
} /* IRQ setup */
last_sb = devc ;
switch ( devc - > major )
{
case 1 : /* SB 1.0 or 1.5 */
devc - > model = hw_config - > card_subtype = MDL_SB1 ;
break ;
case 2 : /* SB 2.x */
if ( devc - > minor = = 0 )
devc - > model = hw_config - > card_subtype = MDL_SB2 ;
else
devc - > model = hw_config - > card_subtype = MDL_SB201 ;
break ;
case 3 : /* SB Pro and most clones */
switch ( devc - > model ) {
case 0 :
devc - > model = hw_config - > card_subtype = MDL_SBPRO ;
if ( hw_config - > name = = NULL )
hw_config - > name = " Sound Blaster Pro (8 BIT ONLY) " ;
break ;
case MDL_ESS :
ess_dsp_init ( devc , hw_config ) ;
break ;
}
break ;
case 4 :
devc - > model = hw_config - > card_subtype = MDL_SB16 ;
/*
* ALS007 and ALS100 return DSP version 4.2 and have 2 post - reset ! = 0
* registers at 0x3c and 0x4c ( output ctrl registers on ALS007 ) whereas
* a " standard " SB16 doesn ' t have a register at 0x4c . ALS100 actively
* updates register 0x22 whenever 0x30 changes , as per the SB16 spec .
* Since ALS007 doesn ' t , this can be used to differentiate the 2 cards .
*/
if ( ( devc - > minor = = 2 ) & & sb_getmixer ( devc , 0x3c ) & & sb_getmixer ( devc , 0x4c ) )
{
mixer30 = sb_getmixer ( devc , 0x30 ) ;
sb_setmixer ( devc , 0x22 , ( mixer22 = sb_getmixer ( devc , 0x22 ) ) & 0x0f ) ;
sb_setmixer ( devc , 0x30 , 0xff ) ;
/* ALS100 will force 0x30 to 0xf8 like SB16; ALS007 will allow 0xff. */
/* Register 0x22 & 0xf0 on ALS100 == 0xf0; on ALS007 it == 0x10. */
if ( ( sb_getmixer ( devc , 0x30 ) ! = 0xff ) | | ( ( sb_getmixer ( devc , 0x22 ) & 0xf0 ) ! = 0x10 ) )
{
devc - > submodel = SUBMDL_ALS100 ;
if ( hw_config - > name = = NULL )
hw_config - > name = " Sound Blaster 16 (ALS-100) " ;
}
else
{
sb_setmixer ( devc , 0x3c , 0x1f ) ; /* Enable all inputs */
sb_setmixer ( devc , 0x4c , 0x1f ) ;
sb_setmixer ( devc , 0x22 , mixer22 ) ; /* Restore 0x22 to original value */
devc - > submodel = SUBMDL_ALS007 ;
if ( hw_config - > name = = NULL )
hw_config - > name = " Sound Blaster 16 (ALS-007) " ;
}
sb_setmixer ( devc , 0x30 , mixer30 ) ;
}
else if ( hw_config - > name = = NULL )
hw_config - > name = " Sound Blaster 16 " ;
if ( hw_config - > dma2 = = - 1 )
devc - > dma16 = devc - > dma8 ;
else if ( hw_config - > dma2 < 5 | | hw_config - > dma2 > 7 )
{
printk ( KERN_WARNING " SB16: Bad or missing 16 bit DMA channel \n " ) ;
devc - > dma16 = devc - > dma8 ;
}
else
devc - > dma16 = hw_config - > dma2 ;
if ( ! sb16_set_dma_hw ( devc ) ) {
free_irq ( devc - > irq , devc ) ;
release_region ( hw_config - > io_base , 16 ) ;
return 0 ;
}
devc - > caps | = SB_NO_MIDI ;
}
if ( ! ( devc - > caps & SB_NO_MIXER ) )
if ( devc - > major = = 3 | | devc - > major = = 4 )
sb_mixer_init ( devc , owner ) ;
if ( ! ( devc - > caps & SB_NO_MIDI ) )
sb_dsp_midi_init ( devc , owner ) ;
if ( hw_config - > name = = NULL )
hw_config - > name = " Sound Blaster (8 BIT/MONO ONLY) " ;
sprintf ( name , " %s (%d.%02d) " , hw_config - > name , devc - > major , devc - > minor ) ;
conf_printf ( name , hw_config ) ;
/*
* Assuming that a sound card is Sound Blaster ( compatible ) is the most common
* configuration error and the mother of all problems . Usually sound cards
* emulate SB Pro but in addition they have a 16 bit native mode which should be
* used in Unix . See Readme . cards for more information about configuring OSS / Free
* properly .
*/
if ( devc - > model < = MDL_SBPRO )
{
if ( devc - > major = = 3 & & devc - > minor ! = 1 ) /* "True" SB Pro should have v3.1 (rare ones may have 3.2). */
{
printk ( KERN_INFO " This sound card may not be fully Sound Blaster Pro compatible. \n " ) ;
printk ( KERN_INFO " In many cases there is another way to configure OSS so that \n " ) ;
printk ( KERN_INFO " it works properly with OSS (for example in 16 bit mode). \n " ) ;
printk ( KERN_INFO " Please ignore this message if you _really_ have a SB Pro. \n " ) ;
}
else if ( ! sb_be_quiet & & devc - > model = = MDL_SBPRO )
{
printk ( KERN_INFO " SB DSP version is just %d.%02d which means that your card is \n " , devc - > major , devc - > minor ) ;
printk ( KERN_INFO " several years old (8 bit only device) or alternatively the sound driver \n " ) ;
printk ( KERN_INFO " is incorrectly configured. \n " ) ;
}
}
hw_config - > card_subtype = devc - > model ;
hw_config - > slots [ 0 ] = devc - > dev ;
last_devc = devc ; /* For SB MPU detection */
if ( ! ( devc - > caps & SB_NO_AUDIO ) & & devc - > dma8 > = 0 )
{
if ( sound_alloc_dma ( devc - > dma8 , " SoundBlaster8 " ) )
{
printk ( KERN_WARNING " Sound Blaster: Can't allocate 8 bit DMA channel %d \n " , devc - > dma8 ) ;
}
if ( devc - > dma16 > = 0 & & devc - > dma16 ! = devc - > dma8 )
{
if ( sound_alloc_dma ( devc - > dma16 , " SoundBlaster16 " ) )
printk ( KERN_WARNING " Sound Blaster: can't allocate 16 bit DMA channel %d. \n " , devc - > dma16 ) ;
}
sb_audio_init ( devc , name , owner ) ;
hw_config - > slots [ 0 ] = devc - > dev ;
}
else
{
MDB ( printk ( " Sound Blaster: no audio devices found. \n " ) ) ;
}
return 1 ;
}
/* if (sbmpu) below we allow mpu401 to manage the midi devs
otherwise we have to unload them . ( Andrzej Krzysztofowicz ) */
void sb_dsp_unload ( struct address_info * hw_config , int sbmpu )
{
sb_devc * devc ;
devc = audio_devs [ hw_config - > slots [ 0 ] ] - > devc ;
if ( devc & & devc - > base = = hw_config - > io_base )
{
if ( ( devc - > model & MDL_ESS ) & & devc - > pcibase )
release_region ( devc - > pcibase , 8 ) ;
release_region ( devc - > base , 16 ) ;
if ( ! ( devc - > caps & SB_NO_AUDIO ) )
{
sound_free_dma ( devc - > dma8 ) ;
if ( devc - > dma16 > = 0 )
sound_free_dma ( devc - > dma16 ) ;
}
if ( ! ( devc - > caps & SB_NO_AUDIO & & devc - > caps & SB_NO_MIDI ) )
{
if ( devc - > irq > 0 )
free_irq ( devc - > irq , devc ) ;
sb_mixer_unload ( devc ) ;
/* We don't have to do this bit any more the UART401 is its own
master - - Krzysztof Halasa */
/* But we have to do it, if UART401 is not detected */
if ( ! sbmpu )
sound_unload_mididev ( devc - > my_mididev ) ;
sound_unload_audiodev ( devc - > dev ) ;
}
kfree ( devc ) ;
}
else
release_region ( hw_config - > io_base , 16 ) ;
2005-06-26 01:58:49 +04:00
kfree ( detected_devc ) ;
2005-04-17 02:20:36 +04:00
}
/*
* Mixer access routines
*
* ES1887 modifications : some mixer registers reside in the
* range above 0xa0 . These must be accessed in another way .
*/
void sb_setmixer ( sb_devc * devc , unsigned int port , unsigned int value )
{
unsigned long flags ;
if ( devc - > model = = MDL_ESS ) {
ess_setmixer ( devc , port , value ) ;
return ;
}
spin_lock_irqsave ( & devc - > lock , flags ) ;
outb ( ( ( unsigned char ) ( port & 0xff ) ) , MIXER_ADDR ) ;
udelay ( 20 ) ;
outb ( ( ( unsigned char ) ( value & 0xff ) ) , MIXER_DATA ) ;
udelay ( 20 ) ;
spin_unlock_irqrestore ( & devc - > lock , flags ) ;
}
unsigned int sb_getmixer ( sb_devc * devc , unsigned int port )
{
unsigned int val ;
unsigned long flags ;
if ( devc - > model = = MDL_ESS ) return ess_getmixer ( devc , port ) ;
spin_lock_irqsave ( & devc - > lock , flags ) ;
outb ( ( ( unsigned char ) ( port & 0xff ) ) , MIXER_ADDR ) ;
udelay ( 20 ) ;
val = inb ( MIXER_DATA ) ;
udelay ( 20 ) ;
spin_unlock_irqrestore ( & devc - > lock , flags ) ;
return val ;
}
void sb_chgmixer
( sb_devc * devc , unsigned int reg , unsigned int mask , unsigned int val )
{
int value ;
value = sb_getmixer ( devc , reg ) ;
value = ( value & ~ mask ) | ( val & mask ) ;
sb_setmixer ( devc , reg , value ) ;
}
/*
* MPU401 MIDI initialization .
*/
static void smw_putmem ( sb_devc * devc , int base , int addr , unsigned char val )
{
unsigned long flags ;
spin_lock_irqsave ( & jazz16_lock , flags ) ; /* NOT the SB card? */
outb ( ( addr & 0xff ) , base + 1 ) ; /* Low address bits */
outb ( ( addr > > 8 ) , base + 2 ) ; /* High address bits */
outb ( ( val ) , base ) ; /* Data */
spin_unlock_irqrestore ( & jazz16_lock , flags ) ;
}
static unsigned char smw_getmem ( sb_devc * devc , int base , int addr )
{
unsigned long flags ;
unsigned char val ;
spin_lock_irqsave ( & jazz16_lock , flags ) ; /* NOT the SB card? */
outb ( ( addr & 0xff ) , base + 1 ) ; /* Low address bits */
outb ( ( addr > > 8 ) , base + 2 ) ; /* High address bits */
val = inb ( base ) ; /* Data */
spin_unlock_irqrestore ( & jazz16_lock , flags ) ;
return val ;
}
static int smw_midi_init ( sb_devc * devc , struct address_info * hw_config )
{
int mpu_base = hw_config - > io_base ;
int mp_base = mpu_base + 4 ; /* Microcontroller base */
int i ;
unsigned char control ;
/*
* Reset the microcontroller so that the RAM can be accessed
*/
control = inb ( mpu_base + 7 ) ;
outb ( ( control | 3 ) , mpu_base + 7 ) ; /* Set last two bits to 1 (?) */
outb ( ( ( control & 0xfe ) | 2 ) , mpu_base + 7 ) ; /* xxxxxxx0 resets the mc */
mdelay ( 3 ) ; /* Wait at least 1ms */
outb ( ( control & 0xfc ) , mpu_base + 7 ) ; /* xxxxxx00 enables RAM */
/*
* Detect microcontroller by probing the 8 k RAM area
*/
smw_putmem ( devc , mp_base , 0 , 0x00 ) ;
smw_putmem ( devc , mp_base , 1 , 0xff ) ;
udelay ( 10 ) ;
if ( smw_getmem ( devc , mp_base , 0 ) ! = 0x00 | | smw_getmem ( devc , mp_base , 1 ) ! = 0xff )
{
DDB ( printk ( " SM Wave: No microcontroller RAM detected (%02x, %02x) \n " , smw_getmem ( devc , mp_base , 0 ) , smw_getmem ( devc , mp_base , 1 ) ) ) ;
return 0 ; /* No RAM */
}
/*
* There is RAM so assume it ' s really a SM Wave
*/
devc - > model = MDL_SMW ;
smw_mixer_init ( devc ) ;
# ifdef MODULE
if ( ! smw_ucode )
{
smw_ucodeLen = mod_firmware_load ( " /etc/sound/midi0001.bin " , ( void * ) & smw_ucode ) ;
smw_free = smw_ucode ;
}
# endif
if ( smw_ucodeLen > 0 )
{
if ( smw_ucodeLen ! = 8192 )
{
printk ( KERN_ERR " SM Wave: Invalid microcode (MIDI0001.BIN) length \n " ) ;
return 1 ;
}
/*
* Download microcode
*/
for ( i = 0 ; i < 8192 ; i + + )
smw_putmem ( devc , mp_base , i , smw_ucode [ i ] ) ;
/*
* Verify microcode
*/
for ( i = 0 ; i < 8192 ; i + + )
if ( smw_getmem ( devc , mp_base , i ) ! = smw_ucode [ i ] )
{
printk ( KERN_ERR " SM Wave: Microcode verification failed \n " ) ;
return 0 ;
}
}
control = 0 ;
# ifdef SMW_SCSI_IRQ
/*
* Set the SCSI interrupt ( IRQ2 / 9 , IRQ3 or IRQ10 ) . The SCSI interrupt
* is disabled by default .
*
* FIXME - make this a module option
*
* BTW the Zilog 5380 SCSI controller is located at MPU base + 0x10 .
*/
{
static unsigned char scsi_irq_bits [ ] = {
0 , 0 , 3 , 1 , 0 , 0 , 0 , 0 , 0 , 3 , 2 , 0 , 0 , 0 , 0 , 0
} ;
control | = scsi_irq_bits [ SMW_SCSI_IRQ ] < < 6 ;
}
# endif
# ifdef SMW_OPL4_ENABLE
/*
* Make the OPL4 chip visible on the PC bus at 0x380 .
*
* There is no need to enable this feature since this driver
* doesn ' t support OPL4 yet . Also there is no RAM in SM Wave so
* enabling OPL4 is pretty useless .
*/
control | = 0x10 ; /* Uses IRQ12 if bit 0x20 == 0 */
/* control |= 0x20; Uncomment this if you want to use IRQ7 */
# endif
outb ( ( control | 0x03 ) , mpu_base + 7 ) ; /* xxxxxx11 restarts */
hw_config - > name = " SoundMan Wave " ;
return 1 ;
}
static int init_Jazz16_midi ( sb_devc * devc , struct address_info * hw_config )
{
int mpu_base = hw_config - > io_base ;
int sb_base = devc - > base ;
int irq = hw_config - > irq ;
unsigned char bits = 0 ;
unsigned long flags ;
if ( irq < 0 )
irq * = - 1 ;
if ( irq < 1 | | irq > 15 | |
jazz_irq_bits [ irq ] = = 0 )
{
printk ( KERN_ERR " Jazz16: Invalid MIDI interrupt (IRQ%d) \n " , irq ) ;
return 0 ;
}
switch ( sb_base )
{
case 0x220 :
bits = 1 ;
break ;
case 0x240 :
bits = 2 ;
break ;
case 0x260 :
bits = 3 ;
break ;
default :
return 0 ;
}
bits = jazz16_bits = bits < < 5 ;
switch ( mpu_base )
{
case 0x310 :
bits | = 1 ;
break ;
case 0x320 :
bits | = 2 ;
break ;
case 0x330 :
bits | = 3 ;
break ;
default :
printk ( KERN_ERR " Jazz16: Invalid MIDI I/O port %x \n " , mpu_base ) ;
return 0 ;
}
/*
* Magic wake up sequence by writing to 0x201 ( aka Joystick port )
*/
spin_lock_irqsave ( & jazz16_lock , flags ) ;
outb ( 0xAF , 0x201 ) ;
outb ( 0x50 , 0x201 ) ;
outb ( bits , 0x201 ) ;
spin_unlock_irqrestore ( & jazz16_lock , flags ) ;
hw_config - > name = " Jazz16 " ;
smw_midi_init ( devc , hw_config ) ;
if ( ! sb_dsp_command ( devc , 0xfb ) )
return 0 ;
if ( ! sb_dsp_command ( devc , jazz_dma_bits [ devc - > dma8 ] |
( jazz_dma_bits [ devc - > dma16 ] < < 4 ) ) )
return 0 ;
if ( ! sb_dsp_command ( devc , jazz_irq_bits [ devc - > irq ] |
( jazz_irq_bits [ irq ] < < 4 ) ) )
return 0 ;
return 1 ;
}
int probe_sbmpu ( struct address_info * hw_config , struct module * owner )
{
sb_devc * devc = last_devc ;
int ret ;
if ( last_devc = = NULL )
return 0 ;
last_devc = NULL ;
if ( hw_config - > io_base < = 0 )
{
/* The real vibra16 is fine about this, but we have to go
wipe up after Cyrix again */
if ( devc - > model = = MDL_SB16 & & devc - > minor > = 12 )
{
unsigned char bits = sb_getmixer ( devc , 0x84 ) & ~ 0x06 ;
sb_setmixer ( devc , 0x84 , bits | 0x02 ) ; /* Disable MPU */
}
return 0 ;
}
# if defined(CONFIG_SOUND_MPU401)
if ( devc - > model = = MDL_ESS )
{
struct resource * ports ;
ports = request_region ( hw_config - > io_base , 2 , " mpu401 " ) ;
if ( ! ports ) {
printk ( KERN_ERR " sbmpu: I/O port conflict (%x) \n " , hw_config - > io_base ) ;
return 0 ;
}
if ( ! ess_midi_init ( devc , hw_config ) ) {
release_region ( hw_config - > io_base , 2 ) ;
return 0 ;
}
hw_config - > name = " ESS1xxx MPU " ;
devc - > midi_irq_cookie = NULL ;
if ( ! probe_mpu401 ( hw_config , ports ) ) {
release_region ( hw_config - > io_base , 2 ) ;
return 0 ;
}
attach_mpu401 ( hw_config , owner ) ;
if ( last_sb - > irq = = - hw_config - > irq )
last_sb - > midi_irq_cookie = ( void * ) hw_config - > slots [ 1 ] ;
return 1 ;
}
# endif
switch ( devc - > model )
{
case MDL_SB16 :
if ( hw_config - > io_base ! = 0x300 & & hw_config - > io_base ! = 0x330 )
{
printk ( KERN_ERR " SB16: Invalid MIDI port %x \n " , hw_config - > io_base ) ;
return 0 ;
}
hw_config - > name = " Sound Blaster 16 " ;
if ( hw_config - > irq < 3 | | hw_config - > irq = = devc - > irq )
hw_config - > irq = - devc - > irq ;
if ( devc - > minor > 12 ) /* What is Vibra's version??? */
sb16_set_mpu_port ( devc , hw_config ) ;
break ;
case MDL_JAZZ :
if ( hw_config - > irq < 3 | | hw_config - > irq = = devc - > irq )
hw_config - > irq = - devc - > irq ;
if ( ! init_Jazz16_midi ( devc , hw_config ) )
return 0 ;
break ;
case MDL_YMPCI :
hw_config - > name = " Yamaha PCI Legacy " ;
printk ( " Yamaha PCI legacy UART401 check. \n " ) ;
break ;
default :
return 0 ;
}
ret = probe_uart401 ( hw_config , owner ) ;
if ( ret )
last_sb - > midi_irq_cookie = midi_devs [ hw_config - > slots [ 4 ] ] - > devc ;
return ret ;
}
void unload_sbmpu ( struct address_info * hw_config )
{
# if defined(CONFIG_SOUND_MPU401)
if ( ! strcmp ( hw_config - > name , " ESS1xxx MPU " ) ) {
unload_mpu401 ( hw_config ) ;
return ;
}
# endif
unload_uart401 ( hw_config ) ;
}
EXPORT_SYMBOL ( sb_dsp_init ) ;
EXPORT_SYMBOL ( sb_dsp_detect ) ;
EXPORT_SYMBOL ( sb_dsp_unload ) ;
EXPORT_SYMBOL ( sb_be_quiet ) ;
EXPORT_SYMBOL ( probe_sbmpu ) ;
EXPORT_SYMBOL ( unload_sbmpu ) ;
EXPORT_SYMBOL ( smw_free ) ;
MODULE_LICENSE ( " GPL " ) ;