2005-04-17 02:20:36 +04:00
/*
* The driver for the EMU10K1 ( SB Live ! ) based 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
*
* Copyright ( c ) by James Courtier - Dutton < James @ superbug . demon . co . uk >
* Added support for Audigy 2 Value .
*
*
* This program is free software ; you can redistribute it and / or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation ; either version 2 of the License , or
* ( at your option ) any later version .
*
* This program is distributed in the hope that it will be useful ,
* but WITHOUT ANY WARRANTY ; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
* GNU General Public License for more details .
*
* You should have received a copy of the GNU General Public License
* along with this program ; if not , write to the Free Software
* Foundation , Inc . , 59 Temple Place , Suite 330 , Boston , MA 02111 - 1307 USA
*
*
*/
# include <linux/init.h>
# include <linux/pci.h>
# include <linux/time.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/emu10k1.h>
# include <sound/initval.h>
2007-10-15 11:50:19 +04:00
MODULE_AUTHOR ( " Jaroslav Kysela <perex@perex.cz> " ) ;
2005-04-17 02:20:36 +04:00
MODULE_DESCRIPTION ( " EMU10K1 " ) ;
MODULE_LICENSE ( " GPL " ) ;
MODULE_SUPPORTED_DEVICE ( " {{Creative Labs,SB Live!/PCI512/E-mu APS}, "
" {Creative Labs,SB Audigy}} " ) ;
2016-11-13 01:26:41 +03:00
# if IS_REACHABLE(CONFIG_SND_SEQUENCER)
2005-04-17 02:20:36 +04:00
# define ENABLE_SYNTH
# include <sound/emu10k1_synth.h>
# 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_PNP ; /* Enable this card */
2006-05-17 19:14:51 +04:00
static int extin [ SNDRV_CARDS ] ;
static int extout [ SNDRV_CARDS ] ;
2005-04-17 02:20:36 +04:00
static int seq_ports [ SNDRV_CARDS ] = { [ 0 . . . ( SNDRV_CARDS - 1 ) ] = 4 } ;
static int max_synth_voices [ SNDRV_CARDS ] = { [ 0 . . . ( SNDRV_CARDS - 1 ) ] = 64 } ;
static int max_buffer_size [ SNDRV_CARDS ] = { [ 0 . . . ( SNDRV_CARDS - 1 ) ] = 128 } ;
2011-12-15 07:19:36 +04:00
static bool enable_ir [ SNDRV_CARDS ] ;
2006-05-17 19:14:51 +04:00
static uint subsystem [ SNDRV_CARDS ] ; /* Force card subsystem model */
2010-08-18 16:08:17 +04:00
static uint delay_pcm_irq [ SNDRV_CARDS ] = { [ 0 . . . ( SNDRV_CARDS - 1 ) ] = 2 } ;
2005-04-17 02:20:36 +04:00
module_param_array ( index , int , NULL , 0444 ) ;
MODULE_PARM_DESC ( index , " Index value for the EMU10K1 soundcard. " ) ;
module_param_array ( id , charp , NULL , 0444 ) ;
MODULE_PARM_DESC ( id , " ID string for the EMU10K1 soundcard. " ) ;
module_param_array ( enable , bool , NULL , 0444 ) ;
MODULE_PARM_DESC ( enable , " Enable the EMU10K1 soundcard. " ) ;
module_param_array ( extin , int , NULL , 0444 ) ;
MODULE_PARM_DESC ( extin , " Available external inputs for FX8010. Zero=default. " ) ;
module_param_array ( extout , int , NULL , 0444 ) ;
MODULE_PARM_DESC ( extout , " Available external outputs for FX8010. Zero=default. " ) ;
module_param_array ( seq_ports , int , NULL , 0444 ) ;
MODULE_PARM_DESC ( seq_ports , " Allocated sequencer ports for internal synthesizer. " ) ;
module_param_array ( max_synth_voices , int , NULL , 0444 ) ;
MODULE_PARM_DESC ( max_synth_voices , " Maximum number of voices for WaveTable. " ) ;
module_param_array ( max_buffer_size , int , NULL , 0444 ) ;
MODULE_PARM_DESC ( max_buffer_size , " Maximum sample buffer size in MB. " ) ;
module_param_array ( enable_ir , bool , NULL , 0444 ) ;
MODULE_PARM_DESC ( enable_ir , " Enable IR. " ) ;
2005-07-07 00:21:51 +04:00
module_param_array ( subsystem , uint , NULL , 0444 ) ;
MODULE_PARM_DESC ( subsystem , " Force card subsystem model. " ) ;
2010-08-18 16:08:17 +04:00
module_param_array ( delay_pcm_irq , uint , NULL , 0444 ) ;
MODULE_PARM_DESC ( delay_pcm_irq , " Delay PCM interrupt by specified number of samples (default 0). " ) ;
2005-04-17 02:20:36 +04:00
/*
* Class 0401 : 1102 : 000 8 ( rev 00 ) Subsystem : 1102 : 1001 - > Audigy2 Value Model : SB0400
*/
2014-08-08 17:56:03 +04:00
static const struct pci_device_id snd_emu10k1_ids [ ] = {
2009-06-25 10:18:02 +04:00
{ PCI_VDEVICE ( CREATIVE , 0x0002 ) , 0 } , /* EMU10K1 */
{ PCI_VDEVICE ( CREATIVE , 0x0004 ) , 1 } , /* Audigy */
{ PCI_VDEVICE ( CREATIVE , 0x0008 ) , 1 } , /* Audigy 2 Value SB0400 */
2005-04-17 02:20:36 +04:00
{ 0 , }
} ;
/*
* Audigy 2 Value notes :
* A_IOCFG Input ( GPIO )
* 0x400 = Front analog jack plugged in . ( Green socket )
* 0x1000 = Read analog jack plugged in . ( Black socket )
* 0x2000 = Center / LFE analog jack plugged in . ( Orange socket )
* A_IOCFG Output ( GPIO )
* 0x60 = Sound out of front Left .
* Win sets it to 0 xXX61
*/
MODULE_DEVICE_TABLE ( pci , snd_emu10k1_ids ) ;
2012-12-06 21:35:10 +04:00
static int snd_card_emu10k1_probe ( struct pci_dev * pci ,
const struct pci_device_id * pci_id )
2005-04-17 02:20:36 +04:00
{
static int dev ;
2005-11-17 16:50:13 +03:00
struct snd_card * card ;
struct snd_emu10k1 * emu ;
2005-04-17 02:20:36 +04:00
# ifdef ENABLE_SYNTH
2005-11-17 16:50:13 +03:00
struct snd_seq_device * wave = NULL ;
2005-04-17 02:20:36 +04:00
# endif
int err ;
if ( dev > = SNDRV_CARDS )
return - ENODEV ;
if ( ! enable [ dev ] ) {
dev + + ;
return - ENOENT ;
}
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
if ( max_buffer_size [ dev ] < 32 )
max_buffer_size [ dev ] = 32 ;
else if ( max_buffer_size [ dev ] > 1024 )
max_buffer_size [ dev ] = 1024 ;
if ( ( err = snd_emu10k1_create ( card , pci , extin [ dev ] , extout [ dev ] ,
( long ) max_buffer_size [ dev ] * 1024 * 1024 ,
2005-07-07 00:21:51 +04:00
enable_ir [ dev ] , subsystem [ dev ] ,
2005-11-17 18:14:10 +03:00
& emu ) ) < 0 )
goto error ;
card - > private_data = emu ;
2010-08-18 16:08:17 +04:00
emu - > delay_pcm_irq = delay_pcm_irq [ dev ] & 0x1f ;
2015-01-02 14:24:49 +03:00
if ( ( err = snd_emu10k1_pcm ( emu , 0 ) ) < 0 )
2005-11-17 18:14:10 +03:00
goto error ;
2015-01-02 14:24:49 +03:00
if ( ( err = snd_emu10k1_pcm_mic ( emu , 1 ) ) < 0 )
2005-11-17 18:14:10 +03:00
goto error ;
2015-01-02 14:24:49 +03:00
if ( ( err = snd_emu10k1_pcm_efx ( emu , 2 ) ) < 0 )
2005-11-17 18:14:10 +03:00
goto error ;
2005-04-17 02:20:36 +04:00
/* This stores the periods table. */
2005-07-02 18:33:34 +04:00
if ( emu - > card_capabilities - > ca0151_chip ) { /* P16V */
2005-11-17 18:14:10 +03:00
if ( ( err = snd_dma_alloc_pages ( SNDRV_DMA_TYPE_DEV , snd_dma_pci_data ( pci ) ,
1024 , & emu - > p16v_buffer ) ) < 0 )
goto error ;
2005-04-17 02:20:36 +04:00
}
2005-11-17 18:14:10 +03:00
if ( ( err = snd_emu10k1_mixer ( emu , 0 , 3 ) ) < 0 )
goto error ;
2005-04-17 02:20:36 +04:00
2005-11-17 18:14:10 +03:00
if ( ( err = snd_emu10k1_timer ( emu , 0 ) ) < 0 )
goto error ;
2005-04-17 02:20:36 +04:00
2015-01-02 14:24:49 +03:00
if ( ( err = snd_emu10k1_pcm_multi ( emu , 3 ) ) < 0 )
2005-11-17 18:14:10 +03:00
goto error ;
if ( emu - > card_capabilities - > ca0151_chip ) { /* P16V */
2015-01-02 14:24:49 +03:00
if ( ( err = snd_p16v_pcm ( emu , 4 ) ) < 0 )
2005-11-17 18:14:10 +03:00
goto error ;
2005-04-17 02:20:36 +04:00
}
if ( emu - > audigy ) {
2005-11-17 18:14:10 +03:00
if ( ( err = snd_emu10k1_audigy_midi ( emu ) ) < 0 )
goto error ;
2005-04-17 02:20:36 +04:00
} else {
2005-11-17 18:14:10 +03:00
if ( ( err = snd_emu10k1_midi ( emu ) ) < 0 )
goto error ;
2005-04-17 02:20:36 +04:00
}
2015-01-02 14:24:49 +03:00
if ( ( err = snd_emu10k1_fx8010_new ( emu , 0 ) ) < 0 )
2005-11-17 18:14:10 +03:00
goto error ;
2005-04-17 02:20:36 +04:00
# ifdef ENABLE_SYNTH
if ( snd_seq_device_new ( card , 1 , SNDRV_SEQ_DEV_ID_EMU10K1_SYNTH ,
2005-11-17 16:50:13 +03:00
sizeof ( struct snd_emu10k1_synth_arg ) , & wave ) < 0 | |
2005-04-17 02:20:36 +04:00
wave = = NULL ) {
2014-02-25 20:02:09 +04:00
dev_warn ( emu - > card - > dev ,
" can't initialize Emu10k1 wavetable synth \n " ) ;
2005-04-17 02:20:36 +04:00
} else {
2005-11-17 16:50:13 +03:00
struct snd_emu10k1_synth_arg * arg ;
2005-04-17 02:20:36 +04:00
arg = SNDRV_SEQ_DEVICE_ARGPTR ( wave ) ;
strcpy ( wave - > name , " Emu-10k1 Synth " ) ;
arg - > hwptr = emu ;
arg - > index = 1 ;
arg - > seq_ports = seq_ports [ dev ] ;
arg - > max_voices = max_synth_voices [ dev ] ;
}
# endif
2015-04-27 14:00:09 +03:00
strlcpy ( card - > driver , emu - > card_capabilities - > driver ,
sizeof ( card - > driver ) ) ;
strlcpy ( card - > shortname , emu - > card_capabilities - > name ,
sizeof ( card - > shortname ) ) ;
2005-04-17 02:20:36 +04:00
snprintf ( card - > longname , sizeof ( card - > longname ) ,
" %s (rev.%d, serial:0x%x) at 0x%lx, irq %i " ,
card - > shortname , emu - > revision , emu - > serial , emu - > port , emu - > irq ) ;
2005-11-17 18:14:10 +03:00
if ( ( err = snd_card_register ( card ) ) < 0 )
goto error ;
2005-04-17 02:20:36 +04:00
pci_set_drvdata ( pci , card ) ;
dev + + ;
return 0 ;
2005-11-17 18:14:10 +03:00
error :
snd_card_free ( card ) ;
return err ;
2005-04-17 02:20:36 +04:00
}
2012-12-06 21:35:10 +04:00
static void snd_card_emu10k1_remove ( struct pci_dev * pci )
2005-04-17 02:20:36 +04:00
{
snd_card_free ( pci_get_drvdata ( pci ) ) ;
}
2005-11-17 18:14:10 +03:00
2012-08-14 20:12:04 +04:00
# ifdef CONFIG_PM_SLEEP
2012-07-02 17:20:37 +04:00
static int snd_emu10k1_suspend ( struct device * dev )
2005-11-17 18:14:10 +03:00
{
2012-07-02 17:20:37 +04:00
struct snd_card * card = dev_get_drvdata ( dev ) ;
2005-11-17 18:14:10 +03:00
struct snd_emu10k1 * emu = card - > private_data ;
snd_power_change_state ( card , SNDRV_CTL_POWER_D3hot ) ;
2012-11-22 20:18:49 +04:00
emu - > suspend = 1 ;
2005-11-17 18:14:10 +03:00
snd_pcm_suspend_all ( emu - > pcm ) ;
snd_pcm_suspend_all ( emu - > pcm_mic ) ;
snd_pcm_suspend_all ( emu - > pcm_efx ) ;
snd_pcm_suspend_all ( emu - > pcm_multi ) ;
snd_pcm_suspend_all ( emu - > pcm_p16v ) ;
snd_ac97_suspend ( emu - > ac97 ) ;
snd_emu10k1_efx_suspend ( emu ) ;
snd_emu10k1_suspend_regs ( emu ) ;
if ( emu - > card_capabilities - > ca0151_chip )
snd_p16v_suspend ( emu ) ;
snd_emu10k1_done ( emu ) ;
return 0 ;
}
2012-07-02 17:20:37 +04:00
static int snd_emu10k1_resume ( struct device * dev )
2005-11-17 18:14:10 +03:00
{
2012-07-02 17:20:37 +04:00
struct snd_card * card = dev_get_drvdata ( dev ) ;
2005-11-17 18:14:10 +03:00
struct snd_emu10k1 * emu = card - > private_data ;
snd_emu10k1_resume_init ( emu ) ;
snd_emu10k1_efx_resume ( emu ) ;
snd_ac97_resume ( emu - > ac97 ) ;
snd_emu10k1_resume_regs ( emu ) ;
if ( emu - > card_capabilities - > ca0151_chip )
snd_p16v_resume ( emu ) ;
2012-11-22 20:18:49 +04:00
emu - > suspend = 0 ;
2005-11-17 18:14:10 +03:00
snd_power_change_state ( card , SNDRV_CTL_POWER_D0 ) ;
return 0 ;
}
2012-07-02 17:20:37 +04:00
static SIMPLE_DEV_PM_OPS ( snd_emu10k1_pm , snd_emu10k1_suspend , snd_emu10k1_resume ) ;
# define SND_EMU10K1_PM_OPS &snd_emu10k1_pm
# else
# define SND_EMU10K1_PM_OPS NULL
2012-08-14 20:12:04 +04:00
# endif /* CONFIG_PM_SLEEP */
2005-11-17 18:14:10 +03:00
2012-04-24 14:25:00 +04:00
static struct pci_driver emu10k1_driver = {
2011-06-10 18:20:20 +04:00
. name = KBUILD_MODNAME ,
2005-04-17 02:20:36 +04:00
. id_table = snd_emu10k1_ids ,
. probe = snd_card_emu10k1_probe ,
2012-12-06 21:35:10 +04:00
. remove = snd_card_emu10k1_remove ,
2012-07-02 17:20:37 +04:00
. driver = {
. pm = SND_EMU10K1_PM_OPS ,
} ,
2005-04-17 02:20:36 +04:00
} ;
2012-04-24 14:25:00 +04:00
module_pci_driver ( emu10k1_driver ) ;