2019-05-27 09:55:05 +03:00
// SPDX-License-Identifier: GPL-2.0-or-later
2005-04-17 02:20:36 +04:00
/*
* Driver for SoundBlaster 16 / AWE32 / AWE64 soundcards
2007-10-15 11:50:19 +04:00
* Copyright ( c ) by Jaroslav Kysela < perex @ perex . cz >
2005-04-17 02:20:36 +04:00
*/
# include <asm/dma.h>
# include <linux/init.h>
# include <linux/pnp.h>
2005-11-17 18:54:56 +03:00
# include <linux/err.h>
2007-02-22 14:50:54 +03:00
# include <linux/isa.h>
2011-07-15 21:13:37 +04:00
# include <linux/module.h>
2005-04-17 02:20:36 +04:00
# include <sound/core.h>
# include <sound/sb.h>
# include <sound/sb16_csp.h>
# include <sound/mpu401.h>
# include <sound/opl3.h>
# include <sound/emu8000.h>
# include <sound/seq_device.h>
# define SNDRV_LEGACY_FIND_FREE_IRQ
# define SNDRV_LEGACY_FIND_FREE_DMA
# include <sound/initval.h>
# ifdef SNDRV_SBAWE
# define PFX "sbawe: "
# else
# define PFX "sb16: "
# endif
2007-10-15 11:50:19 +04:00
MODULE_AUTHOR ( " Jaroslav Kysela <perex@perex.cz> " ) ;
2005-04-17 02:20:36 +04:00
MODULE_LICENSE ( " GPL " ) ;
# ifndef SNDRV_SBAWE
MODULE_DESCRIPTION ( " Sound Blaster 16 " ) ;
# else
MODULE_DESCRIPTION ( " Sound Blaster AWE " ) ;
# endif
#if 0
# define SNDRV_DEBUG_IRQ
# endif
ALSA: seq: Allow the modular sequencer registration
Many drivers bind the sequencer stuff in off-load by another driver
module, so that it's loaded only on demand. In the current code, this
mechanism doesn't work when the driver is built-in while the sequencer
is module. We check with IS_REACHABLE() and enable only when the
sequencer is in the same level of build.
However, this is basically a overshoot. The binder code
(snd-seq-device) is an individual module from the sequencer core
(snd-seq), and we just have to make the former a built-in while
keeping the latter a module for allowing the scenario like the above.
This patch achieves that by rewriting Kconfig slightly. Now, a driver
that provides the manual sequencer device binding should select
CONFIG_SND_SEQ_DEVICE in a way as
select SND_SEQ_DEVICE if SND_SEQUENCER != n
Note that the "!=n" is needed here to avoid the influence of the
sequencer core is module while the driver is built-in.
Also, since rawmidi.o may be linked with snd_seq_device.o when
built-in, we have to shuffle the code to make the linker happy.
(the kernel linker isn't smart enough yet to handle such a case.)
That is, snd_seq_device.c is moved to sound/core from sound/core/seq,
as well as Makefile.
Last but not least, the patch replaces the code using IS_REACHABLE()
with IS_ENABLED(), since now the condition meets always when enabled.
Signed-off-by: Takashi Iwai <tiwai@suse.de>
2017-06-09 16:11:58 +03:00
# if defined(SNDRV_SBAWE) && IS_ENABLED(CONFIG_SND_SEQUENCER)
2005-04-17 02:20:36 +04:00
# define SNDRV_SBAWE_EMU8000
# endif
static int index [ SNDRV_CARDS ] = SNDRV_DEFAULT_IDX ; /* Index 0-MAX */
static char * id [ SNDRV_CARDS ] = SNDRV_DEFAULT_STR ; /* ID for this card */
2011-12-15 07:19:36 +04:00
static bool enable [ SNDRV_CARDS ] = SNDRV_DEFAULT_ENABLE_ISAPNP ; /* Enable this card */
2005-04-17 02:20:36 +04:00
# ifdef CONFIG_PNP
2011-12-15 07:19:36 +04:00
static bool isapnp [ SNDRV_CARDS ] = { [ 0 . . . ( SNDRV_CARDS - 1 ) ] = 1 } ;
2005-04-17 02:20:36 +04:00
# endif
static long port [ SNDRV_CARDS ] = SNDRV_DEFAULT_PORT ; /* 0x220,0x240,0x260,0x280 */
static long mpu_port [ SNDRV_CARDS ] = SNDRV_DEFAULT_PORT ; /* 0x330,0x300 */
static long fm_port [ SNDRV_CARDS ] = SNDRV_DEFAULT_PORT ;
# ifdef SNDRV_SBAWE_EMU8000
static long awe_port [ SNDRV_CARDS ] = SNDRV_DEFAULT_PORT ;
# endif
static int irq [ SNDRV_CARDS ] = SNDRV_DEFAULT_IRQ ; /* 5,7,9,10 */
static int dma8 [ SNDRV_CARDS ] = SNDRV_DEFAULT_DMA ; /* 0,1,3 */
static int dma16 [ SNDRV_CARDS ] = SNDRV_DEFAULT_DMA ; /* 5,6,7 */
static int mic_agc [ SNDRV_CARDS ] = { [ 0 . . . ( SNDRV_CARDS - 1 ) ] = 1 } ;
# ifdef CONFIG_SND_SB16_CSP
2006-05-17 19:14:51 +04:00
static int csp [ SNDRV_CARDS ] ;
2005-04-17 02:20:36 +04:00
# endif
# ifdef SNDRV_SBAWE_EMU8000
static int seq_ports [ SNDRV_CARDS ] = { [ 0 . . . ( SNDRV_CARDS - 1 ) ] = 4 } ;
# endif
module_param_array ( index , int , NULL , 0444 ) ;
MODULE_PARM_DESC ( index , " Index value for SoundBlaster 16 soundcard. " ) ;
module_param_array ( id , charp , NULL , 0444 ) ;
MODULE_PARM_DESC ( id , " ID string for SoundBlaster 16 soundcard. " ) ;
module_param_array ( enable , bool , NULL , 0444 ) ;
MODULE_PARM_DESC ( enable , " Enable SoundBlaster 16 soundcard. " ) ;
# ifdef CONFIG_PNP
module_param_array ( isapnp , bool , NULL , 0444 ) ;
MODULE_PARM_DESC ( isapnp , " PnP detection for specified soundcard. " ) ;
# endif
2017-04-04 18:54:30 +03:00
module_param_hw_array ( port , long , ioport , NULL , 0444 ) ;
2005-04-17 02:20:36 +04:00
MODULE_PARM_DESC ( port , " Port # for SB16 driver. " ) ;
2017-04-04 18:54:30 +03:00
module_param_hw_array ( mpu_port , long , ioport , NULL , 0444 ) ;
2005-04-17 02:20:36 +04:00
MODULE_PARM_DESC ( mpu_port , " MPU-401 port # for SB16 driver. " ) ;
2017-04-04 18:54:30 +03:00
module_param_hw_array ( fm_port , long , ioport , NULL , 0444 ) ;
2005-04-17 02:20:36 +04:00
MODULE_PARM_DESC ( fm_port , " FM port # for SB16 PnP driver. " ) ;
# ifdef SNDRV_SBAWE_EMU8000
2017-04-04 18:54:30 +03:00
module_param_hw_array ( awe_port , long , ioport , NULL , 0444 ) ;
2005-04-17 02:20:36 +04:00
MODULE_PARM_DESC ( awe_port , " AWE port # for SB16 PnP driver. " ) ;
# endif
2017-04-04 18:54:30 +03:00
module_param_hw_array ( irq , int , irq , NULL , 0444 ) ;
2005-04-17 02:20:36 +04:00
MODULE_PARM_DESC ( irq , " IRQ # for SB16 driver. " ) ;
2017-04-04 18:54:30 +03:00
module_param_hw_array ( dma8 , int , dma , NULL , 0444 ) ;
2005-04-17 02:20:36 +04:00
MODULE_PARM_DESC ( dma8 , " 8-bit DMA # for SB16 driver. " ) ;
2017-04-04 18:54:30 +03:00
module_param_hw_array ( dma16 , int , dma , NULL , 0444 ) ;
2005-04-17 02:20:36 +04:00
MODULE_PARM_DESC ( dma16 , " 16-bit DMA # for SB16 driver. " ) ;
module_param_array ( mic_agc , int , NULL , 0444 ) ;
MODULE_PARM_DESC ( mic_agc , " Mic Auto-Gain-Control switch. " ) ;
# ifdef CONFIG_SND_SB16_CSP
module_param_array ( csp , int , NULL , 0444 ) ;
MODULE_PARM_DESC ( csp , " ASP/CSP chip support. " ) ;
# endif
# ifdef SNDRV_SBAWE_EMU8000
module_param_array ( seq_ports , int , NULL , 0444 ) ;
MODULE_PARM_DESC ( seq_ports , " Number of sequencer ports for WaveTable synth. " ) ;
# endif
2005-12-07 11:13:42 +03:00
# ifdef CONFIG_PNP
2007-05-15 13:42:56 +04:00
static int isa_registered ;
2005-12-07 11:13:42 +03:00
static int pnp_registered ;
# endif
2005-04-17 02:20:36 +04:00
struct snd_card_sb16 {
struct resource * fm_res ; /* used to block FM i/o region for legacy cards */
2005-11-17 18:54:56 +03:00
struct snd_sb * chip ;
2005-04-17 02:20:36 +04:00
# ifdef CONFIG_PNP
int dev_no ;
struct pnp_dev * dev ;
# ifdef SNDRV_SBAWE_EMU8000
struct pnp_dev * devwt ;
# endif
# endif
} ;
# ifdef CONFIG_PNP
2017-08-17 13:06:28 +03:00
static const struct pnp_card_device_id snd_sb16_pnpids [ ] = {
2005-04-17 02:20:36 +04:00
# ifndef SNDRV_SBAWE
/* Sound Blaster 16 PnP */
{ . id = " CTL0024 " , . devs = { { " CTL0031 " } } } ,
/* Sound Blaster 16 PnP */
{ . id = " CTL0025 " , . devs = { { " CTL0031 " } } } ,
/* Sound Blaster 16 PnP */
{ . id = " CTL0026 " , . devs = { { " CTL0031 " } } } ,
/* Sound Blaster 16 PnP */
{ . id = " CTL0027 " , . devs = { { " CTL0031 " } } } ,
/* Sound Blaster 16 PnP */
{ . id = " CTL0028 " , . devs = { { " CTL0031 " } } } ,
/* Sound Blaster 16 PnP */
{ . id = " CTL0029 " , . devs = { { " CTL0031 " } } } ,
/* Sound Blaster 16 PnP */
{ . id = " CTL002a " , . devs = { { " CTL0031 " } } } ,
/* Sound Blaster 16 PnP */
/* Note: This card has also a CTL0051:StereoEnhance device!!! */
{ . id = " CTL002b " , . devs = { { " CTL0031 " } } } ,
/* Sound Blaster 16 PnP */
{ . id = " CTL002c " , . devs = { { " CTL0031 " } } } ,
/* Sound Blaster Vibra16S */
{ . id = " CTL0051 " , . devs = { { " CTL0001 " } } } ,
/* Sound Blaster Vibra16C */
{ . id = " CTL0070 " , . devs = { { " CTL0001 " } } } ,
/* Sound Blaster Vibra16CL - added by ctm@ardi.com */
{ . id = " CTL0080 " , . devs = { { " CTL0041 " } } } ,
/* Sound Blaster 16 'value' PnP. It says model ct4130 on the pcb, */
/* but ct4131 on a sticker on the board.. */
{ . id = " CTL0086 " , . devs = { { " CTL0041 " } } } ,
/* Sound Blaster Vibra16X */
{ . id = " CTL00f0 " , . devs = { { " CTL0043 " } } } ,
2006-01-20 16:03:39 +03:00
/* Sound Blaster 16 (Virtual PC 2004) */
{ . id = " tBA03b0 " , . devs = { { . id = " PNPb003 " } } } ,
2005-04-17 02:20:36 +04:00
# else /* SNDRV_SBAWE defined */
/* Sound Blaster AWE 32 PnP */
{ . id = " CTL0035 " , . devs = { { " CTL0031 " } , { " CTL0021 " } } } ,
/* Sound Blaster AWE 32 PnP */
{ . id = " CTL0039 " , . devs = { { " CTL0031 " } , { " CTL0021 " } } } ,
/* Sound Blaster AWE 32 PnP */
{ . id = " CTL0042 " , . devs = { { " CTL0031 " } , { " CTL0021 " } } } ,
/* Sound Blaster AWE 32 PnP */
{ . id = " CTL0043 " , . devs = { { " CTL0031 " } , { " CTL0021 " } } } ,
/* Sound Blaster AWE 32 PnP */
/* Note: This card has also a CTL0051:StereoEnhance device!!! */
{ . id = " CTL0044 " , . devs = { { " CTL0031 " } , { " CTL0021 " } } } ,
/* Sound Blaster AWE 32 PnP */
/* Note: This card has also a CTL0051:StereoEnhance device!!! */
{ . id = " CTL0045 " , . devs = { { " CTL0031 " } , { " CTL0021 " } } } ,
/* Sound Blaster AWE 32 PnP */
{ . id = " CTL0046 " , . devs = { { " CTL0031 " } , { " CTL0021 " } } } ,
/* Sound Blaster AWE 32 PnP */
{ . id = " CTL0047 " , . devs = { { " CTL0031 " } , { " CTL0021 " } } } ,
/* Sound Blaster AWE 32 PnP */
{ . id = " CTL0048 " , . devs = { { " CTL0031 " } , { " CTL0021 " } } } ,
/* Sound Blaster AWE 32 PnP */
{ . id = " CTL0054 " , . devs = { { " CTL0031 " } , { " CTL0021 " } } } ,
/* Sound Blaster AWE 32 PnP */
{ . id = " CTL009a " , . devs = { { " CTL0041 " } , { " CTL0021 " } } } ,
/* Sound Blaster AWE 32 PnP */
{ . id = " CTL009c " , . devs = { { " CTL0041 " } , { " CTL0021 " } } } ,
/* Sound Blaster 32 PnP */
{ . id = " CTL009f " , . devs = { { " CTL0041 " } , { " CTL0021 " } } } ,
/* Sound Blaster AWE 64 PnP */
{ . id = " CTL009d " , . devs = { { " CTL0042 " } , { " CTL0022 " } } } ,
/* Sound Blaster AWE 64 PnP Gold */
{ . id = " CTL009e " , . devs = { { " CTL0044 " } , { " CTL0023 " } } } ,
/* Sound Blaster AWE 64 PnP Gold */
{ . id = " CTL00b2 " , . devs = { { " CTL0044 " } , { " CTL0023 " } } } ,
/* Sound Blaster AWE 64 PnP */
{ . id = " CTL00c1 " , . devs = { { " CTL0042 " } , { " CTL0022 " } } } ,
/* Sound Blaster AWE 64 PnP */
{ . id = " CTL00c3 " , . devs = { { " CTL0045 " } , { " CTL0022 " } } } ,
/* Sound Blaster AWE 64 PnP */
{ . id = " CTL00c5 " , . devs = { { " CTL0045 " } , { " CTL0022 " } } } ,
/* Sound Blaster AWE 64 PnP */
{ . id = " CTL00c7 " , . devs = { { " CTL0045 " } , { " CTL0022 " } } } ,
/* Sound Blaster AWE 64 PnP */
{ . id = " CTL00e4 " , . devs = { { " CTL0045 " } , { " CTL0022 " } } } ,
/* Sound Blaster AWE 64 PnP */
{ . id = " CTL00e9 " , . devs = { { " CTL0045 " } , { " CTL0022 " } } } ,
/* Sound Blaster 16 PnP (AWE) */
{ . id = " CTL00ed " , . devs = { { " CTL0041 " } , { " CTL0070 " } } } ,
/* Generic entries */
{ . id = " CTLXXXX " , . devs = { { " CTL0031 " } , { " CTL0021 " } } } ,
{ . id = " CTLXXXX " , . devs = { { " CTL0041 " } , { " CTL0021 " } } } ,
{ . id = " CTLXXXX " , . devs = { { " CTL0042 " } , { " CTL0022 " } } } ,
{ . id = " CTLXXXX " , . devs = { { " CTL0044 " } , { " CTL0023 " } } } ,
{ . id = " CTLXXXX " , . devs = { { " CTL0045 " } , { " CTL0022 " } } } ,
# endif /* SNDRV_SBAWE */
{ . id = " " , }
} ;
MODULE_DEVICE_TABLE ( pnp_card , snd_sb16_pnpids ) ;
# endif /* CONFIG_PNP */
# ifdef SNDRV_SBAWE_EMU8000
# define DRIVER_NAME "snd-card-sbawe"
# else
# define DRIVER_NAME "snd-card-sb16"
# endif
# ifdef CONFIG_PNP
2012-12-06 21:35:21 +04:00
static int snd_card_sb16_pnp ( int dev , struct snd_card_sb16 * acard ,
struct pnp_card_link * card ,
const struct pnp_card_device_id * id )
2005-04-17 02:20:36 +04:00
{
struct pnp_dev * pdev ;
int err ;
acard - > dev = pnp_request_card_device ( card , id - > devs [ 0 ] . id , NULL ) ;
2007-11-30 19:59:25 +03:00
if ( acard - > dev = = NULL )
2005-04-17 02:20:36 +04:00
return - ENODEV ;
2007-11-30 19:59:25 +03:00
2005-04-17 02:20:36 +04:00
# ifdef SNDRV_SBAWE_EMU8000
acard - > devwt = pnp_request_card_device ( card , id - > devs [ 1 ] . id , acard - > dev ) ;
# endif
/* Audio initialization */
pdev = acard - > dev ;
err = pnp_activate_dev ( pdev ) ;
if ( err < 0 ) {
snd_printk ( KERN_ERR PFX " AUDIO pnp configure failure \n " ) ;
return err ;
}
port [ dev ] = pnp_port_start ( pdev , 0 ) ;
mpu_port [ dev ] = pnp_port_start ( pdev , 1 ) ;
fm_port [ dev ] = pnp_port_start ( pdev , 2 ) ;
dma8 [ dev ] = pnp_dma ( pdev , 0 ) ;
dma16 [ dev ] = pnp_dma ( pdev , 1 ) ;
irq [ dev ] = pnp_irq ( pdev , 0 ) ;
snd_printdd ( " pnp SB16: port=0x%lx, mpu port=0x%lx, fm port=0x%lx \n " ,
port [ dev ] , mpu_port [ dev ] , fm_port [ dev ] ) ;
snd_printdd ( " pnp SB16: dma1=%i, dma2=%i, irq=%i \n " ,
dma8 [ dev ] , dma16 [ dev ] , irq [ dev ] ) ;
# ifdef SNDRV_SBAWE_EMU8000
/* WaveTable initialization */
pdev = acard - > devwt ;
if ( pdev ! = NULL ) {
err = pnp_activate_dev ( pdev ) ;
if ( err < 0 ) {
goto __wt_error ;
}
awe_port [ dev ] = pnp_port_start ( pdev , 0 ) ;
2006-06-13 01:50:27 +04:00
snd_printdd ( " pnp SB16: wavetable port=0x%llx \n " ,
( unsigned long long ) pnp_port_start ( pdev , 0 ) ) ;
2005-04-17 02:20:36 +04:00
} else {
__wt_error :
if ( pdev ) {
pnp_release_card_device ( pdev ) ;
snd_printk ( KERN_ERR PFX " WaveTable pnp configure failure \n " ) ;
}
acard - > devwt = NULL ;
awe_port [ dev ] = - 1 ;
}
# endif
return 0 ;
}
# endif /* CONFIG_PNP */
[ALSA] Add snd_card_set_generic_dev() call to ISA drivers
ISA,CMI8330 driver,ES18xx driver,OPL3SA2 driver,Sound Galaxy driver
Sound Scape driver,AD1848 driver,CS4231 driver,CS4236+ driver
ES1688 driver,GUS Classic driver,GUS Extreme driver,GUS MAX driver
AMD InterWave driver,Opti9xx drivers,SB16/AWE driver,SB8 driver
Wavefront drivers
- Added snd_card_set_generic_dev() call.
- Added SND_GENERIC_DRIVER to Kconfig.
- Clean up the error path in probe if necessary.
Signed-off-by: Takashi Iwai <tiwai@suse.de>
2005-09-05 19:19:20 +04:00
# ifdef CONFIG_PNP
# define is_isapnp_selected(dev) isapnp[dev]
# else
# define is_isapnp_selected(dev) 0
# endif
2014-01-29 16:03:56 +04:00
static int snd_sb16_card_new ( struct device * devptr , int dev ,
struct snd_card * * cardp )
2005-11-17 18:54:56 +03:00
{
2008-12-28 18:43:35 +03:00
struct snd_card * card ;
int err ;
2021-07-15 10:59:16 +03:00
err = snd_devm_card_new ( devptr , index [ dev ] , id [ dev ] , THIS_MODULE ,
sizeof ( struct snd_card_sb16 ) , & card ) ;
2008-12-28 18:43:35 +03:00
if ( err < 0 )
2008-12-28 18:47:30 +03:00
return err ;
* cardp = card ;
return 0 ;
2005-11-17 18:54:56 +03:00
}
2012-12-06 21:35:21 +04:00
static int snd_sb16_probe ( struct snd_card * card , int dev )
2005-04-17 02:20:36 +04:00
{
int xirq , xdma8 , xdma16 ;
2005-11-17 16:34:36 +03:00
struct snd_sb * chip ;
2005-11-17 18:54:56 +03:00
struct snd_card_sb16 * acard = card - > private_data ;
2005-11-17 16:34:36 +03:00
struct snd_opl3 * opl3 ;
struct snd_hwdep * synth = NULL ;
2005-04-17 02:20:36 +04:00
# ifdef CONFIG_SND_SB16_CSP
2005-11-17 16:34:36 +03:00
struct snd_hwdep * xcsp = NULL ;
2005-04-17 02:20:36 +04:00
# endif
unsigned long flags ;
int err ;
xirq = irq [ dev ] ;
xdma8 = dma8 [ dev ] ;
xdma16 = dma16 [ dev ] ;
2021-06-08 17:04:35 +03:00
err = snd_sbdsp_create ( card , port [ dev ] , xirq , snd_sb16dsp_interrupt ,
xdma8 , xdma16 , SB_HW_AUTO , & chip ) ;
if ( err < 0 )
2005-11-17 18:54:56 +03:00
return err ;
[ALSA] Add snd_card_set_generic_dev() call to ISA drivers
ISA,CMI8330 driver,ES18xx driver,OPL3SA2 driver,Sound Galaxy driver
Sound Scape driver,AD1848 driver,CS4231 driver,CS4236+ driver
ES1688 driver,GUS Classic driver,GUS Extreme driver,GUS MAX driver
AMD InterWave driver,Opti9xx drivers,SB16/AWE driver,SB8 driver
Wavefront drivers
- Added snd_card_set_generic_dev() call.
- Added SND_GENERIC_DRIVER to Kconfig.
- Clean up the error path in probe if necessary.
Signed-off-by: Takashi Iwai <tiwai@suse.de>
2005-09-05 19:19:20 +04:00
2005-11-17 18:54:56 +03:00
acard - > chip = chip ;
2005-04-17 02:20:36 +04:00
if ( chip - > hardware ! = SB_HW_16 ) {
[ALSA] Add snd_card_set_generic_dev() call to ISA drivers
ISA,CMI8330 driver,ES18xx driver,OPL3SA2 driver,Sound Galaxy driver
Sound Scape driver,AD1848 driver,CS4231 driver,CS4236+ driver
ES1688 driver,GUS Classic driver,GUS Extreme driver,GUS MAX driver
AMD InterWave driver,Opti9xx drivers,SB16/AWE driver,SB8 driver
Wavefront drivers
- Added snd_card_set_generic_dev() call.
- Added SND_GENERIC_DRIVER to Kconfig.
- Clean up the error path in probe if necessary.
Signed-off-by: Takashi Iwai <tiwai@suse.de>
2005-09-05 19:19:20 +04:00
snd_printk ( KERN_ERR PFX " SB 16 chip was not detected at 0x%lx \n " , port [ dev ] ) ;
2005-11-17 18:54:56 +03:00
return - ENODEV ;
2005-04-17 02:20:36 +04:00
}
chip - > mpu_port = mpu_port [ dev ] ;
2021-06-08 17:04:35 +03:00
if ( ! is_isapnp_selected ( dev ) ) {
err = snd_sb16dsp_configure ( chip ) ;
if ( err < 0 )
return err ;
}
[ALSA] Add snd_card_set_generic_dev() call to ISA drivers
ISA,CMI8330 driver,ES18xx driver,OPL3SA2 driver,Sound Galaxy driver
Sound Scape driver,AD1848 driver,CS4231 driver,CS4236+ driver
ES1688 driver,GUS Classic driver,GUS Extreme driver,GUS MAX driver
AMD InterWave driver,Opti9xx drivers,SB16/AWE driver,SB8 driver
Wavefront drivers
- Added snd_card_set_generic_dev() call.
- Added SND_GENERIC_DRIVER to Kconfig.
- Clean up the error path in probe if necessary.
Signed-off-by: Takashi Iwai <tiwai@suse.de>
2005-09-05 19:19:20 +04:00
2021-06-08 17:04:35 +03:00
err = snd_sb16dsp_pcm ( chip , 0 ) ;
if ( err < 0 )
2005-11-17 18:54:56 +03:00
return err ;
2005-04-17 02:20:36 +04:00
strcpy ( card - > driver ,
# ifdef SNDRV_SBAWE_EMU8000
awe_port [ dev ] > 0 ? " SB AWE " :
# endif
" SB16 " ) ;
strcpy ( card - > shortname , chip - > name ) ;
sprintf ( card - > longname , " %s at 0x%lx, irq %i, dma " ,
chip - > name ,
chip - > port ,
xirq ) ;
if ( xdma8 > = 0 )
sprintf ( card - > longname + strlen ( card - > longname ) , " %d " , xdma8 ) ;
if ( xdma16 > = 0 )
sprintf ( card - > longname + strlen ( card - > longname ) , " %s%d " ,
xdma8 > = 0 ? " & " : " " , xdma16 ) ;
if ( chip - > mpu_port > 0 & & chip - > mpu_port ! = SNDRV_AUTO_PORT ) {
2021-06-08 17:04:35 +03:00
err = snd_mpu401_uart_new ( card , 0 , MPU401_HW_SB ,
chip - > mpu_port ,
MPU401_INFO_IRQ_HOOK , - 1 ,
& chip - > rmidi ) ;
if ( err < 0 )
2005-11-17 18:54:56 +03:00
return err ;
2005-04-17 02:20:36 +04:00
chip - > rmidi_callback = snd_mpu401_uart_interrupt ;
}
# ifdef SNDRV_SBAWE_EMU8000
if ( awe_port [ dev ] = = SNDRV_AUTO_PORT )
awe_port [ dev ] = 0 ; /* disable */
# endif
if ( fm_port [ dev ] > 0 & & fm_port [ dev ] ! = SNDRV_AUTO_PORT ) {
if ( snd_opl3_create ( card , fm_port [ dev ] , fm_port [ dev ] + 2 ,
OPL3_HW_OPL3 ,
acard - > fm_res ! = NULL | | fm_port [ dev ] = = port [ dev ] ,
& opl3 ) < 0 ) {
snd_printk ( KERN_ERR PFX " no OPL device at 0x%lx-0x%lx \n " ,
fm_port [ dev ] , fm_port [ dev ] + 2 ) ;
} else {
# ifdef SNDRV_SBAWE_EMU8000
int seqdev = awe_port [ dev ] > 0 ? 2 : 1 ;
# else
int seqdev = 1 ;
# endif
2021-06-08 17:04:35 +03:00
err = snd_opl3_hwdep_new ( opl3 , 0 , seqdev , & synth ) ;
if ( err < 0 )
2005-11-17 18:54:56 +03:00
return err ;
2005-04-17 02:20:36 +04:00
}
}
2021-06-08 17:04:35 +03:00
err = snd_sbmixer_new ( chip ) ;
if ( err < 0 )
2005-11-17 18:54:56 +03:00
return err ;
2005-04-17 02:20:36 +04:00
# ifdef CONFIG_SND_SB16_CSP
/* CSP chip on SB16ASP/AWE32 */
if ( ( chip - > hardware = = SB_HW_16 ) & & csp [ dev ] ) {
snd_sb_csp_new ( chip , synth ! = NULL ? 1 : 0 , & xcsp ) ;
if ( xcsp ) {
chip - > csp = xcsp - > private_data ;
chip - > hardware = SB_HW_16CSP ;
} else {
snd_printk ( KERN_INFO PFX " warning - CSP chip not detected on soundcard #%i \n " , dev + 1 ) ;
}
}
# endif
# ifdef SNDRV_SBAWE_EMU8000
if ( awe_port [ dev ] > 0 ) {
2021-06-08 17:04:35 +03:00
err = snd_emu8000_new ( card , 1 , awe_port [ dev ] ,
seq_ports [ dev ] , NULL ) ;
if ( err < 0 ) {
2005-04-17 02:20:36 +04:00
snd_printk ( KERN_ERR PFX " fatal error - EMU-8000 synthesizer not detected at 0x%lx \n " , awe_port [ dev ] ) ;
[ALSA] Add snd_card_set_generic_dev() call to ISA drivers
ISA,CMI8330 driver,ES18xx driver,OPL3SA2 driver,Sound Galaxy driver
Sound Scape driver,AD1848 driver,CS4231 driver,CS4236+ driver
ES1688 driver,GUS Classic driver,GUS Extreme driver,GUS MAX driver
AMD InterWave driver,Opti9xx drivers,SB16/AWE driver,SB8 driver
Wavefront drivers
- Added snd_card_set_generic_dev() call.
- Added SND_GENERIC_DRIVER to Kconfig.
- Clean up the error path in probe if necessary.
Signed-off-by: Takashi Iwai <tiwai@suse.de>
2005-09-05 19:19:20 +04:00
2005-11-17 18:54:56 +03:00
return err ;
2005-04-17 02:20:36 +04:00
}
}
# endif
/* setup Mic AGC */
spin_lock_irqsave ( & chip - > mixer_lock , flags ) ;
snd_sbmixer_write ( chip , SB_DSP4_MIC_AGC ,
( snd_sbmixer_read ( chip , SB_DSP4_MIC_AGC ) & 0x01 ) |
( mic_agc [ dev ] ? 0x00 : 0x01 ) ) ;
spin_unlock_irqrestore ( & chip - > mixer_lock , flags ) ;
2021-06-08 17:04:35 +03:00
err = snd_card_register ( card ) ;
if ( err < 0 )
2005-11-17 18:54:56 +03:00
return err ;
[ALSA] Add snd_card_set_generic_dev() call to ISA drivers
ISA,CMI8330 driver,ES18xx driver,OPL3SA2 driver,Sound Galaxy driver
Sound Scape driver,AD1848 driver,CS4231 driver,CS4236+ driver
ES1688 driver,GUS Classic driver,GUS Extreme driver,GUS MAX driver
AMD InterWave driver,Opti9xx drivers,SB16/AWE driver,SB8 driver
Wavefront drivers
- Added snd_card_set_generic_dev() call.
- Added SND_GENERIC_DRIVER to Kconfig.
- Clean up the error path in probe if necessary.
Signed-off-by: Takashi Iwai <tiwai@suse.de>
2005-09-05 19:19:20 +04:00
2005-04-17 02:20:36 +04:00
return 0 ;
2005-11-17 18:54:56 +03:00
}
# ifdef CONFIG_PM
static int snd_sb16_suspend ( struct snd_card * card , pm_message_t state )
{
struct snd_card_sb16 * acard = card - > private_data ;
struct snd_sb * chip = acard - > chip ;
[ALSA] Add snd_card_set_generic_dev() call to ISA drivers
ISA,CMI8330 driver,ES18xx driver,OPL3SA2 driver,Sound Galaxy driver
Sound Scape driver,AD1848 driver,CS4231 driver,CS4236+ driver
ES1688 driver,GUS Classic driver,GUS Extreme driver,GUS MAX driver
AMD InterWave driver,Opti9xx drivers,SB16/AWE driver,SB8 driver
Wavefront drivers
- Added snd_card_set_generic_dev() call.
- Added SND_GENERIC_DRIVER to Kconfig.
- Clean up the error path in probe if necessary.
Signed-off-by: Takashi Iwai <tiwai@suse.de>
2005-09-05 19:19:20 +04:00
2005-11-17 18:54:56 +03:00
snd_power_change_state ( card , SNDRV_CTL_POWER_D3hot ) ;
snd_sbmixer_suspend ( chip ) ;
return 0 ;
2005-04-17 02:20:36 +04:00
}
2005-11-17 18:54:56 +03:00
static int snd_sb16_resume ( struct snd_card * card )
2005-04-17 02:20:36 +04:00
{
2005-11-17 18:54:56 +03:00
struct snd_card_sb16 * acard = card - > private_data ;
struct snd_sb * chip = acard - > chip ;
2005-04-17 02:20:36 +04:00
2005-11-17 18:54:56 +03:00
snd_sbdsp_reset ( chip ) ;
snd_sbmixer_resume ( chip ) ;
snd_power_change_state ( card , SNDRV_CTL_POWER_D0 ) ;
return 0 ;
}
# endif
2012-12-06 21:35:21 +04:00
static int snd_sb16_isa_probe1 ( int dev , struct device * pdev )
2005-11-17 18:54:56 +03:00
{
struct snd_card_sb16 * acard ;
struct snd_card * card ;
int err ;
2014-01-29 16:03:56 +04:00
err = snd_sb16_card_new ( pdev , dev , & card ) ;
2008-12-28 18:47:30 +03:00
if ( err < 0 )
return err ;
2005-11-17 18:54:56 +03:00
acard = card - > private_data ;
/* non-PnP FM port address is hardwired with base port address */
fm_port [ dev ] = port [ dev ] ;
/* block the 0x388 port to avoid PnP conflicts */
2021-07-15 10:59:16 +03:00
acard - > fm_res = devm_request_region ( card - > dev , 0x388 , 4 ,
" SoundBlaster FM " ) ;
2005-11-17 18:54:56 +03:00
# ifdef SNDRV_SBAWE_EMU8000
/* non-PnP AWE port address is hardwired with base port address */
awe_port [ dev ] = port [ dev ] + 0x400 ;
# endif
2021-06-08 17:04:35 +03:00
err = snd_sb16_probe ( card , dev ) ;
2021-07-15 10:59:16 +03:00
if ( err < 0 )
2005-11-17 18:54:56 +03:00
return err ;
2007-02-22 14:50:54 +03:00
dev_set_drvdata ( pdev , card ) ;
2005-11-17 18:54:56 +03:00
return 0 ;
2005-04-17 02:20:36 +04:00
}
2005-11-17 18:54:56 +03:00
2012-12-06 21:35:21 +04:00
static int snd_sb16_isa_match ( struct device * pdev , unsigned int dev )
2007-02-22 14:50:54 +03:00
{
return enable [ dev ] & & ! is_isapnp_selected ( dev ) ;
}
2012-12-06 21:35:21 +04:00
static int snd_sb16_isa_probe ( struct device * pdev , unsigned int dev )
2005-11-17 18:54:56 +03:00
{
int err ;
2020-01-05 17:48:00 +03:00
static const int possible_irqs [ ] = { 5 , 9 , 10 , 7 , - 1 } ;
static const int possible_dmas8 [ ] = { 1 , 3 , 0 , - 1 } ;
static const int possible_dmas16 [ ] = { 5 , 6 , 7 , - 1 } ;
2005-11-17 18:54:56 +03:00
if ( irq [ dev ] = = SNDRV_AUTO_IRQ ) {
2021-06-08 17:04:35 +03:00
irq [ dev ] = snd_legacy_find_free_irq ( possible_irqs ) ;
if ( irq [ dev ] < 0 ) {
2005-11-17 18:54:56 +03:00
snd_printk ( KERN_ERR PFX " unable to find a free IRQ \n " ) ;
return - EBUSY ;
}
}
if ( dma8 [ dev ] = = SNDRV_AUTO_DMA ) {
2021-06-08 17:04:35 +03:00
dma8 [ dev ] = snd_legacy_find_free_dma ( possible_dmas8 ) ;
if ( dma8 [ dev ] < 0 ) {
2005-11-17 18:54:56 +03:00
snd_printk ( KERN_ERR PFX " unable to find a free 8-bit DMA \n " ) ;
return - EBUSY ;
}
}
if ( dma16 [ dev ] = = SNDRV_AUTO_DMA ) {
2021-06-08 17:04:35 +03:00
dma16 [ dev ] = snd_legacy_find_free_dma ( possible_dmas16 ) ;
if ( dma16 [ dev ] < 0 ) {
2005-11-17 18:54:56 +03:00
snd_printk ( KERN_ERR PFX " unable to find a free 16-bit DMA \n " ) ;
return - EBUSY ;
}
}
if ( port [ dev ] ! = SNDRV_AUTO_PORT )
2007-02-22 14:50:54 +03:00
return snd_sb16_isa_probe1 ( dev , pdev ) ;
2005-11-17 18:54:56 +03:00
else {
2020-01-05 17:48:00 +03:00
static const int possible_ports [ ] = { 0x220 , 0x240 , 0x260 , 0x280 } ;
2005-11-17 18:54:56 +03:00
int i ;
for ( i = 0 ; i < ARRAY_SIZE ( possible_ports ) ; i + + ) {
port [ dev ] = possible_ports [ i ] ;
2007-02-22 14:50:54 +03:00
err = snd_sb16_isa_probe1 ( dev , pdev ) ;
2005-11-17 18:54:56 +03:00
if ( ! err )
return 0 ;
}
return err ;
}
}
# ifdef CONFIG_PM
2007-02-22 14:50:54 +03:00
static int snd_sb16_isa_suspend ( struct device * dev , unsigned int n ,
pm_message_t state )
2005-11-17 18:54:56 +03:00
{
2007-02-22 14:50:54 +03:00
return snd_sb16_suspend ( dev_get_drvdata ( dev ) , state ) ;
2005-11-17 18:54:56 +03:00
}
2007-02-22 14:50:54 +03:00
static int snd_sb16_isa_resume ( struct device * dev , unsigned int n )
2005-11-17 18:54:56 +03:00
{
2007-02-22 14:50:54 +03:00
return snd_sb16_resume ( dev_get_drvdata ( dev ) ) ;
2005-11-17 18:54:56 +03:00
}
# endif
# ifdef SNDRV_SBAWE
2007-03-20 13:33:46 +03:00
# define DEV_NAME "sbawe"
2005-11-17 18:54:56 +03:00
# else
2007-03-20 13:33:46 +03:00
# define DEV_NAME "sb16"
2005-11-17 18:54:56 +03:00
# endif
2007-02-22 14:50:54 +03:00
static struct isa_driver snd_sb16_isa_driver = {
. match = snd_sb16_isa_match ,
. probe = snd_sb16_isa_probe ,
2005-11-17 18:54:56 +03:00
# ifdef CONFIG_PM
2007-02-22 14:50:54 +03:00
. suspend = snd_sb16_isa_suspend ,
. resume = snd_sb16_isa_resume ,
2005-11-17 18:54:56 +03:00
# endif
. driver = {
2007-03-20 13:33:46 +03:00
. name = DEV_NAME
2005-11-17 18:54:56 +03:00
} ,
} ;
2005-04-17 02:20:36 +04:00
# ifdef CONFIG_PNP
2012-12-06 21:35:21 +04:00
static int snd_sb16_pnp_detect ( struct pnp_card_link * pcard ,
const struct pnp_card_device_id * pid )
2005-04-17 02:20:36 +04:00
{
static int dev ;
2005-11-17 18:54:56 +03:00
struct snd_card * card ;
2005-04-17 02:20:36 +04:00
int res ;
for ( ; dev < SNDRV_CARDS ; dev + + ) {
if ( ! enable [ dev ] | | ! isapnp [ dev ] )
continue ;
2014-01-29 16:03:56 +04:00
res = snd_sb16_card_new ( & pcard - > card - > dev , dev , & card ) ;
2008-12-28 18:47:30 +03:00
if ( res < 0 )
return res ;
2021-06-08 17:04:35 +03:00
res = snd_card_sb16_pnp ( dev , card - > private_data , pcard , pid ) ;
2021-07-15 10:59:16 +03:00
if ( res < 0 )
2021-06-08 17:04:35 +03:00
return res ;
res = snd_sb16_probe ( card , dev ) ;
2021-07-15 10:59:16 +03:00
if ( res < 0 )
2005-04-17 02:20:36 +04:00
return res ;
2005-11-17 18:54:56 +03:00
pnp_set_card_drvdata ( pcard , card ) ;
2005-04-17 02:20:36 +04:00
dev + + ;
return 0 ;
}
return - ENODEV ;
}
2005-11-17 18:54:56 +03:00
# ifdef CONFIG_PM
static int snd_sb16_pnp_suspend ( struct pnp_card_link * pcard , pm_message_t state )
{
return snd_sb16_suspend ( pnp_get_card_drvdata ( pcard ) , state ) ;
2005-04-17 02:20:36 +04:00
}
2005-11-17 18:54:56 +03:00
static int snd_sb16_pnp_resume ( struct pnp_card_link * pcard )
{
return snd_sb16_resume ( pnp_get_card_drvdata ( pcard ) ) ;
}
# endif
2005-04-17 02:20:36 +04:00
static struct pnp_card_driver sb16_pnpc_driver = {
. flags = PNP_DRIVER_RES_DISABLE ,
2005-11-17 18:54:56 +03:00
# ifdef SNDRV_SBAWE
. name = " sbawe " ,
# else
2005-04-17 02:20:36 +04:00
. name = " sb16 " ,
2005-11-17 18:54:56 +03:00
# endif
2005-04-17 02:20:36 +04:00
. id_table = snd_sb16_pnpids ,
. probe = snd_sb16_pnp_detect ,
2005-11-17 18:54:56 +03:00
# ifdef CONFIG_PM
. suspend = snd_sb16_pnp_suspend ,
. resume = snd_sb16_pnp_resume ,
# endif
2005-04-17 02:20:36 +04:00
} ;
# endif /* CONFIG_PNP */
static int __init alsa_card_sb16_init ( void )
{
2007-02-22 14:50:54 +03:00
int err ;
2005-04-17 02:20:36 +04:00
2007-02-22 14:50:54 +03:00
err = isa_register_driver ( & snd_sb16_isa_driver , SNDRV_CARDS ) ;
2005-04-17 02:20:36 +04:00
# ifdef CONFIG_PNP
2007-05-15 13:42:56 +04:00
if ( ! err )
isa_registered = 1 ;
2006-03-27 13:17:15 +04:00
err = pnp_register_card_driver ( & sb16_pnpc_driver ) ;
2007-02-22 14:50:54 +03:00
if ( ! err )
2005-12-07 11:13:42 +03:00
pnp_registered = 1 ;
2007-05-15 13:42:56 +04:00
if ( isa_registered )
err = 0 ;
2005-04-17 02:20:36 +04:00
# endif
2007-05-15 13:42:56 +04:00
return err ;
2005-04-17 02:20:36 +04:00
}
static void __exit alsa_card_sb16_exit ( void )
{
2007-02-22 14:50:54 +03:00
# ifdef CONFIG_PNP
if ( pnp_registered )
pnp_unregister_card_driver ( & sb16_pnpc_driver ) ;
2007-05-15 13:42:56 +04:00
if ( isa_registered )
2007-02-22 14:50:54 +03:00
# endif
2007-05-15 13:42:56 +04:00
isa_unregister_driver ( & snd_sb16_isa_driver ) ;
2005-04-17 02:20:36 +04:00
}
module_init ( alsa_card_sb16_init )
module_exit ( alsa_card_sb16_exit )