2019-05-19 15:08:20 +03:00
// SPDX-License-Identifier: GPL-2.0-only
2005-04-17 02:20:36 +04:00
/*
* ALSA driver for the Aureal Vortex family of soundprocessors .
* Author : Manuel Jander ( mjander @ embedded . cl )
*
* This driver is the result of the OpenVortex Project from Savannah
* ( savannah . nongnu . org / projects / openvortex ) . I would like to thank
* the developers of OpenVortex , Jeff Muizelaar and Kester Maddock , from
* whom i got plenty of help , and their codebase was invaluable .
* Thanks to the ALSA developers , they helped a lot working out
* the ALSA part .
* Thanks also to Sourceforge for maintaining the old binary drivers ,
* and the forum , where developers could comunicate .
*
* Now at least i can play Legacy DOOM with MIDI music : - )
*/
# include "au88x0.h"
# include <linux/init.h>
# include <linux/pci.h>
# include <linux/slab.h>
# include <linux/interrupt.h>
2011-07-15 21:13:37 +04:00
# include <linux/module.h>
2005-12-01 13:14:00 +03:00
# include <linux/dma-mapping.h>
2005-04-17 02:20:36 +04:00
# include <sound/initval.h>
// module parameters (see "Module Parameters")
static int index [ SNDRV_CARDS ] = SNDRV_DEFAULT_IDX ;
static char * id [ SNDRV_CARDS ] = SNDRV_DEFAULT_STR ;
2011-12-15 07:19:36 +04:00
static bool enable [ SNDRV_CARDS ] = SNDRV_DEFAULT_ENABLE_PNP ;
2005-04-17 02:20:36 +04:00
static int pcifix [ SNDRV_CARDS ] = { [ 0 . . . ( SNDRV_CARDS - 1 ) ] = 255 } ;
module_param_array ( index , int , NULL , 0444 ) ;
MODULE_PARM_DESC ( index , " Index value for " CARD_NAME " soundcard. " ) ;
module_param_array ( id , charp , NULL , 0444 ) ;
MODULE_PARM_DESC ( id , " ID string for " CARD_NAME " soundcard. " ) ;
module_param_array ( enable , bool , NULL , 0444 ) ;
MODULE_PARM_DESC ( enable , " Enable " CARD_NAME " soundcard. " ) ;
module_param_array ( pcifix , int , NULL , 0444 ) ;
MODULE_PARM_DESC ( pcifix , " Enable VIA-workaround for " CARD_NAME " soundcard. " ) ;
MODULE_DESCRIPTION ( " Aureal vortex " ) ;
MODULE_LICENSE ( " GPL " ) ;
MODULE_SUPPORTED_DEVICE ( " {{Aureal Semiconductor Inc., Aureal Vortex Sound Processor}} " ) ;
MODULE_DEVICE_TABLE ( pci , snd_vortex_ids ) ;
static void vortex_fix_latency ( struct pci_dev * vortex )
{
int rc ;
if ( ! ( rc = pci_write_config_byte ( vortex , 0x40 , 0xff ) ) ) {
2014-10-13 10:07:19 +04:00
dev_info ( & vortex - > dev , " vortex latency is 0xff \n " ) ;
2005-04-17 02:20:36 +04:00
} else {
2014-10-13 10:07:19 +04:00
dev_warn ( & vortex - > dev ,
" could not set vortex latency: pci error 0x%x \n " , rc ) ;
2005-04-17 02:20:36 +04:00
}
}
static void vortex_fix_agp_bridge ( struct pci_dev * via )
{
int rc ;
u8 value ;
/*
* only set the bit ( Extend PCI # 2 Internal Master for
* Efficient Handling of Dummy Requests ) if the can
* read the config and it is not already set
*/
if ( ! ( rc = pci_read_config_byte ( via , 0x42 , & value ) )
& & ( ( value & 0x10 )
| | ! ( rc = pci_write_config_byte ( via , 0x42 , value | 0x10 ) ) ) ) {
2014-10-13 10:07:19 +04:00
dev_info ( & via - > dev , " bridge config is 0x%x \n " , value | 0x10 ) ;
2005-04-17 02:20:36 +04:00
} else {
2014-10-13 10:07:19 +04:00
dev_warn ( & via - > dev ,
" could not set vortex latency: pci error 0x%x \n " , rc ) ;
2005-04-17 02:20:36 +04:00
}
}
2012-12-06 21:35:10 +04:00
static void snd_vortex_workaround ( struct pci_dev * vortex , int fix )
2005-04-17 02:20:36 +04:00
{
2005-09-07 16:28:33 +04:00
struct pci_dev * via = NULL ;
2005-04-17 02:20:36 +04:00
/* autodetect if workarounds are required */
if ( fix = = 255 ) {
/* VIA KT133 */
2005-09-07 16:28:33 +04:00
via = pci_get_device ( PCI_VENDOR_ID_VIA ,
PCI_DEVICE_ID_VIA_8365_1 , NULL ) ;
2005-04-17 02:20:36 +04:00
/* VIA Apollo */
if ( via = = NULL ) {
2005-09-07 16:28:33 +04:00
via = pci_get_device ( PCI_VENDOR_ID_VIA ,
PCI_DEVICE_ID_VIA_82C598_1 , NULL ) ;
/* AMD Irongate */
if ( via = = NULL )
via = pci_get_device ( PCI_VENDOR_ID_AMD ,
PCI_DEVICE_ID_AMD_FE_GATE_7007 , NULL ) ;
2005-04-17 02:20:36 +04:00
}
if ( via ) {
2014-10-13 10:07:19 +04:00
dev_info ( & vortex - > dev ,
" Activating latency workaround... \n " ) ;
2005-04-17 02:20:36 +04:00
vortex_fix_latency ( vortex ) ;
vortex_fix_agp_bridge ( via ) ;
}
} else {
if ( fix & 0x1 )
vortex_fix_latency ( vortex ) ;
2005-09-07 16:28:33 +04:00
if ( ( fix & 0x2 ) & & ( via = pci_get_device ( PCI_VENDOR_ID_VIA ,
PCI_DEVICE_ID_VIA_8365_1 , NULL ) ) )
2005-04-17 02:20:36 +04:00
vortex_fix_agp_bridge ( via ) ;
2005-09-07 16:28:33 +04:00
if ( ( fix & 0x4 ) & & ( via = pci_get_device ( PCI_VENDOR_ID_VIA ,
PCI_DEVICE_ID_VIA_82C598_1 , NULL ) ) )
2005-04-17 02:20:36 +04:00
vortex_fix_agp_bridge ( via ) ;
2005-09-07 16:28:33 +04:00
if ( ( fix & 0x8 ) & & ( via = pci_get_device ( PCI_VENDOR_ID_AMD ,
PCI_DEVICE_ID_AMD_FE_GATE_7007 , NULL ) ) )
2005-04-17 02:20:36 +04:00
vortex_fix_agp_bridge ( via ) ;
}
2005-09-07 16:28:33 +04:00
pci_dev_put ( via ) ;
2005-04-17 02:20:36 +04:00
}
// component-destructor
// (see "Management of Cards and Components")
2005-11-17 16:55:19 +03:00
static int snd_vortex_dev_free ( struct snd_device * device )
2005-04-17 02:20:36 +04:00
{
vortex_t * vortex = device - > device_data ;
vortex_gameport_unregister ( vortex ) ;
vortex_core_shutdown ( vortex ) ;
// Take down PCI interface.
free_irq ( vortex - > irq , vortex ) ;
2006-10-06 18:45:19 +04:00
iounmap ( vortex - > mmio ) ;
2005-04-17 02:20:36 +04:00
pci_release_regions ( vortex - > pci_dev ) ;
pci_disable_device ( vortex - > pci_dev ) ;
kfree ( vortex ) ;
return 0 ;
}
// chip-specific constructor
// (see "Management of Cards and Components")
2012-12-06 21:35:10 +04:00
static int
2005-11-17 16:55:19 +03:00
snd_vortex_create ( struct snd_card * card , struct pci_dev * pci , vortex_t * * rchip )
2005-04-17 02:20:36 +04:00
{
vortex_t * chip ;
int err ;
2020-01-03 11:16:25 +03:00
static const struct snd_device_ops ops = {
2005-04-17 02:20:36 +04:00
. dev_free = snd_vortex_dev_free ,
} ;
* rchip = NULL ;
// check PCI availability (DMA).
if ( ( err = pci_enable_device ( pci ) ) < 0 )
return err ;
ALSA: remove deprecated use of pci api
Replace occurences of the pci api by appropriate call to the dma api.
A simplified version of the semantic patch that finds this problem is as
follows: (http://coccinelle.lip6.fr)
@deprecated@
idexpression id;
position p;
@@
(
pci_dma_supported@p ( id, ...)
|
pci_alloc_consistent@p ( id, ...)
)
@bad1@
idexpression id;
position deprecated.p;
@@
...when != &id->dev
when != pci_get_drvdata ( id )
when != pci_enable_device ( id )
(
pci_dma_supported@p ( id, ...)
|
pci_alloc_consistent@p ( id, ...)
)
@depends on !bad1@
idexpression id;
expression direction;
position deprecated.p;
@@
(
- pci_dma_supported@p ( id,
+ dma_supported ( &id->dev,
...
+ , GFP_ATOMIC
)
|
- pci_alloc_consistent@p ( id,
+ dma_alloc_coherent ( &id->dev,
...
+ , GFP_ATOMIC
)
)
Signed-off-by: Quentin Lambert <lambert.quentin@gmail.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
2015-04-15 17:10:17 +03:00
if ( dma_set_mask ( & pci - > dev , DMA_BIT_MASK ( 32 ) ) < 0 | |
dma_set_coherent_mask ( & pci - > dev , DMA_BIT_MASK ( 32 ) ) < 0 ) {
2014-10-13 10:07:19 +04:00
dev_err ( card - > dev , " error to set DMA mask \n " ) ;
2006-01-13 19:16:29 +03:00
pci_disable_device ( pci ) ;
2005-04-17 02:20:36 +04:00
return - ENXIO ;
}
[ALSA] Replace with kzalloc() - pci stuff
AD1889 driver,ATIIXP driver,ATIIXP-modem driver,AZT3328 driver
BT87x driver,CMIPCI driver,CS4281 driver,ENS1370/1+ driver
ES1938 driver,ES1968 driver,FM801 driver,Intel8x0 driver
Intel8x0-modem driver,Maestro3 driver,SonicVibes driver,VIA82xx driver
VIA82xx-modem driver,AC97 Codec,AK4531 codec,au88x0 driver
CA0106 driver,CS46xx driver,EMU10K1/EMU10K2 driver,HDA Codec driver
HDA generic driver,HDA Intel driver,ICE1712 driver,ICE1724 driver
KORG1212 driver,MIXART driver,NM256 driver,Trident driver,YMFPCI driver
Replace kcalloc(1,..) with kzalloc().
Signed-off-by: Takashi Iwai <tiwai@suse.de>
2005-09-09 16:21:46 +04:00
chip = kzalloc ( sizeof ( * chip ) , GFP_KERNEL ) ;
2006-01-13 19:16:29 +03:00
if ( chip = = NULL ) {
pci_disable_device ( pci ) ;
2005-04-17 02:20:36 +04:00
return - ENOMEM ;
2006-01-13 19:16:29 +03:00
}
2005-04-17 02:20:36 +04:00
chip - > card = card ;
// initialize the stuff
chip - > pci_dev = pci ;
chip - > io = pci_resource_start ( pci , 0 ) ;
chip - > vendor = pci - > vendor ;
chip - > device = pci - > device ;
chip - > card = card ;
chip - > irq = - 1 ;
// (1) PCI resource allocation
// Get MMIO area
//
if ( ( err = pci_request_regions ( pci , CARD_NAME_SHORT ) ) ! = 0 )
goto regions_out ;
2008-09-29 03:20:09 +04:00
chip - > mmio = pci_ioremap_bar ( pci , 0 ) ;
2005-04-17 02:20:36 +04:00
if ( ! chip - > mmio ) {
2014-10-13 10:07:19 +04:00
dev_err ( card - > dev , " MMIO area remap failed. \n " ) ;
2005-04-17 02:20:36 +04:00
err = - ENOMEM ;
goto ioremap_out ;
}
/* Init audio core.
* This must be done before we do request_irq otherwise we can get spurious
2007-10-20 01:10:43 +04:00
* interrupts that we do not handle properly and make a mess of things */
2005-04-17 02:20:36 +04:00
if ( ( err = vortex_core_init ( chip ) ) ! = 0 ) {
2014-10-13 10:07:19 +04:00
dev_err ( card - > dev , " hw core init failed \n " ) ;
2005-04-17 02:20:36 +04:00
goto core_out ;
}
if ( ( err = request_irq ( pci - > irq , vortex_interrupt ,
2011-06-10 18:36:37 +04:00
IRQF_SHARED , KBUILD_MODNAME ,
2005-04-17 02:20:36 +04:00
chip ) ) ! = 0 ) {
2014-10-13 10:07:19 +04:00
dev_err ( card - > dev , " cannot grab irq \n " ) ;
2005-04-17 02:20:36 +04:00
goto irq_out ;
}
chip - > irq = pci - > irq ;
2019-12-10 09:34:04 +03:00
card - > sync_irq = chip - > irq ;
2005-04-17 02:20:36 +04:00
pci_set_master ( pci ) ;
// End of PCI setup.
// Register alsa root device.
if ( ( err = snd_device_new ( card , SNDRV_DEV_LOWLEVEL , chip , & ops ) ) < 0 ) {
goto alloc_out ;
}
* rchip = chip ;
return 0 ;
alloc_out :
free_irq ( chip - > irq , chip ) ;
irq_out :
vortex_core_shutdown ( chip ) ;
core_out :
iounmap ( chip - > mmio ) ;
ioremap_out :
pci_release_regions ( chip - > pci_dev ) ;
regions_out :
pci_disable_device ( chip - > pci_dev ) ;
//FIXME: this not the right place to unregister the gameport
vortex_gameport_unregister ( chip ) ;
2007-08-06 16:05:27 +04:00
kfree ( chip ) ;
2005-04-17 02:20:36 +04:00
return err ;
}
// constructor -- see "Constructor" sub-section
2012-12-06 21:35:10 +04:00
static int
2005-04-17 02:20:36 +04:00
snd_vortex_probe ( struct pci_dev * pci , const struct pci_device_id * pci_id )
{
static int dev ;
2005-11-17 16:55:19 +03:00
struct snd_card * card ;
2005-04-17 02:20:36 +04:00
vortex_t * chip ;
int err ;
// (1)
if ( dev > = SNDRV_CARDS )
return - ENODEV ;
if ( ! enable [ dev ] ) {
dev + + ;
return - ENOENT ;
}
// (2)
2014-01-29 17:20:19 +04:00
err = snd_card_new ( & pci - > dev , index [ dev ] , id [ dev ] , THIS_MODULE ,
0 , & card ) ;
2008-12-28 18:44:30 +03:00
if ( err < 0 )
return err ;
2005-04-17 02:20:36 +04:00
// (3)
if ( ( err = snd_vortex_create ( card , pci , & chip ) ) < 0 ) {
snd_card_free ( card ) ;
return err ;
}
snd_vortex_workaround ( pci , pcifix [ dev ] ) ;
2006-05-03 19:07:29 +04:00
// Card details needed in snd_vortex_midi
strcpy ( card - > driver , CARD_NAME_SHORT ) ;
sprintf ( card - > shortname , " Aureal Vortex %s " , CARD_NAME_SHORT ) ;
sprintf ( card - > longname , " %s at 0x%lx irq %i " ,
card - > shortname , chip - > io , chip - > irq ) ;
2005-04-17 02:20:36 +04:00
// (4) Alloc components.
2012-01-13 06:30:08 +04:00
err = snd_vortex_mixer ( chip ) ;
if ( err < 0 ) {
snd_card_free ( card ) ;
return err ;
}
2005-04-17 02:20:36 +04:00
// ADB pcm.
2012-01-13 06:35:01 +04:00
err = snd_vortex_new_pcm ( chip , VORTEX_PCM_ADB , NR_PCM ) ;
if ( err < 0 ) {
2005-04-17 02:20:36 +04:00
snd_card_free ( card ) ;
return err ;
}
# ifndef CHIP_AU8820
// ADB SPDIF
if ( ( err = snd_vortex_new_pcm ( chip , VORTEX_PCM_SPDIF , 1 ) ) < 0 ) {
snd_card_free ( card ) ;
return err ;
}
// A3D
if ( ( err = snd_vortex_new_pcm ( chip , VORTEX_PCM_A3D , NR_A3D ) ) < 0 ) {
snd_card_free ( card ) ;
return err ;
}
# endif
/*
// ADB I2S
if ( ( err = snd_vortex_new_pcm ( chip , VORTEX_PCM_I2S , 1 ) ) < 0 ) {
snd_card_free ( card ) ;
return err ;
}
*/
# ifndef CHIP_AU8810
// WT pcm.
if ( ( err = snd_vortex_new_pcm ( chip , VORTEX_PCM_WT , NR_WT ) ) < 0 ) {
snd_card_free ( card ) ;
return err ;
}
# endif
if ( ( err = snd_vortex_midi ( chip ) ) < 0 ) {
snd_card_free ( card ) ;
return err ;
}
vortex_gameport_register ( chip ) ;
#if 0
if ( snd_seq_device_new ( card , 1 , SNDRV_SEQ_DEV_ID_VORTEX_SYNTH ,
sizeof ( snd_vortex_synth_arg_t ) , & wave ) < 0
| | wave = = NULL ) {
2014-10-28 19:36:50 +03:00
dev_err ( card - > dev , " Can't initialize Aureal wavetable synth \n " ) ;
2005-04-17 02:20:36 +04:00
} else {
snd_vortex_synth_arg_t * arg ;
arg = SNDRV_SEQ_DEVICE_ARGPTR ( wave ) ;
strcpy ( wave - > name , " Aureal Synth " ) ;
arg - > hwptr = vortex ;
arg - > index = 1 ;
arg - > seq_ports = seq_ports [ dev ] ;
arg - > max_voices = max_synth_voices [ dev ] ;
}
# endif
// (5)
if ( ( err = pci_read_config_word ( pci , PCI_DEVICE_ID ,
& ( chip - > device ) ) ) < 0 ) {
snd_card_free ( card ) ;
return err ;
}
if ( ( err = pci_read_config_word ( pci , PCI_VENDOR_ID ,
& ( chip - > vendor ) ) ) < 0 ) {
snd_card_free ( card ) ;
return err ;
}
2007-06-09 02:46:36 +04:00
chip - > rev = pci - > revision ;
2005-04-17 02:20:36 +04:00
# ifdef CHIP_AU8830
if ( ( chip - > rev ) ! = 0xfe & & ( chip - > rev ) ! = 0xfa ) {
2014-10-13 10:07:19 +04:00
dev_alert ( card - > dev ,
" The revision (%x) of your card has not been seen before. \n " ,
2005-04-17 02:20:36 +04:00
chip - > rev ) ;
2014-10-13 10:07:19 +04:00
dev_alert ( card - > dev ,
" Please email the results of 'lspci -vv' to openvortex-dev@nongnu.org. \n " ) ;
2005-04-17 02:20:36 +04:00
snd_card_free ( card ) ;
err = - ENODEV ;
return err ;
}
# endif
// (6)
if ( ( err = snd_card_register ( card ) ) < 0 ) {
snd_card_free ( card ) ;
return err ;
}
// (7)
pci_set_drvdata ( pci , card ) ;
dev + + ;
vortex_connect_default ( chip , 1 ) ;
vortex_enable_int ( chip ) ;
return 0 ;
}
// destructor -- see "Destructor" sub-section
2012-12-06 21:35:10 +04:00
static void snd_vortex_remove ( struct pci_dev * pci )
2005-04-17 02:20:36 +04:00
{
snd_card_free ( pci_get_drvdata ( pci ) ) ;
}
// pci_driver definition
2012-04-24 14:25:00 +04:00
static struct pci_driver vortex_driver = {
2011-06-10 18:20:20 +04:00
. name = KBUILD_MODNAME ,
2005-04-17 02:20:36 +04:00
. id_table = snd_vortex_ids ,
. probe = snd_vortex_probe ,
2012-12-06 21:35:10 +04:00
. remove = snd_vortex_remove ,
2005-04-17 02:20:36 +04:00
} ;
2012-04-24 14:25:00 +04:00
module_pci_driver ( vortex_driver ) ;