2005-04-17 02:20:36 +04:00
/*
* Driver for generic ESS AudioDrive ESx688 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
*
*
* 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>
2005-11-17 19:13:30 +03:00
# include <linux/err.h>
2007-02-14 15:26:17 +03:00
# include <linux/isa.h>
2005-04-17 02:20:36 +04:00
# include <linux/time.h>
# include <linux/wait.h>
# include <linux/moduleparam.h>
2005-11-17 19:13:30 +03:00
# include <asm/dma.h>
2005-04-17 02:20:36 +04:00
# include <sound/core.h>
# include <sound/es1688.h>
# include <sound/mpu401.h>
# include <sound/opl3.h>
# define SNDRV_LEGACY_FIND_FREE_IRQ
# define SNDRV_LEGACY_FIND_FREE_DMA
# include <sound/initval.h>
2007-02-14 15:26:17 +03:00
# define CRD_NAME "Generic ESS ES1688 / ES688 AudioDrive"
# define DEV_NAME "es1688"
MODULE_DESCRIPTION ( CRD_NAME ) ;
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 " ) ;
MODULE_SUPPORTED_DEVICE ( " {{ESS,ES688 PnP AudioDrive,pnp:ESS0100}, "
" {ESS,ES1688 PnP AudioDrive,pnp:ESS0102}, "
" {ESS,ES688 AudioDrive,pnp:ESS6881}, "
" {ESS,ES1688 AudioDrive,pnp:ESS1681}} " ) ;
static int index [ SNDRV_CARDS ] = SNDRV_DEFAULT_IDX ; /* Index 0-MAX */
static char * id [ SNDRV_CARDS ] = SNDRV_DEFAULT_STR ; /* ID for this card */
static int enable [ SNDRV_CARDS ] = SNDRV_DEFAULT_ENABLE ; /* Enable this card */
static long port [ SNDRV_CARDS ] = SNDRV_DEFAULT_PORT ; /* 0x220,0x240,0x260 */
static long mpu_port [ SNDRV_CARDS ] = { [ 0 . . . ( SNDRV_CARDS - 1 ) ] = - 1 } ;
static int irq [ SNDRV_CARDS ] = SNDRV_DEFAULT_IRQ ; /* 5,7,9,10 */
static int mpu_irq [ SNDRV_CARDS ] = SNDRV_DEFAULT_IRQ ; /* 5,7,9,10 */
static int dma8 [ SNDRV_CARDS ] = SNDRV_DEFAULT_DMA ; /* 0,1,3 */
module_param_array ( index , int , NULL , 0444 ) ;
2007-02-14 15:26:17 +03:00
MODULE_PARM_DESC ( index , " Index value for " CRD_NAME " soundcard. " ) ;
2005-04-17 02:20:36 +04:00
module_param_array ( id , charp , NULL , 0444 ) ;
2007-02-14 15:26:17 +03:00
MODULE_PARM_DESC ( id , " ID string for " CRD_NAME " soundcard. " ) ;
2005-04-17 02:20:36 +04:00
module_param_array ( enable , bool , NULL , 0444 ) ;
2007-02-14 15:26:17 +03:00
MODULE_PARM_DESC ( enable , " Enable " CRD_NAME " soundcard. " ) ;
2005-04-17 02:20:36 +04:00
module_param_array ( port , long , NULL , 0444 ) ;
2007-02-14 15:26:17 +03:00
MODULE_PARM_DESC ( port , " Port # for " CRD_NAME " driver. " ) ;
2005-04-17 02:20:36 +04:00
module_param_array ( mpu_port , long , NULL , 0444 ) ;
2007-02-14 15:26:17 +03:00
MODULE_PARM_DESC ( mpu_port , " MPU-401 port # for " CRD_NAME " driver. " ) ;
2005-04-17 02:20:36 +04:00
module_param_array ( irq , int , NULL , 0444 ) ;
2007-02-14 15:26:17 +03:00
MODULE_PARM_DESC ( irq , " IRQ # for " CRD_NAME " driver. " ) ;
2005-04-17 02:20:36 +04:00
module_param_array ( mpu_irq , int , NULL , 0444 ) ;
2007-02-14 15:26:17 +03:00
MODULE_PARM_DESC ( mpu_irq , " MPU-401 IRQ # for " CRD_NAME " driver. " ) ;
2005-04-17 02:20:36 +04:00
module_param_array ( dma8 , int , NULL , 0444 ) ;
2007-02-14 15:26:17 +03:00
MODULE_PARM_DESC ( dma8 , " 8-bit DMA # for " CRD_NAME " driver. " ) ;
2005-12-07 11:13:42 +03:00
2007-02-14 15:26:17 +03:00
static int __devinit snd_es1688_match ( struct device * dev , unsigned int n )
{
return enable [ n ] ;
}
2005-04-17 02:20:36 +04:00
2007-02-19 15:01:45 +03:00
static int __devinit snd_es1688_legacy_create ( struct snd_card * card ,
struct device * dev , unsigned int n , struct snd_es1688 * * rchip )
2005-04-17 02:20:36 +04:00
{
2007-02-19 15:01:45 +03:00
static long possible_ports [ ] = { 0x220 , 0x240 , 0x260 } ;
2005-04-17 02:20:36 +04:00
static int possible_irqs [ ] = { 5 , 9 , 10 , 7 , - 1 } ;
static int possible_dmas [ ] = { 1 , 3 , 0 , - 1 } ;
2007-02-14 15:26:17 +03:00
2007-02-19 15:01:45 +03:00
int i , error ;
if ( irq [ n ] = = SNDRV_AUTO_IRQ ) {
irq [ n ] = snd_legacy_find_free_irq ( possible_irqs ) ;
if ( irq [ n ] < 0 ) {
2008-11-03 10:51:33 +03:00
dev_err ( dev , " unable to find a free IRQ \n " ) ;
2007-02-19 15:01:45 +03:00
return - EBUSY ;
}
}
if ( dma8 [ n ] = = SNDRV_AUTO_DMA ) {
dma8 [ n ] = snd_legacy_find_free_dma ( possible_dmas ) ;
if ( dma8 [ n ] < 0 ) {
2008-11-03 10:51:33 +03:00
dev_err ( dev , " unable to find a free DMA \n " ) ;
2007-02-19 15:01:45 +03:00
return - EBUSY ;
}
}
if ( port [ n ] ! = SNDRV_AUTO_PORT )
return snd_es1688_create ( card , port [ n ] , mpu_port [ n ] , irq [ n ] ,
mpu_irq [ n ] , dma8 [ n ] , ES1688_HW_AUTO , rchip ) ;
i = 0 ;
do {
port [ n ] = possible_ports [ i ] ;
error = snd_es1688_create ( card , port [ n ] , mpu_port [ n ] , irq [ n ] ,
mpu_irq [ n ] , dma8 [ n ] , ES1688_HW_AUTO , rchip ) ;
} while ( error < 0 & & + + i < ARRAY_SIZE ( possible_ports ) ) ;
return error ;
}
static int __devinit snd_es1688_probe ( struct device * dev , unsigned int n )
{
2005-11-17 16:31:42 +03:00
struct snd_card * card ;
struct snd_es1688 * chip ;
struct snd_opl3 * opl3 ;
struct snd_pcm * pcm ;
2007-02-14 15:26:17 +03:00
int error ;
card = snd_card_new ( index [ n ] , id [ n ] , THIS_MODULE , 0 ) ;
if ( ! card )
return - EINVAL ;
2005-04-17 02:20:36 +04:00
2007-02-19 15:01:45 +03:00
error = snd_es1688_legacy_create ( card , dev , n , & chip ) ;
2007-02-14 15:26:17 +03:00
if ( error < 0 )
goto out ;
[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
2007-02-14 15:26:17 +03:00
error = snd_es1688_pcm ( chip , 0 , & pcm ) ;
if ( error < 0 )
goto out ;
[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
2007-02-14 15:26:17 +03:00
error = snd_es1688_mixer ( chip ) ;
if ( error < 0 )
goto out ;
2005-04-17 02:20:36 +04:00
strcpy ( card - > driver , " ES1688 " ) ;
strcpy ( card - > shortname , pcm - > name ) ;
2007-02-19 15:01:45 +03:00
sprintf ( card - > longname , " %s at 0x%lx, irq %i, dma %i " , pcm - > name ,
chip - > port , chip - > irq , chip - > dma8 ) ;
2005-04-17 02:20:36 +04:00
2007-02-19 15:01:45 +03:00
if ( snd_opl3_create ( card , chip - > port , chip - > port + 2 ,
OPL3_HW_OPL3 , 0 , & opl3 ) < 0 )
2008-11-03 10:51:33 +03:00
dev_warn ( dev , " opl3 not detected at 0x%lx \n " , chip - > port ) ;
2007-02-14 15:26:17 +03:00
else {
error = snd_opl3_hwdep_new ( opl3 , 0 , 1 , NULL ) ;
if ( error < 0 )
goto out ;
2005-04-17 02:20:36 +04:00
}
2007-02-19 15:01:45 +03:00
if ( mpu_irq [ n ] > = 0 & & mpu_irq [ n ] ! = SNDRV_AUTO_IRQ & &
chip - > mpu_port > 0 ) {
error = snd_mpu401_uart_new ( card , 0 , MPU401_HW_ES1688 ,
chip - > mpu_port , 0 ,
mpu_irq [ n ] , IRQF_DISABLED , NULL ) ;
2007-02-14 15:26:17 +03:00
if ( error < 0 )
goto out ;
2005-04-17 02:20:36 +04:00
}
[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
2007-02-14 15:26:17 +03:00
snd_card_set_dev ( card , 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
2007-02-14 15:26:17 +03:00
error = snd_card_register ( card ) ;
if ( error < 0 )
goto out ;
[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
2007-02-14 15:26:17 +03:00
dev_set_drvdata ( dev , card ) ;
2005-04-17 02:20:36 +04:00
return 0 ;
2007-02-14 15:26:17 +03:00
out : snd_card_free ( card ) ;
return error ;
2005-04-17 02:20:36 +04:00
}
2007-02-14 15:26:17 +03:00
static int __devexit snd_es1688_remove ( struct device * dev , unsigned int n )
2005-04-17 02:20:36 +04:00
{
2007-02-14 15:26:17 +03:00
snd_card_free ( dev_get_drvdata ( dev ) ) ;
dev_set_drvdata ( dev , NULL ) ;
2005-11-17 19:13:30 +03:00
return 0 ;
2005-04-17 02:20:36 +04:00
}
2007-02-14 15:26:17 +03:00
static struct isa_driver snd_es1688_driver = {
. match = snd_es1688_match ,
2005-11-17 19:13:30 +03:00
. probe = snd_es1688_probe ,
2007-02-14 15:26:17 +03:00
. remove = snd_es1688_remove ,
#if 0 /* FIXME */
. suspend = snd_es1688_suspend ,
. resume = snd_es1688_resume ,
# endif
2005-11-17 19:13:30 +03:00
. driver = {
2007-02-14 15:26:17 +03:00
. name = DEV_NAME
}
2005-11-17 19:13:30 +03:00
} ;
2005-04-17 02:20:36 +04:00
static int __init alsa_card_es1688_init ( void )
{
2007-02-14 15:26:17 +03:00
return isa_register_driver ( & snd_es1688_driver , SNDRV_CARDS ) ;
2005-04-17 02:20:36 +04:00
}
static void __exit alsa_card_es1688_exit ( void )
{
2007-02-14 15:26:17 +03:00
isa_unregister_driver ( & snd_es1688_driver ) ;
2005-04-17 02:20:36 +04:00
}
2007-02-14 15:26:17 +03:00
module_init ( alsa_card_es1688_init ) ;
module_exit ( alsa_card_es1688_exit ) ;