2005-04-16 15:20:36 -07:00
/*
2007-10-15 09:50:19 +02:00
* Copyright ( c ) by Jaroslav Kysela < perex @ perex . cz >
2005-04-16 15:20:36 -07:00
* Creative Labs , Inc .
* Routines for control of EMU10K1 chips
*
2006-10-01 10:48:04 +01:00
* Copyright ( c ) by James Courtier - Dutton < James @ superbug . co . uk >
2005-04-16 15:20:36 -07:00
* Added support for Audigy 2 Value .
2006-10-01 10:48:04 +01:00
* Added EMU 1010 support .
* General bug fixes and enhancements .
2005-04-16 15:20:36 -07:00
*
*
* BUGS :
* - -
*
* TODO :
* - -
*
* 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
*
*/
2007-07-23 17:52:27 +01:00
# include <linux/sched.h>
# include <linux/kthread.h>
2005-04-16 15:20:36 -07:00
# include <linux/delay.h>
# include <linux/init.h>
2011-07-15 12:38:28 -04:00
# include <linux/module.h>
2005-04-16 15:20:36 -07:00
# include <linux/interrupt.h>
# include <linux/pci.h>
# include <linux/slab.h>
# include <linux/vmalloc.h>
2006-01-16 16:34:20 +01:00
# include <linux/mutex.h>
2005-04-16 15:20:36 -07:00
# include <sound/core.h>
# include <sound/emu10k1.h>
2006-10-01 10:48:04 +01:00
# include <linux/firmware.h>
2005-04-16 15:20:36 -07:00
# include "p16v.h"
2005-11-11 23:39:05 +01:00
# include "tina2.h"
2006-12-06 15:58:02 +00:00
# include "p17v.h"
2005-04-16 15:20:36 -07:00
2005-12-04 18:03:03 +01:00
2007-05-03 17:59:54 +02:00
# define HANA_FILENAME "emu / hana.fw"
# define DOCK_FILENAME "emu / audio_dock.fw"
2007-07-14 02:18:26 +01:00
# define EMU1010B_FILENAME "emu / emu1010b.fw"
# define MICRO_DOCK_FILENAME "emu / micro_dock.fw"
2007-11-04 14:08:26 +00:00
# define EMU0404_FILENAME "emu / emu0404.fw"
2007-07-14 10:24:49 +01:00
# define EMU1010_NOTEBOOK_FILENAME "emu / emu1010_notebook.fw"
2007-05-03 17:59:54 +02:00
MODULE_FIRMWARE ( HANA_FILENAME ) ;
MODULE_FIRMWARE ( DOCK_FILENAME ) ;
2007-07-14 02:18:26 +01:00
MODULE_FIRMWARE ( EMU1010B_FILENAME ) ;
MODULE_FIRMWARE ( MICRO_DOCK_FILENAME ) ;
2007-11-04 14:08:26 +00:00
MODULE_FIRMWARE ( EMU0404_FILENAME ) ;
2007-07-14 10:24:49 +01:00
MODULE_FIRMWARE ( EMU1010_NOTEBOOK_FILENAME ) ;
2007-05-03 17:59:54 +02:00
2005-04-16 15:20:36 -07:00
/*************************************************************************
* EMU10K1 init / done
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2008-10-23 18:51:00 +02:00
void snd_emu10k1_voice_init ( struct snd_emu10k1 * emu , int ch )
2005-04-16 15:20:36 -07:00
{
snd_emu10k1_ptr_write ( emu , DCYSUSV , ch , 0 ) ;
snd_emu10k1_ptr_write ( emu , IP , ch , 0 ) ;
snd_emu10k1_ptr_write ( emu , VTFT , ch , 0xffff ) ;
snd_emu10k1_ptr_write ( emu , CVCF , ch , 0xffff ) ;
snd_emu10k1_ptr_write ( emu , PTRX , ch , 0 ) ;
snd_emu10k1_ptr_write ( emu , CPF , ch , 0 ) ;
snd_emu10k1_ptr_write ( emu , CCR , ch , 0 ) ;
snd_emu10k1_ptr_write ( emu , PSST , ch , 0 ) ;
snd_emu10k1_ptr_write ( emu , DSL , ch , 0x10 ) ;
snd_emu10k1_ptr_write ( emu , CCCA , ch , 0 ) ;
snd_emu10k1_ptr_write ( emu , Z1 , ch , 0 ) ;
snd_emu10k1_ptr_write ( emu , Z2 , ch , 0 ) ;
snd_emu10k1_ptr_write ( emu , FXRT , ch , 0x32100000 ) ;
snd_emu10k1_ptr_write ( emu , ATKHLDM , ch , 0 ) ;
snd_emu10k1_ptr_write ( emu , DCYSUSM , ch , 0 ) ;
snd_emu10k1_ptr_write ( emu , IFATN , ch , 0xffff ) ;
snd_emu10k1_ptr_write ( emu , PEFE , ch , 0 ) ;
snd_emu10k1_ptr_write ( emu , FMMOD , ch , 0 ) ;
snd_emu10k1_ptr_write ( emu , TREMFRQ , ch , 24 ) ; /* 1 Hz */
snd_emu10k1_ptr_write ( emu , FM2FRQ2 , ch , 24 ) ; /* 1 Hz */
snd_emu10k1_ptr_write ( emu , TEMPENV , ch , 0 ) ;
/*** these are last so OFF prevents writing ***/
snd_emu10k1_ptr_write ( emu , LFOVAL2 , ch , 0 ) ;
snd_emu10k1_ptr_write ( emu , LFOVAL1 , ch , 0 ) ;
snd_emu10k1_ptr_write ( emu , ATKHLDV , ch , 0 ) ;
snd_emu10k1_ptr_write ( emu , ENVVOL , ch , 0 ) ;
snd_emu10k1_ptr_write ( emu , ENVVAL , ch , 0 ) ;
/* Audigy extra stuffs */
if ( emu - > audigy ) {
snd_emu10k1_ptr_write ( emu , 0x4c , ch , 0 ) ; /* ?? */
snd_emu10k1_ptr_write ( emu , 0x4d , ch , 0 ) ; /* ?? */
snd_emu10k1_ptr_write ( emu , 0x4e , ch , 0 ) ; /* ?? */
snd_emu10k1_ptr_write ( emu , 0x4f , ch , 0 ) ; /* ?? */
snd_emu10k1_ptr_write ( emu , A_FXRT1 , ch , 0x03020100 ) ;
snd_emu10k1_ptr_write ( emu , A_FXRT2 , ch , 0x3f3f3f3f ) ;
snd_emu10k1_ptr_write ( emu , A_SENDAMOUNTS , ch , 0 ) ;
}
}
2005-12-21 22:05:29 +01:00
static unsigned int spi_dac_init [ ] = {
0x00ff ,
0x02ff ,
0x0400 ,
0x0520 ,
0x0600 ,
0x08ff ,
0x0aff ,
0x0cff ,
0x0eff ,
0x10ff ,
0x1200 ,
0x1400 ,
0x1480 ,
0x1800 ,
0x1aff ,
0x1cff ,
0x1e00 ,
0x0530 ,
0x0602 ,
0x0622 ,
0x1400 ,
} ;
2006-12-06 15:58:02 +00:00
static unsigned int i2c_adc_init [ ] [ 2 ] = {
{ 0x17 , 0x00 } , /* Reset */
{ 0x07 , 0x00 } , /* Timeout */
{ 0x0b , 0x22 } , /* Interface control */
{ 0x0c , 0x22 } , /* Master mode control */
{ 0x0d , 0x08 } , /* Powerdown control */
{ 0x0e , 0xcf } , /* Attenuation Left 0x01 = -103dB, 0xff = 24dB */
{ 0x0f , 0xcf } , /* Attenuation Right 0.5dB steps */
{ 0x10 , 0x7b } , /* ALC Control 1 */
{ 0x11 , 0x00 } , /* ALC Control 2 */
{ 0x12 , 0x32 } , /* ALC Control 3 */
{ 0x13 , 0x00 } , /* Noise gate control */
{ 0x14 , 0xa6 } , /* Limiter control */
2008-10-23 18:51:00 +02:00
{ 0x15 , ADC_MUX_2 } , /* ADC Mixer control. Mic for A2ZS Notebook */
2006-12-06 15:58:02 +00:00
} ;
2008-10-23 18:51:00 +02:00
2005-11-17 16:14:10 +01:00
static int snd_emu10k1_init ( struct snd_emu10k1 * emu , int enable_ir , int resume )
2005-04-16 15:20:36 -07:00
{
unsigned int silent_page ;
2005-11-17 16:14:10 +01:00
int ch ;
2006-12-06 15:58:02 +00:00
u32 tmp ;
2005-04-16 15:20:36 -07:00
/* disable audio and lock cache */
2008-10-23 18:51:00 +02:00
outl ( HCFG_LOCKSOUNDCACHE | HCFG_LOCKTANKCACHE_MASK |
HCFG_MUTEBUTTONENABLE , emu - > port + HCFG ) ;
2005-04-16 15:20:36 -07:00
/* reset recording buffers */
snd_emu10k1_ptr_write ( emu , MICBS , 0 , ADCBS_BUFSIZE_NONE ) ;
snd_emu10k1_ptr_write ( emu , MICBA , 0 , 0 ) ;
snd_emu10k1_ptr_write ( emu , FXBS , 0 , ADCBS_BUFSIZE_NONE ) ;
snd_emu10k1_ptr_write ( emu , FXBA , 0 , 0 ) ;
snd_emu10k1_ptr_write ( emu , ADCBS , 0 , ADCBS_BUFSIZE_NONE ) ;
snd_emu10k1_ptr_write ( emu , ADCBA , 0 , 0 ) ;
/* disable channel interrupt */
outl ( 0 , emu - > port + INTE ) ;
snd_emu10k1_ptr_write ( emu , CLIEL , 0 , 0 ) ;
snd_emu10k1_ptr_write ( emu , CLIEH , 0 , 0 ) ;
snd_emu10k1_ptr_write ( emu , SOLEL , 0 , 0 ) ;
snd_emu10k1_ptr_write ( emu , SOLEH , 0 , 0 ) ;
2008-10-23 18:51:00 +02:00
if ( emu - > audigy ) {
2005-04-16 15:20:36 -07:00
/* set SPDIF bypass mode */
snd_emu10k1_ptr_write ( emu , SPBYPASS , 0 , SPBYPASS_FORMAT ) ;
/* enable rear left + rear right AC97 slots */
2005-11-17 16:14:10 +01:00
snd_emu10k1_ptr_write ( emu , AC97SLOT , 0 , AC97SLOT_REAR_RIGHT |
AC97SLOT_REAR_LEFT ) ;
2005-04-16 15:20:36 -07:00
}
/* init envelope engine */
2005-11-17 16:14:10 +01:00
for ( ch = 0 ; ch < NUM_G ; ch + + )
2005-04-16 15:20:36 -07:00
snd_emu10k1_voice_init ( emu , ch ) ;
2005-11-17 16:14:10 +01:00
snd_emu10k1_ptr_write ( emu , SPCS0 , 0 , emu - > spdif_bits [ 0 ] ) ;
snd_emu10k1_ptr_write ( emu , SPCS1 , 0 , emu - > spdif_bits [ 1 ] ) ;
snd_emu10k1_ptr_write ( emu , SPCS2 , 0 , emu - > spdif_bits [ 2 ] ) ;
2005-04-16 15:20:36 -07:00
2005-03-30 13:51:18 +02:00
if ( emu - > card_capabilities - > ca0151_chip ) { /* audigy2 */
2005-04-16 15:20:36 -07:00
/* Hacks for Alice3 to work independent of haP16V driver */
2008-10-23 18:51:00 +02:00
/* Setup SRCMulti_I2S SamplingRate */
2005-04-16 15:20:36 -07:00
tmp = snd_emu10k1_ptr_read ( emu , A_SPDIF_SAMPLERATE , 0 ) ;
tmp & = 0xfffff1ff ;
tmp | = ( 0x2 < < 9 ) ;
snd_emu10k1_ptr_write ( emu , A_SPDIF_SAMPLERATE , 0 , tmp ) ;
2008-10-23 18:51:00 +02:00
2005-04-16 15:20:36 -07:00
/* Setup SRCSel (Enable Spdif,I2S SRCMulti) */
snd_emu10k1_ptr20_write ( emu , SRCSel , 0 , 0x14 ) ;
/* Setup SRCMulti Input Audio Enable */
/* Use 0xFFFFFFFF to enable P16V sounds. */
snd_emu10k1_ptr20_write ( emu , SRCMULTI_ENABLE , 0 , 0xFFFFFFFF ) ;
/* Enabled Phased (8-channel) P16V playback */
outl ( 0x0201 , emu - > port + HCFG2 ) ;
/* Set playback routing. */
2005-04-10 15:43:35 +02:00
snd_emu10k1_ptr20_write ( emu , CAPTURE_P16V_SOURCE , 0 , 0x78e4 ) ;
2005-04-16 15:20:36 -07:00
}
2005-07-02 16:33:34 +02:00
if ( emu - > card_capabilities - > ca0108_chip ) { /* audigy2 Value */
2005-04-16 15:20:36 -07:00
/* Hacks for Alice3 to work independent of haP16V driver */
2014-02-25 17:02:09 +01:00
dev_info ( emu - > card - > dev , " Audigy2 value: Special config. \n " ) ;
2008-10-23 18:51:00 +02:00
/* Setup SRCMulti_I2S SamplingRate */
2005-04-16 15:20:36 -07:00
tmp = snd_emu10k1_ptr_read ( emu , A_SPDIF_SAMPLERATE , 0 ) ;
tmp & = 0xfffff1ff ;
tmp | = ( 0x2 < < 9 ) ;
snd_emu10k1_ptr_write ( emu , A_SPDIF_SAMPLERATE , 0 , tmp ) ;
/* Setup SRCSel (Enable Spdif,I2S SRCMulti) */
outl ( 0x600000 , emu - > port + 0x20 ) ;
outl ( 0x14 , emu - > port + 0x24 ) ;
/* Setup SRCMulti Input Audio Enable */
outl ( 0x7b0000 , emu - > port + 0x20 ) ;
outl ( 0xFF000000 , emu - > port + 0x24 ) ;
/* Setup SPDIF Out Audio Enable */
/* The Audigy 2 Value has a separate SPDIF out,
* so no need for a mixer switch
*/
outl ( 0x7a0000 , emu - > port + 0x20 ) ;
outl ( 0xFF000000 , emu - > port + 0x24 ) ;
tmp = inl ( emu - > port + A_IOCFG ) & ~ 0x8 ; /* Clear bit 3 */
outl ( tmp , emu - > port + A_IOCFG ) ;
}
2005-12-21 15:06:08 +01:00
if ( emu - > card_capabilities - > spi_dac ) { /* Audigy 2 ZS Notebook with DAC Wolfson WM8768/WM8568 */
2005-12-21 22:05:29 +01:00
int size , n ;
size = ARRAY_SIZE ( spi_dac_init ) ;
2006-10-01 10:48:04 +01:00
for ( n = 0 ; n < size ; n + + )
2005-12-21 22:05:29 +01:00
snd_emu10k1_spi_write ( emu , spi_dac_init [ n ] ) ;
2005-12-21 15:06:08 +01:00
snd_emu10k1_ptr20_write ( emu , 0x60 , 0 , 0x10 ) ;
2005-12-21 15:31:02 +01:00
/* Enable GPIOs
* GPIO0 : Unknown
* GPIO1 : Speakers - enabled .
* GPIO2 : Unknown
* GPIO3 : Unknown
* GPIO4 : IEC958 Output on .
* GPIO5 : Unknown
* GPIO6 : Unknown
* GPIO7 : Unknown
*/
outl ( 0x76 , emu - > port + A_IOCFG ) ; /* Windows uses 0x3f76 */
2005-12-21 15:06:08 +01:00
}
2006-12-06 15:58:02 +00:00
if ( emu - > card_capabilities - > i2c_adc ) { /* Audigy 2 ZS Notebook with ADC Wolfson WM8775 */
int size , n ;
snd_emu10k1_ptr20_write ( emu , P17V_I2S_SRC_SEL , 0 , 0x2020205f ) ;
tmp = inl ( emu - > port + A_IOCFG ) ;
outl ( tmp | 0x4 , emu - > port + A_IOCFG ) ; /* Set bit 2 for mic input */
tmp = inl ( emu - > port + A_IOCFG ) ;
size = ARRAY_SIZE ( i2c_adc_init ) ;
for ( n = 0 ; n < size ; n + + )
snd_emu10k1_i2c_write ( emu , i2c_adc_init [ n ] [ 0 ] , i2c_adc_init [ n ] [ 1 ] ) ;
2008-10-23 18:51:00 +02:00
for ( n = 0 ; n < 4 ; n + + ) {
emu - > i2c_capture_volume [ n ] [ 0 ] = 0xcf ;
emu - > i2c_capture_volume [ n ] [ 1 ] = 0xcf ;
2006-12-06 15:58:02 +00:00
}
}
2008-10-23 18:51:00 +02:00
2005-04-16 15:20:36 -07:00
snd_emu10k1_ptr_write ( emu , PTB , 0 , emu - > ptb_pages . addr ) ;
snd_emu10k1_ptr_write ( emu , TCB , 0 , 0 ) ; /* taken from original driver */
snd_emu10k1_ptr_write ( emu , TCBS , 0 , 4 ) ; /* taken from original driver */
silent_page = ( emu - > silent_page . addr < < 1 ) | MAP_PTI_MASK ;
for ( ch = 0 ; ch < NUM_G ; ch + + ) {
snd_emu10k1_ptr_write ( emu , MAPA , ch , silent_page ) ;
snd_emu10k1_ptr_write ( emu , MAPB , ch , silent_page ) ;
}
2007-11-04 14:08:26 +00:00
if ( emu - > card_capabilities - > emu_model ) {
2006-10-01 10:48:04 +01:00
outl ( HCFG_AUTOMUTE_ASYNC |
HCFG_EMU32_SLAVE |
HCFG_AUDIOENABLE , emu - > port + HCFG ) ;
2005-04-16 15:20:36 -07:00
/*
* Hokay , setup HCFG
* Mute Disable Audio = 0
* Lock Tank Memory = 1
* Lock Sound Memory = 0
* Auto Mute = 1
*/
2006-10-01 10:48:04 +01:00
} else if ( emu - > audigy ) {
2005-04-16 15:20:36 -07:00
if ( emu - > revision = = 4 ) /* audigy2 */
outl ( HCFG_AUDIOENABLE |
HCFG_AC3ENABLE_CDSPDIF |
HCFG_AC3ENABLE_GPSPDIF |
HCFG_AUTOMUTE | HCFG_JOYENABLE , emu - > port + HCFG ) ;
else
outl ( HCFG_AUTOMUTE | HCFG_JOYENABLE , emu - > port + HCFG ) ;
2005-07-02 16:33:34 +02:00
/* FIXME: Remove all these emu->model and replace it with a card recognition parameter,
* e . g . card_capabilities - > joystick */
2005-04-16 15:20:36 -07:00
} else if ( emu - > model = = 0x20 | |
emu - > model = = 0xc400 | |
( emu - > model = = 0x21 & & emu - > revision < 6 ) )
outl ( HCFG_LOCKTANKCACHE_MASK | HCFG_AUTOMUTE , emu - > port + HCFG ) ;
else
2008-10-23 18:51:00 +02:00
/* With on-chip joystick */
2005-04-16 15:20:36 -07:00
outl ( HCFG_LOCKTANKCACHE_MASK | HCFG_AUTOMUTE | HCFG_JOYENABLE , emu - > port + HCFG ) ;
if ( enable_ir ) { /* enable IR for SB Live */
2007-11-04 14:08:26 +00:00
if ( emu - > card_capabilities - > emu_model ) {
2006-10-01 10:48:04 +01:00
; /* Disable all access to A_IOCFG for the emu1010 */
2006-12-06 15:58:02 +00:00
} else if ( emu - > card_capabilities - > i2c_adc ) {
; /* Disable A_IOCFG for Audigy 2 ZS Notebook */
2005-12-04 18:03:03 +01:00
} else if ( emu - > audigy ) {
2005-04-16 15:20:36 -07:00
unsigned int reg = inl ( emu - > port + A_IOCFG ) ;
outl ( reg | A_IOCFG_GPOUT2 , emu - > port + A_IOCFG ) ;
udelay ( 500 ) ;
outl ( reg | A_IOCFG_GPOUT1 | A_IOCFG_GPOUT2 , emu - > port + A_IOCFG ) ;
udelay ( 100 ) ;
outl ( reg , emu - > port + A_IOCFG ) ;
} else {
unsigned int reg = inl ( emu - > port + HCFG ) ;
outl ( reg | HCFG_GPOUT2 , emu - > port + HCFG ) ;
udelay ( 500 ) ;
outl ( reg | HCFG_GPOUT1 | HCFG_GPOUT2 , emu - > port + HCFG ) ;
udelay ( 100 ) ;
outl ( reg , emu - > port + HCFG ) ;
2008-10-23 18:51:00 +02:00
}
2005-04-16 15:20:36 -07:00
}
2008-10-23 18:51:00 +02:00
2007-11-04 14:08:26 +00:00
if ( emu - > card_capabilities - > emu_model ) {
2006-10-01 10:48:04 +01:00
; /* Disable all access to A_IOCFG for the emu1010 */
2006-12-06 15:58:02 +00:00
} else if ( emu - > card_capabilities - > i2c_adc ) {
; /* Disable A_IOCFG for Audigy 2 ZS Notebook */
2005-12-04 18:03:03 +01:00
} else if ( emu - > audigy ) { /* enable analog output */
2005-04-16 15:20:36 -07:00
unsigned int reg = inl ( emu - > port + A_IOCFG ) ;
outl ( reg | A_IOCFG_GPOUT0 , emu - > port + A_IOCFG ) ;
}
2005-11-17 16:14:10 +01:00
return 0 ;
}
2005-04-16 15:20:36 -07:00
2005-11-17 16:14:10 +01:00
static void snd_emu10k1_audio_enable ( struct snd_emu10k1 * emu )
{
2005-04-16 15:20:36 -07:00
/*
* Enable the audio bit
*/
outl ( inl ( emu - > port + HCFG ) | HCFG_AUDIOENABLE , emu - > port + HCFG ) ;
/* Enable analog/digital outs on audigy */
2007-11-04 14:08:26 +00:00
if ( emu - > card_capabilities - > emu_model ) {
2006-10-01 10:48:04 +01:00
; /* Disable all access to A_IOCFG for the emu1010 */
2006-12-06 15:58:02 +00:00
} else if ( emu - > card_capabilities - > i2c_adc ) {
; /* Disable A_IOCFG for Audigy 2 ZS Notebook */
2005-12-04 18:03:03 +01:00
} else if ( emu - > audigy ) {
2005-04-16 15:20:36 -07:00
outl ( inl ( emu - > port + A_IOCFG ) & ~ 0x44 , emu - > port + A_IOCFG ) ;
2008-10-23 18:51:00 +02:00
2005-07-02 16:33:34 +02:00
if ( emu - > card_capabilities - > ca0151_chip ) { /* audigy2 */
2005-04-16 15:20:36 -07:00
/* Unmute Analog now. Set GPO6 to 1 for Apollo.
* This has to be done after init ALice3 I2SOut beyond 48 KHz .
* So , sequence is important . */
outl ( inl ( emu - > port + A_IOCFG ) | 0x0040 , emu - > port + A_IOCFG ) ;
2005-07-02 16:33:34 +02:00
} else if ( emu - > card_capabilities - > ca0108_chip ) { /* audigy2 value */
2005-04-16 15:20:36 -07:00
/* Unmute Analog now. */
outl ( inl ( emu - > port + A_IOCFG ) | 0x0060 , emu - > port + A_IOCFG ) ;
} else {
/* Disable routing from AC97 line out to Front speakers */
outl ( inl ( emu - > port + A_IOCFG ) | 0x0080 , emu - > port + A_IOCFG ) ;
}
}
2008-10-23 18:51:00 +02:00
2005-04-16 15:20:36 -07:00
#if 0
{
unsigned int tmp ;
/* FIXME: the following routine disables LiveDrive-II !! */
2008-10-23 18:51:00 +02:00
/* TOSLink detection */
2005-04-16 15:20:36 -07:00
emu - > tos_link = 0 ;
tmp = inl ( emu - > port + HCFG ) ;
if ( tmp & ( HCFG_GPINPUT0 | HCFG_GPINPUT1 ) ) {
outl ( tmp | 0x800 , emu - > port + HCFG ) ;
udelay ( 50 ) ;
if ( tmp ! = ( inl ( emu - > port + HCFG ) & ~ 0x800 ) ) {
emu - > tos_link = 1 ;
outl ( tmp , emu - > port + HCFG ) ;
}
}
}
# endif
snd_emu10k1_intr_enable ( emu , INTE_PCIERRORENABLE ) ;
}
2008-10-23 18:51:00 +02:00
int snd_emu10k1_done ( struct snd_emu10k1 * emu )
2005-04-16 15:20:36 -07:00
{
int ch ;
outl ( 0 , emu - > port + INTE ) ;
/*
* Shutdown the chip
*/
for ( ch = 0 ; ch < NUM_G ; ch + + )
snd_emu10k1_ptr_write ( emu , DCYSUSV , ch , 0 ) ;
for ( ch = 0 ; ch < NUM_G ; ch + + ) {
snd_emu10k1_ptr_write ( emu , VTFT , ch , 0 ) ;
snd_emu10k1_ptr_write ( emu , CVCF , ch , 0 ) ;
snd_emu10k1_ptr_write ( emu , PTRX , ch , 0 ) ;
snd_emu10k1_ptr_write ( emu , CPF , ch , 0 ) ;
}
/* reset recording buffers */
snd_emu10k1_ptr_write ( emu , MICBS , 0 , 0 ) ;
snd_emu10k1_ptr_write ( emu , MICBA , 0 , 0 ) ;
snd_emu10k1_ptr_write ( emu , FXBS , 0 , 0 ) ;
snd_emu10k1_ptr_write ( emu , FXBA , 0 , 0 ) ;
snd_emu10k1_ptr_write ( emu , FXWC , 0 , 0 ) ;
snd_emu10k1_ptr_write ( emu , ADCBS , 0 , ADCBS_BUFSIZE_NONE ) ;
snd_emu10k1_ptr_write ( emu , ADCBA , 0 , 0 ) ;
snd_emu10k1_ptr_write ( emu , TCBS , 0 , TCBS_BUFFSIZE_16K ) ;
snd_emu10k1_ptr_write ( emu , TCB , 0 , 0 ) ;
if ( emu - > audigy )
snd_emu10k1_ptr_write ( emu , A_DBG , 0 , A_DBG_SINGLE_STEP ) ;
else
snd_emu10k1_ptr_write ( emu , DBG , 0 , EMU10K1_DBG_SINGLE_STEP ) ;
/* disable channel interrupt */
snd_emu10k1_ptr_write ( emu , CLIEL , 0 , 0 ) ;
snd_emu10k1_ptr_write ( emu , CLIEH , 0 , 0 ) ;
snd_emu10k1_ptr_write ( emu , SOLEL , 0 , 0 ) ;
snd_emu10k1_ptr_write ( emu , SOLEH , 0 , 0 ) ;
/* disable audio and lock cache */
outl ( HCFG_LOCKSOUNDCACHE | HCFG_LOCKTANKCACHE_MASK | HCFG_MUTEBUTTONENABLE , emu - > port + HCFG ) ;
snd_emu10k1_ptr_write ( emu , PTB , 0 , 0 ) ;
return 0 ;
}
/*************************************************************************
* ECARD functional implementation
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/* In A1 Silicon, these bits are in the HC register */
# define HOOKN_BIT (1L << 12)
# define HANDN_BIT (1L << 11)
# define PULSEN_BIT (1L << 10)
# define EC_GDI1 (1 << 13)
# define EC_GDI0 (1 << 14)
# define EC_NUM_CONTROL_BITS 20
# define EC_AC3_DATA_SELN 0x0001L
# define EC_EE_DATA_SEL 0x0002L
# define EC_EE_CNTRL_SELN 0x0004L
# define EC_EECLK 0x0008L
# define EC_EECS 0x0010L
# define EC_EESDO 0x0020L
# define EC_TRIM_CSN 0x0040L
# define EC_TRIM_SCLK 0x0080L
# define EC_TRIM_SDATA 0x0100L
# define EC_TRIM_MUTEN 0x0200L
# define EC_ADCCAL 0x0400L
# define EC_ADCRSTN 0x0800L
# define EC_DACCAL 0x1000L
# define EC_DACMUTEN 0x2000L
# define EC_LEDN 0x4000L
# define EC_SPDIF0_SEL_SHIFT 15
# define EC_SPDIF1_SEL_SHIFT 17
# define EC_SPDIF0_SEL_MASK (0x3L << EC_SPDIF0_SEL_SHIFT)
# define EC_SPDIF1_SEL_MASK (0x7L << EC_SPDIF1_SEL_SHIFT)
# define EC_SPDIF0_SELECT(_x) (((_x) << EC_SPDIF0_SEL_SHIFT) & EC_SPDIF0_SEL_MASK)
# define EC_SPDIF1_SELECT(_x) (((_x) << EC_SPDIF1_SEL_SHIFT) & EC_SPDIF1_SEL_MASK)
# define EC_CURRENT_PROM_VERSION 0x01 / * Self-explanatory. This should
* be incremented any time the EEPROM ' s
* format is changed . */
# define EC_EEPROM_SIZE 0x40 /* ECARD EEPROM has 64 16-bit words */
/* Addresses for special values stored in to EEPROM */
# define EC_PROM_VERSION_ADDR 0x20 /* Address of the current prom version */
# define EC_BOARDREV0_ADDR 0x21 /* LSW of board rev */
# define EC_BOARDREV1_ADDR 0x22 /* MSW of board rev */
# define EC_LAST_PROMFILE_ADDR 0x2f
2008-10-23 18:51:00 +02:00
# define EC_SERIALNUM_ADDR 0x30 / * First word of serial number. The
2005-04-16 15:20:36 -07:00
* can be up to 30 characters in length
* and is stored as a NULL - terminated
* ASCII string . Any unused bytes must be
* filled with zeros */
# define EC_CHECKSUM_ADDR 0x3f /* Location at which checksum is stored */
2008-10-23 18:51:00 +02:00
/* Most of this stuff is pretty self-evident. According to the hardware
* dudes , we need to leave the ADCCAL bit low in order to avoid a DC
2005-04-16 15:20:36 -07:00
* offset problem . Weird .
*/
# define EC_RAW_RUN_MODE (EC_DACMUTEN | EC_ADCRSTN | EC_TRIM_MUTEN | \
EC_TRIM_CSN )
# define EC_DEFAULT_ADC_GAIN 0xC4C4
# define EC_DEFAULT_SPDIF0_SEL 0x0
# define EC_DEFAULT_SPDIF1_SEL 0x4
/**************************************************************************
* @ func Clock bits into the Ecard ' s control latch . The Ecard uses a
* control latch will is loaded bit - serially by toggling the Modem control
* lines from function 2 on the E8010 . This function hides these details
* and presents the illusion that we are actually writing to a distinct
* register .
*/
2008-10-23 18:51:00 +02:00
static void snd_emu10k1_ecard_write ( struct snd_emu10k1 * emu , unsigned int value )
2005-04-16 15:20:36 -07:00
{
unsigned short count ;
unsigned int data ;
unsigned long hc_port ;
unsigned int hc_value ;
hc_port = emu - > port + HCFG ;
hc_value = inl ( hc_port ) & ~ ( HOOKN_BIT | HANDN_BIT | PULSEN_BIT ) ;
outl ( hc_value , hc_port ) ;
for ( count = 0 ; count < EC_NUM_CONTROL_BITS ; count + + ) {
/* Set up the value */
data = ( ( value & 0x1 ) ? PULSEN_BIT : 0 ) ;
value > > = 1 ;
outl ( hc_value | data , hc_port ) ;
/* Clock the shift register */
outl ( hc_value | data | HANDN_BIT , hc_port ) ;
outl ( hc_value | data , hc_port ) ;
}
/* Latch the bits */
outl ( hc_value | HOOKN_BIT , hc_port ) ;
outl ( hc_value , hc_port ) ;
}
/**************************************************************************
* @ func Set the gain of the ECARD ' s CS3310 Trim / gain controller . The
* trim value consists of a 16 bit value which is composed of two
* 8 bit gain / trim values , one for the left channel and one for the
* right channel . The following table maps from the Gain / Attenuation
* value in decibels into the corresponding bit pattern for a single
* channel .
*/
2008-10-23 18:51:00 +02:00
static void snd_emu10k1_ecard_setadcgain ( struct snd_emu10k1 * emu ,
2005-04-16 15:20:36 -07:00
unsigned short gain )
{
unsigned int bit ;
/* Enable writing to the TRIM registers */
snd_emu10k1_ecard_write ( emu , emu - > ecard_ctrl & ~ EC_TRIM_CSN ) ;
/* Do it again to insure that we meet hold time requirements */
snd_emu10k1_ecard_write ( emu , emu - > ecard_ctrl & ~ EC_TRIM_CSN ) ;
for ( bit = ( 1 < < 15 ) ; bit ; bit > > = 1 ) {
unsigned int value ;
2008-10-23 18:51:00 +02:00
2005-04-16 15:20:36 -07:00
value = emu - > ecard_ctrl & ~ ( EC_TRIM_CSN | EC_TRIM_SDATA ) ;
if ( gain & bit )
value | = EC_TRIM_SDATA ;
/* Clock the bit */
snd_emu10k1_ecard_write ( emu , value ) ;
snd_emu10k1_ecard_write ( emu , value | EC_TRIM_SCLK ) ;
snd_emu10k1_ecard_write ( emu , value ) ;
}
snd_emu10k1_ecard_write ( emu , emu - > ecard_ctrl ) ;
}
2008-10-23 18:51:00 +02:00
static int snd_emu10k1_ecard_init ( struct snd_emu10k1 * emu )
2005-04-16 15:20:36 -07:00
{
unsigned int hc_value ;
/* Set up the initial settings */
emu - > ecard_ctrl = EC_RAW_RUN_MODE |
EC_SPDIF0_SELECT ( EC_DEFAULT_SPDIF0_SEL ) |
EC_SPDIF1_SELECT ( EC_DEFAULT_SPDIF1_SEL ) ;
2008-10-23 18:51:00 +02:00
/* Step 0: Set the codec type in the hardware control register
2005-04-16 15:20:36 -07:00
* and enable audio output */
hc_value = inl ( emu - > port + HCFG ) ;
outl ( hc_value | HCFG_AUDIOENABLE | HCFG_CODECFORMAT_I2S , emu - > port + HCFG ) ;
inl ( emu - > port + HCFG ) ;
/* Step 1: Turn off the led and deassert TRIM_CS */
snd_emu10k1_ecard_write ( emu , EC_ADCCAL | EC_LEDN | EC_TRIM_CSN ) ;
/* Step 2: Calibrate the ADC and DAC */
snd_emu10k1_ecard_write ( emu , EC_DACCAL | EC_LEDN | EC_TRIM_CSN ) ;
/* Step 3: Wait for awhile; XXX We can't get away with this
* under a real operating system ; we ' ll need to block and wait that
* way . */
snd_emu10k1_wait ( emu , 48000 ) ;
/* Step 4: Switch off the DAC and ADC calibration. Note
* That ADC_CAL is actually an inverted signal , so we assert
* it here to stop calibration . */
snd_emu10k1_ecard_write ( emu , EC_ADCCAL | EC_LEDN | EC_TRIM_CSN ) ;
/* Step 4: Switch into run mode */
snd_emu10k1_ecard_write ( emu , emu - > ecard_ctrl ) ;
/* Step 5: Set the analog input gain */
snd_emu10k1_ecard_setadcgain ( emu , EC_DEFAULT_ADC_GAIN ) ;
return 0 ;
}
2008-10-23 18:51:00 +02:00
static int snd_emu10k1_cardbus_init ( struct snd_emu10k1 * emu )
2005-10-31 10:27:41 +00:00
{
unsigned long special_port ;
unsigned int value ;
/* Special initialisation routine
* before the rest of the IO - Ports become active .
*/
special_port = emu - > port + 0x38 ;
value = inl ( special_port ) ;
outl ( 0x00d00000 , special_port ) ;
value = inl ( special_port ) ;
outl ( 0x00d00001 , special_port ) ;
value = inl ( special_port ) ;
outl ( 0x00d0005f , special_port ) ;
value = inl ( special_port ) ;
outl ( 0x00d0007f , special_port ) ;
value = inl ( special_port ) ;
outl ( 0x0090007f , special_port ) ;
value = inl ( special_port ) ;
2005-11-11 23:39:05 +01:00
snd_emu10k1_ptr20_write ( emu , TINA2_VOLUME , 0 , 0xfefefefe ) ; /* Defaults to 0x30303030 */
2007-11-10 17:55:14 +00:00
/* Delay to give time for ADC chip to switch on. It needs 113ms */
msleep ( 200 ) ;
2005-10-31 10:27:41 +00:00
return 0 ;
}
2013-04-24 07:55:20 +02:00
static int snd_emu1010_load_firmware ( struct snd_emu10k1 * emu ,
const struct firmware * fw_entry )
2005-12-04 18:03:03 +01:00
{
2006-10-01 10:48:04 +01:00
int n , i ;
int reg ;
int value ;
2007-11-04 14:08:26 +00:00
unsigned int write_post ;
unsigned long flags ;
2006-10-01 10:48:04 +01:00
2012-11-22 17:17:17 +01:00
if ( ! fw_entry )
return - EIO ;
2005-12-04 18:03:03 +01:00
2006-10-01 10:48:04 +01:00
/* The FPGA is a Xilinx Spartan IIE XC2S50E */
/* GPIO7 -> FPGA PGMN
* GPIO6 - > FPGA CCLK
* GPIO5 - > FPGA DIN
* FPGA CONFIG OFF - > FPGA PGMN
*/
2007-11-04 14:08:26 +00:00
spin_lock_irqsave ( & emu - > emu_lock , flags ) ;
2006-10-01 10:48:04 +01:00
outl ( 0x00 , emu - > port + A_IOCFG ) ; /* Set PGMN low for 1uS. */
2007-11-04 14:08:26 +00:00
write_post = inl ( emu - > port + A_IOCFG ) ;
udelay ( 100 ) ;
2006-10-01 10:48:04 +01:00
outl ( 0x80 , emu - > port + A_IOCFG ) ; /* Leave bit 7 set during netlist setup. */
2007-11-04 14:08:26 +00:00
write_post = inl ( emu - > port + A_IOCFG ) ;
2006-10-01 10:48:04 +01:00
udelay ( 100 ) ; /* Allow FPGA memory to clean */
2008-10-23 18:51:00 +02:00
for ( n = 0 ; n < fw_entry - > size ; n + + ) {
value = fw_entry - > data [ n ] ;
for ( i = 0 ; i < 8 ; i + + ) {
2006-10-01 10:48:04 +01:00
reg = 0x80 ;
if ( value & 0x1 )
reg = reg | 0x20 ;
2008-10-23 18:51:00 +02:00
value = value > > 1 ;
2006-10-01 10:48:04 +01:00
outl ( reg , emu - > port + A_IOCFG ) ;
2007-11-04 14:08:26 +00:00
write_post = inl ( emu - > port + A_IOCFG ) ;
2006-10-01 10:48:04 +01:00
outl ( reg | 0x40 , emu - > port + A_IOCFG ) ;
2007-11-04 14:08:26 +00:00
write_post = inl ( emu - > port + A_IOCFG ) ;
2006-10-01 10:48:04 +01:00
}
}
/* After programming, set GPIO bit 4 high again. */
outl ( 0x10 , emu - > port + A_IOCFG ) ;
2007-11-04 14:08:26 +00:00
write_post = inl ( emu - > port + A_IOCFG ) ;
spin_unlock_irqrestore ( & emu - > emu_lock , flags ) ;
2005-12-04 18:03:03 +01:00
return 0 ;
}
2007-12-14 12:43:00 +01:00
static int emu1010_firmware_thread ( void * data )
{
2008-10-23 18:51:00 +02:00
struct snd_emu10k1 * emu = data ;
2009-02-25 22:28:59 +01:00
u32 tmp , tmp2 , reg ;
2015-04-11 14:34:44 +02:00
u32 last_reg = 0 ;
2007-07-23 17:52:27 +01:00
int err ;
for ( ; ; ) {
/* Delay to allow Audio Dock to settle */
2007-11-04 14:08:26 +00:00
msleep_interruptible ( 1000 ) ;
2007-07-23 17:52:27 +01:00
if ( kthread_should_stop ( ) )
break ;
2012-11-22 21:21:20 +01:00
# ifdef CONFIG_PM_SLEEP
2012-11-22 17:18:49 +01:00
if ( emu - > suspend )
continue ;
2012-11-22 21:21:20 +01:00
# endif
2008-10-23 18:51:00 +02:00
snd_emu1010_fpga_read ( emu , EMU_HANA_IRQ_STATUS , & tmp ) ; /* IRQ Status */
snd_emu1010_fpga_read ( emu , EMU_HANA_OPTION_CARDS , & reg ) ; /* OPTIONS: Which cards are attached to the EMU */
2007-07-23 17:52:27 +01:00
if ( reg & EMU_HANA_OPTION_DOCK_OFFLINE ) {
/* Audio Dock attached */
/* Return to Audio Dock programming mode */
2014-02-25 17:02:09 +01:00
dev_info ( emu - > card - > dev ,
" emu1010: Loading Audio Dock Firmware \n " ) ;
2008-10-23 18:51:00 +02:00
snd_emu1010_fpga_write ( emu , EMU_HANA_FPGA_CONFIG , EMU_HANA_FPGA_CONFIG_AUDIODOCK ) ;
2013-04-24 07:55:20 +02:00
if ( ! emu - > dock_fw ) {
const char * filename = NULL ;
switch ( emu - > card_capabilities - > emu_model ) {
case EMU_MODEL_EMU1010 :
filename = DOCK_FILENAME ;
break ;
case EMU_MODEL_EMU1010B :
filename = MICRO_DOCK_FILENAME ;
break ;
case EMU_MODEL_EMU1616 :
filename = MICRO_DOCK_FILENAME ;
break ;
}
if ( filename ) {
err = request_firmware ( & emu - > dock_fw ,
filename ,
& emu - > pci - > dev ) ;
if ( err )
continue ;
}
}
if ( emu - > dock_fw ) {
err = snd_emu1010_load_firmware ( emu , emu - > dock_fw ) ;
if ( err )
continue ;
}
2007-07-23 17:52:27 +01:00
2008-10-23 18:51:00 +02:00
snd_emu1010_fpga_write ( emu , EMU_HANA_FPGA_CONFIG , 0 ) ;
snd_emu1010_fpga_read ( emu , EMU_HANA_IRQ_STATUS , & reg ) ;
2014-02-25 17:02:09 +01:00
dev_info ( emu - > card - > dev ,
" emu1010: EMU_HANA+DOCK_IRQ_STATUS = 0x%x \n " ,
reg ) ;
2007-07-23 17:52:27 +01:00
/* ID, should read & 0x7f = 0x55 when FPGA programmed. */
2008-10-23 18:51:00 +02:00
snd_emu1010_fpga_read ( emu , EMU_HANA_ID , & reg ) ;
2014-02-25 17:02:09 +01:00
dev_info ( emu - > card - > dev ,
" emu1010: EMU_HANA+DOCK_ID = 0x%x \n " , reg ) ;
2007-07-23 17:52:27 +01:00
if ( ( reg & 0x1f ) ! = 0x15 ) {
/* FPGA failed to be programmed */
2014-02-25 17:02:09 +01:00
dev_info ( emu - > card - > dev ,
" emu1010: Loading Audio Dock Firmware file failed, reg = 0x%x \n " ,
reg ) ;
2007-11-04 14:08:26 +00:00
continue ;
2007-07-23 17:52:27 +01:00
}
2014-02-25 17:02:09 +01:00
dev_info ( emu - > card - > dev ,
" emu1010: Audio Dock Firmware loaded \n " ) ;
2008-10-23 18:51:00 +02:00
snd_emu1010_fpga_read ( emu , EMU_DOCK_MAJOR_REV , & tmp ) ;
snd_emu1010_fpga_read ( emu , EMU_DOCK_MINOR_REV , & tmp2 ) ;
2014-02-25 17:02:09 +01:00
dev_info ( emu - > card - > dev , " Audio Dock ver: %u.%u \n " ,
2009-02-05 16:08:14 +01:00
tmp , tmp2 ) ;
2007-07-26 18:44:49 +01:00
/* Sync clocking between 1010 and Dock */
/* Allow DLL to settle */
msleep ( 10 ) ;
/* Unmute all. Default is muted after a firmware load */
2008-10-23 18:51:00 +02:00
snd_emu1010_fpga_write ( emu , EMU_HANA_UNMUTE , EMU_UNMUTE ) ;
2015-04-11 14:34:44 +02:00
} else if ( ! reg & & last_reg ) {
/* Audio Dock removed */
dev_info ( emu - > card - > dev ,
" emu1010: Audio Dock detached \n " ) ;
/* Unmute all */
snd_emu1010_fpga_write ( emu , EMU_HANA_UNMUTE , EMU_UNMUTE ) ;
2007-07-23 17:52:27 +01:00
}
2015-04-11 14:34:44 +02:00
last_reg = reg ;
2007-07-23 17:52:27 +01:00
}
2014-02-25 17:02:09 +01:00
dev_info ( emu - > card - > dev , " emu1010: firmware thread stopping \n " ) ;
2007-07-23 17:52:27 +01:00
return 0 ;
}
2007-06-11 12:21:20 +02:00
/*
* EMU - 1010 - details found out from this driver , official MS Win drivers ,
* testing the card :
*
* Audigy2 ( aka Alice2 ) :
* - - - - - - - - - - - - - - - - - - - - -
* * communication over PCI
* * conversion of 32 - bit data coming over EMU32 links from HANA FPGA
* to 2 x 16 - bit , using internal DSP instructions
* * slave mode , clock supplied by HANA
* * linked to HANA using :
* 32 x 32 - bit serial EMU32 output channels
* 16 x EMU32 input channels
* ( ? ) x I2S I / O channels ( ? )
*
* FPGA ( aka HANA ) :
* - - - - - - - - - - - - - - -
* * provides all ( ? ) physical inputs and outputs of the card
* ( ADC , DAC , SPDIF I / O , ADAT I / O , etc . )
* * provides clock signal for the card and Alice2
* * two crystals - for 44.1 kHz and 48 kHz multiples
* * provides internal routing of signal sources to signal destinations
* * inputs / outputs to Alice2 - see above
*
* Current status of the driver :
* - - - - - - - - - - - - - - - - - - - - - - - - - - - -
* * only 44.1 / 48 kHz supported ( the MS Win driver supports up to 192 kHz )
* * PCM device nb . 2 :
* 16 x 16 - bit playback - snd_emu10k1_fx8010_playback_ops
* 16 x 32 - bit capture - snd_emu10k1_capture_efx_ops
*/
2008-10-23 18:51:00 +02:00
static int snd_emu10k1_emu1010_init ( struct snd_emu10k1 * emu )
2005-12-04 18:03:03 +01:00
{
unsigned int i ;
2009-02-25 22:28:59 +01:00
u32 tmp , tmp2 , reg ;
2006-10-01 10:48:04 +01:00
int err ;
2014-02-25 17:02:09 +01:00
dev_info ( emu - > card - > dev , " emu1010: Special config. \n " ) ;
2006-10-01 10:48:04 +01:00
/* AC97 2.1, Any 16Meg of 4Gig address, Auto-Mute, EMU32 Slave,
* Lock Sound Memory Cache , Lock Tank Memory Cache ,
* Mute all codecs .
*/
2005-12-04 18:03:03 +01:00
outl ( 0x0005a00c , emu - > port + HCFG ) ;
2006-10-01 10:48:04 +01:00
/* AC97 2.1, Any 16Meg of 4Gig address, Auto-Mute, EMU32 Slave,
* Lock Tank Memory Cache ,
* Mute all codecs .
*/
2008-10-23 18:51:00 +02:00
outl ( 0x0005a004 , emu - > port + HCFG ) ;
2006-10-01 10:48:04 +01:00
/* AC97 2.1, Any 16Meg of 4Gig address, Auto-Mute, EMU32 Slave,
* Mute all codecs .
*/
2005-12-04 18:03:03 +01:00
outl ( 0x0005a000 , emu - > port + HCFG ) ;
2006-10-01 10:48:04 +01:00
/* AC97 2.1, Any 16Meg of 4Gig address, Auto-Mute, EMU32 Slave,
* Mute all codecs .
*/
2005-12-04 18:03:03 +01:00
outl ( 0x0005a000 , emu - > port + HCFG ) ;
2006-10-01 10:48:04 +01:00
/* Disable 48Volt power to Audio Dock */
2008-10-23 18:51:00 +02:00
snd_emu1010_fpga_write ( emu , EMU_HANA_DOCK_PWR , 0 ) ;
2006-10-01 10:48:04 +01:00
/* ID, should read & 0x7f = 0x55. (Bit 7 is the IRQ bit) */
2008-10-23 18:51:00 +02:00
snd_emu1010_fpga_read ( emu , EMU_HANA_ID , & reg ) ;
2014-02-25 17:02:09 +01:00
dev_dbg ( emu - > card - > dev , " reg1 = 0x%x \n " , reg ) ;
2007-07-14 10:24:49 +01:00
if ( ( reg & 0x3f ) = = 0x15 ) {
2006-10-01 10:48:04 +01:00
/* FPGA netlist already present so clear it */
/* Return to programming mode */
2008-10-23 18:51:00 +02:00
snd_emu1010_fpga_write ( emu , EMU_HANA_FPGA_CONFIG , 0x02 ) ;
2005-12-04 18:03:03 +01:00
}
2008-10-23 18:51:00 +02:00
snd_emu1010_fpga_read ( emu , EMU_HANA_ID , & reg ) ;
2014-02-25 17:02:09 +01:00
dev_dbg ( emu - > card - > dev , " reg2 = 0x%x \n " , reg ) ;
2007-07-14 10:24:49 +01:00
if ( ( reg & 0x3f ) = = 0x15 ) {
2006-10-01 10:48:04 +01:00
/* FPGA failed to return to programming mode */
2014-02-25 17:02:09 +01:00
dev_info ( emu - > card - > dev ,
" emu1010: FPGA failed to return to programming mode \n " ) ;
2006-10-01 10:48:04 +01:00
return - ENODEV ;
2005-12-04 18:03:03 +01:00
}
2014-02-25 17:02:09 +01:00
dev_info ( emu - > card - > dev , " emu1010: EMU_HANA_ID = 0x%x \n " , reg ) ;
2012-11-22 17:17:17 +01:00
if ( ! emu - > firmware ) {
const char * filename ;
switch ( emu - > card_capabilities - > emu_model ) {
case EMU_MODEL_EMU1010 :
filename = HANA_FILENAME ;
break ;
case EMU_MODEL_EMU1010B :
filename = EMU1010B_FILENAME ;
break ;
case EMU_MODEL_EMU1616 :
filename = EMU1010_NOTEBOOK_FILENAME ;
break ;
case EMU_MODEL_EMU0404 :
filename = EMU0404_FILENAME ;
break ;
default :
return - ENODEV ;
}
err = request_firmware ( & emu - > firmware , filename , & emu - > pci - > dev ) ;
if ( err ! = 0 ) {
2014-02-25 17:02:09 +01:00
dev_info ( emu - > card - > dev ,
" emu1010: firmware: %s not found. Err = %d \n " ,
filename , err ) ;
2012-11-22 17:17:17 +01:00
return err ;
}
2014-02-25 17:02:09 +01:00
dev_info ( emu - > card - > dev ,
" emu1010: firmware file = %s, size = 0x%zx \n " ,
2012-11-22 17:17:17 +01:00
filename , emu - > firmware - > size ) ;
2013-02-25 09:53:35 +01:00
}
2013-04-24 07:55:20 +02:00
err = snd_emu1010_load_firmware ( emu , emu - > firmware ) ;
2013-02-25 09:53:35 +01:00
if ( err ! = 0 ) {
2014-02-25 17:02:09 +01:00
dev_info ( emu - > card - > dev , " emu1010: Loading Firmware failed \n " ) ;
2013-02-25 09:53:35 +01:00
return err ;
2005-12-04 18:03:03 +01:00
}
2006-10-01 10:48:04 +01:00
/* ID, should read & 0x7f = 0x55 when FPGA programmed. */
2008-10-23 18:51:00 +02:00
snd_emu1010_fpga_read ( emu , EMU_HANA_ID , & reg ) ;
2007-07-14 10:24:49 +01:00
if ( ( reg & 0x3f ) ! = 0x15 ) {
2006-10-01 10:48:04 +01:00
/* FPGA failed to be programmed */
2014-02-25 17:02:09 +01:00
dev_info ( emu - > card - > dev ,
" emu1010: Loading Hana Firmware file failed, reg = 0x%x \n " ,
reg ) ;
2006-10-01 10:48:04 +01:00
return - ENODEV ;
2005-12-04 18:03:03 +01:00
}
2014-02-25 17:02:09 +01:00
dev_info ( emu - > card - > dev , " emu1010: Hana Firmware loaded \n " ) ;
2008-10-23 18:51:00 +02:00
snd_emu1010_fpga_read ( emu , EMU_HANA_MAJOR_REV , & tmp ) ;
snd_emu1010_fpga_read ( emu , EMU_HANA_MINOR_REV , & tmp2 ) ;
2014-02-25 17:02:09 +01:00
dev_info ( emu - > card - > dev , " emu1010: Hana version: %u.%u \n " , tmp , tmp2 ) ;
2006-10-01 10:48:04 +01:00
/* Enable 48Volt power to Audio Dock */
2008-10-23 18:51:00 +02:00
snd_emu1010_fpga_write ( emu , EMU_HANA_DOCK_PWR , EMU_HANA_DOCK_PWR_ON ) ;
2006-10-01 10:48:04 +01:00
2008-10-23 18:51:00 +02:00
snd_emu1010_fpga_read ( emu , EMU_HANA_OPTION_CARDS , & reg ) ;
2014-02-25 17:02:09 +01:00
dev_info ( emu - > card - > dev , " emu1010: Card options = 0x%x \n " , reg ) ;
2008-10-23 18:51:00 +02:00
snd_emu1010_fpga_read ( emu , EMU_HANA_OPTION_CARDS , & reg ) ;
2014-02-25 17:02:09 +01:00
dev_info ( emu - > card - > dev , " emu1010: Card options = 0x%x \n " , reg ) ;
2008-10-23 18:51:00 +02:00
snd_emu1010_fpga_read ( emu , EMU_HANA_OPTICAL_TYPE , & tmp ) ;
2007-07-23 20:30:22 +01:00
/* Optical -> ADAT I/O */
2007-07-26 18:31:39 +01:00
/* 0 : SPDIF
* 1 : ADAT
*/
emu - > emu1010 . optical_in = 1 ; /* IN_ADAT */
emu - > emu1010 . optical_out = 1 ; /* IN_ADAT */
tmp = 0 ;
tmp = ( emu - > emu1010 . optical_in ? EMU_HANA_OPTICAL_IN_ADAT : 0 ) |
( emu - > emu1010 . optical_out ? EMU_HANA_OPTICAL_OUT_ADAT : 0 ) ;
2008-10-23 18:51:00 +02:00
snd_emu1010_fpga_write ( emu , EMU_HANA_OPTICAL_TYPE , tmp ) ;
snd_emu1010_fpga_read ( emu , EMU_HANA_ADC_PADS , & tmp ) ;
2006-10-01 10:48:04 +01:00
/* Set no attenuation on Audio Dock pads. */
2008-10-23 18:51:00 +02:00
snd_emu1010_fpga_write ( emu , EMU_HANA_ADC_PADS , 0x00 ) ;
2006-10-09 23:08:00 +01:00
emu - > emu1010 . adc_pads = 0x00 ;
2008-10-23 18:51:00 +02:00
snd_emu1010_fpga_read ( emu , EMU_HANA_DOCK_MISC , & tmp ) ;
2006-10-01 10:48:04 +01:00
/* Unmute Audio dock DACs, Headphone source DAC-4. */
2008-10-23 18:51:00 +02:00
snd_emu1010_fpga_write ( emu , EMU_HANA_DOCK_MISC , 0x30 ) ;
snd_emu1010_fpga_write ( emu , EMU_HANA_DOCK_LEDS_2 , 0x12 ) ;
snd_emu1010_fpga_read ( emu , EMU_HANA_DAC_PADS , & tmp ) ;
2006-10-09 23:08:00 +01:00
/* DAC PADs. */
2008-10-23 18:51:00 +02:00
snd_emu1010_fpga_write ( emu , EMU_HANA_DAC_PADS , 0x0f ) ;
2006-10-09 23:08:00 +01:00
emu - > emu1010 . dac_pads = 0x0f ;
2008-10-23 18:51:00 +02:00
snd_emu1010_fpga_read ( emu , EMU_HANA_DOCK_MISC , & tmp ) ;
snd_emu1010_fpga_write ( emu , EMU_HANA_DOCK_MISC , 0x30 ) ;
snd_emu1010_fpga_read ( emu , EMU_HANA_SPDIF_MODE , & tmp ) ;
2006-10-01 10:48:04 +01:00
/* SPDIF Format. Set Consumer mode, 24bit, copy enable */
2008-10-23 18:51:00 +02:00
snd_emu1010_fpga_write ( emu , EMU_HANA_SPDIF_MODE , 0x10 ) ;
2006-10-01 10:48:04 +01:00
/* MIDI routing */
2008-10-23 18:51:00 +02:00
snd_emu1010_fpga_write ( emu , EMU_HANA_MIDI_IN , 0x19 ) ;
2006-10-01 10:48:04 +01:00
/* Unknown. */
2008-10-23 18:51:00 +02:00
snd_emu1010_fpga_write ( emu , EMU_HANA_MIDI_OUT , 0x0c ) ;
2011-02-24 22:15:42 -08:00
/* IRQ Enable: All on */
2008-10-23 18:51:00 +02:00
/* snd_emu1010_fpga_write(emu, 0x09, 0x0f ); */
2006-10-01 10:48:04 +01:00
/* IRQ Enable: All off */
2008-10-23 18:51:00 +02:00
snd_emu1010_fpga_write ( emu , EMU_HANA_IRQ_ENABLE , 0x00 ) ;
2006-10-01 10:48:04 +01:00
2008-10-23 18:51:00 +02:00
snd_emu1010_fpga_read ( emu , EMU_HANA_OPTION_CARDS , & reg ) ;
2014-02-25 17:02:09 +01:00
dev_info ( emu - > card - > dev , " emu1010: Card options3 = 0x%x \n " , reg ) ;
2006-10-01 10:48:04 +01:00
/* Default WCLK set to 48kHz. */
2008-10-23 18:51:00 +02:00
snd_emu1010_fpga_write ( emu , EMU_HANA_DEFCLOCK , 0x00 ) ;
2006-10-01 10:48:04 +01:00
/* Word Clock source, Internal 48kHz x1 */
2008-10-23 18:51:00 +02:00
snd_emu1010_fpga_write ( emu , EMU_HANA_WCLOCK , EMU_HANA_WCLOCK_INT_48K ) ;
/* snd_emu1010_fpga_write(emu, EMU_HANA_WCLOCK, EMU_HANA_WCLOCK_INT_48K | EMU_HANA_WCLOCK_4X); */
2006-10-01 10:48:04 +01:00
/* Audio Dock LEDs. */
2008-10-23 18:51:00 +02:00
snd_emu1010_fpga_write ( emu , EMU_HANA_DOCK_LEDS_2 , 0x12 ) ;
2005-12-04 18:03:03 +01:00
2006-10-01 10:48:04 +01:00
#if 0
/* For 96kHz */
snd_emu1010_fpga_link_dst_src_write ( emu ,
EMU_DST_ALICE2_EMU32_0 , EMU_SRC_HAMOA_ADC_LEFT1 ) ;
snd_emu1010_fpga_link_dst_src_write ( emu ,
EMU_DST_ALICE2_EMU32_1 , EMU_SRC_HAMOA_ADC_RIGHT1 ) ;
snd_emu1010_fpga_link_dst_src_write ( emu ,
EMU_DST_ALICE2_EMU32_4 , EMU_SRC_HAMOA_ADC_LEFT2 ) ;
snd_emu1010_fpga_link_dst_src_write ( emu ,
EMU_DST_ALICE2_EMU32_5 , EMU_SRC_HAMOA_ADC_RIGHT2 ) ;
# endif
#if 0
/* For 192kHz */
snd_emu1010_fpga_link_dst_src_write ( emu ,
EMU_DST_ALICE2_EMU32_0 , EMU_SRC_HAMOA_ADC_LEFT1 ) ;
snd_emu1010_fpga_link_dst_src_write ( emu ,
EMU_DST_ALICE2_EMU32_1 , EMU_SRC_HAMOA_ADC_RIGHT1 ) ;
snd_emu1010_fpga_link_dst_src_write ( emu ,
EMU_DST_ALICE2_EMU32_2 , EMU_SRC_HAMOA_ADC_LEFT2 ) ;
snd_emu1010_fpga_link_dst_src_write ( emu ,
EMU_DST_ALICE2_EMU32_3 , EMU_SRC_HAMOA_ADC_RIGHT2 ) ;
snd_emu1010_fpga_link_dst_src_write ( emu ,
EMU_DST_ALICE2_EMU32_4 , EMU_SRC_HAMOA_ADC_LEFT3 ) ;
snd_emu1010_fpga_link_dst_src_write ( emu ,
EMU_DST_ALICE2_EMU32_5 , EMU_SRC_HAMOA_ADC_RIGHT3 ) ;
snd_emu1010_fpga_link_dst_src_write ( emu ,
EMU_DST_ALICE2_EMU32_6 , EMU_SRC_HAMOA_ADC_LEFT4 ) ;
snd_emu1010_fpga_link_dst_src_write ( emu ,
EMU_DST_ALICE2_EMU32_7 , EMU_SRC_HAMOA_ADC_RIGHT4 ) ;
# endif
# if 1
/* For 48kHz */
snd_emu1010_fpga_link_dst_src_write ( emu ,
EMU_DST_ALICE2_EMU32_0 , EMU_SRC_DOCK_MIC_A1 ) ;
snd_emu1010_fpga_link_dst_src_write ( emu ,
EMU_DST_ALICE2_EMU32_1 , EMU_SRC_DOCK_MIC_B1 ) ;
snd_emu1010_fpga_link_dst_src_write ( emu ,
EMU_DST_ALICE2_EMU32_2 , EMU_SRC_HAMOA_ADC_LEFT2 ) ;
snd_emu1010_fpga_link_dst_src_write ( emu ,
EMU_DST_ALICE2_EMU32_3 , EMU_SRC_HAMOA_ADC_LEFT2 ) ;
snd_emu1010_fpga_link_dst_src_write ( emu ,
EMU_DST_ALICE2_EMU32_4 , EMU_SRC_DOCK_ADC1_LEFT1 ) ;
snd_emu1010_fpga_link_dst_src_write ( emu ,
EMU_DST_ALICE2_EMU32_5 , EMU_SRC_DOCK_ADC1_RIGHT1 ) ;
snd_emu1010_fpga_link_dst_src_write ( emu ,
EMU_DST_ALICE2_EMU32_6 , EMU_SRC_DOCK_ADC2_LEFT1 ) ;
snd_emu1010_fpga_link_dst_src_write ( emu ,
EMU_DST_ALICE2_EMU32_7 , EMU_SRC_DOCK_ADC2_RIGHT1 ) ;
2007-06-11 12:21:20 +02:00
/* Pavel Hofman - setting defaults for 8 more capture channels
* Defaults only , users will set their own values anyways , let ' s
* just copy / paste .
*/
2008-10-23 18:51:00 +02:00
2007-06-11 12:21:20 +02:00
snd_emu1010_fpga_link_dst_src_write ( emu ,
EMU_DST_ALICE2_EMU32_8 , EMU_SRC_DOCK_MIC_A1 ) ;
snd_emu1010_fpga_link_dst_src_write ( emu ,
EMU_DST_ALICE2_EMU32_9 , EMU_SRC_DOCK_MIC_B1 ) ;
snd_emu1010_fpga_link_dst_src_write ( emu ,
EMU_DST_ALICE2_EMU32_A , EMU_SRC_HAMOA_ADC_LEFT2 ) ;
snd_emu1010_fpga_link_dst_src_write ( emu ,
EMU_DST_ALICE2_EMU32_B , EMU_SRC_HAMOA_ADC_LEFT2 ) ;
snd_emu1010_fpga_link_dst_src_write ( emu ,
EMU_DST_ALICE2_EMU32_C , EMU_SRC_DOCK_ADC1_LEFT1 ) ;
snd_emu1010_fpga_link_dst_src_write ( emu ,
EMU_DST_ALICE2_EMU32_D , EMU_SRC_DOCK_ADC1_RIGHT1 ) ;
snd_emu1010_fpga_link_dst_src_write ( emu ,
EMU_DST_ALICE2_EMU32_E , EMU_SRC_DOCK_ADC2_LEFT1 ) ;
snd_emu1010_fpga_link_dst_src_write ( emu ,
EMU_DST_ALICE2_EMU32_F , EMU_SRC_DOCK_ADC2_RIGHT1 ) ;
2006-10-01 10:48:04 +01:00
# endif
#if 0
/* Original */
snd_emu1010_fpga_link_dst_src_write ( emu ,
EMU_DST_ALICE2_EMU32_4 , EMU_SRC_HANA_ADAT ) ;
snd_emu1010_fpga_link_dst_src_write ( emu ,
EMU_DST_ALICE2_EMU32_5 , EMU_SRC_HANA_ADAT + 1 ) ;
snd_emu1010_fpga_link_dst_src_write ( emu ,
EMU_DST_ALICE2_EMU32_6 , EMU_SRC_HANA_ADAT + 2 ) ;
snd_emu1010_fpga_link_dst_src_write ( emu ,
EMU_DST_ALICE2_EMU32_7 , EMU_SRC_HANA_ADAT + 3 ) ;
snd_emu1010_fpga_link_dst_src_write ( emu ,
EMU_DST_ALICE2_EMU32_8 , EMU_SRC_HANA_ADAT + 4 ) ;
snd_emu1010_fpga_link_dst_src_write ( emu ,
EMU_DST_ALICE2_EMU32_9 , EMU_SRC_HANA_ADAT + 5 ) ;
snd_emu1010_fpga_link_dst_src_write ( emu ,
EMU_DST_ALICE2_EMU32_A , EMU_SRC_HANA_ADAT + 6 ) ;
snd_emu1010_fpga_link_dst_src_write ( emu ,
EMU_DST_ALICE2_EMU32_B , EMU_SRC_HANA_ADAT + 7 ) ;
snd_emu1010_fpga_link_dst_src_write ( emu ,
EMU_DST_ALICE2_EMU32_C , EMU_SRC_DOCK_MIC_A1 ) ;
snd_emu1010_fpga_link_dst_src_write ( emu ,
EMU_DST_ALICE2_EMU32_D , EMU_SRC_DOCK_MIC_B1 ) ;
snd_emu1010_fpga_link_dst_src_write ( emu ,
EMU_DST_ALICE2_EMU32_E , EMU_SRC_HAMOA_ADC_LEFT2 ) ;
snd_emu1010_fpga_link_dst_src_write ( emu ,
EMU_DST_ALICE2_EMU32_F , EMU_SRC_HAMOA_ADC_LEFT2 ) ;
# endif
2008-10-23 18:51:00 +02:00
for ( i = 0 ; i < 0x20 ; i + + ) {
/* AudioDock Elink <- Silence */
snd_emu1010_fpga_link_dst_src_write ( emu , 0x0100 + i , EMU_SRC_SILENCE ) ;
2006-10-01 10:48:04 +01:00
}
2008-10-23 18:51:00 +02:00
for ( i = 0 ; i < 4 ; i + + ) {
2006-10-01 10:48:04 +01:00
/* Hana SPDIF Out <- Silence */
2008-10-23 18:51:00 +02:00
snd_emu1010_fpga_link_dst_src_write ( emu , 0x0200 + i , EMU_SRC_SILENCE ) ;
2006-10-01 10:48:04 +01:00
}
2008-10-23 18:51:00 +02:00
for ( i = 0 ; i < 7 ; i + + ) {
2006-10-01 10:48:04 +01:00
/* Hamoa DAC <- Silence */
2008-10-23 18:51:00 +02:00
snd_emu1010_fpga_link_dst_src_write ( emu , 0x0300 + i , EMU_SRC_SILENCE ) ;
2006-10-01 10:48:04 +01:00
}
2008-10-23 18:51:00 +02:00
for ( i = 0 ; i < 7 ; i + + ) {
2006-10-01 10:48:04 +01:00
/* Hana ADAT Out <- Silence */
snd_emu1010_fpga_link_dst_src_write ( emu , EMU_DST_HANA_ADAT + i , EMU_SRC_SILENCE ) ;
}
snd_emu1010_fpga_link_dst_src_write ( emu ,
EMU_DST_ALICE_I2S0_LEFT , EMU_SRC_DOCK_ADC1_LEFT1 ) ;
snd_emu1010_fpga_link_dst_src_write ( emu ,
EMU_DST_ALICE_I2S0_RIGHT , EMU_SRC_DOCK_ADC1_RIGHT1 ) ;
snd_emu1010_fpga_link_dst_src_write ( emu ,
EMU_DST_ALICE_I2S1_LEFT , EMU_SRC_DOCK_ADC2_LEFT1 ) ;
snd_emu1010_fpga_link_dst_src_write ( emu ,
EMU_DST_ALICE_I2S1_RIGHT , EMU_SRC_DOCK_ADC2_RIGHT1 ) ;
snd_emu1010_fpga_link_dst_src_write ( emu ,
EMU_DST_ALICE_I2S2_LEFT , EMU_SRC_DOCK_ADC3_LEFT1 ) ;
snd_emu1010_fpga_link_dst_src_write ( emu ,
EMU_DST_ALICE_I2S2_RIGHT , EMU_SRC_DOCK_ADC3_RIGHT1 ) ;
2008-10-23 18:51:00 +02:00
snd_emu1010_fpga_write ( emu , EMU_HANA_UNMUTE , 0x01 ) ; /* Unmute all */
snd_emu1010_fpga_read ( emu , EMU_HANA_OPTION_CARDS , & tmp ) ;
2006-10-01 10:48:04 +01:00
/* AC97 1.03, Any 32Meg of 2Gig address, Auto-Mute, EMU32 Slave,
* Lock Sound Memory Cache , Lock Tank Memory Cache ,
* Mute all codecs .
*/
2008-10-23 18:51:00 +02:00
outl ( 0x0000a000 , emu - > port + HCFG ) ;
2006-10-01 10:48:04 +01:00
/* AC97 1.03, Any 32Meg of 2Gig address, Auto-Mute, EMU32 Slave,
* Lock Sound Memory Cache , Lock Tank Memory Cache ,
* Un - Mute all codecs .
*/
2005-12-04 18:03:03 +01:00
outl ( 0x0000a001 , emu - > port + HCFG ) ;
2008-10-23 18:51:00 +02:00
2005-12-04 18:03:03 +01:00
/* Initial boot complete. Now patches */
2008-10-23 18:51:00 +02:00
snd_emu1010_fpga_read ( emu , EMU_HANA_OPTION_CARDS , & tmp ) ;
snd_emu1010_fpga_write ( emu , EMU_HANA_MIDI_IN , 0x19 ) ; /* MIDI Route */
snd_emu1010_fpga_write ( emu , EMU_HANA_MIDI_OUT , 0x0c ) ; /* Unknown */
snd_emu1010_fpga_write ( emu , EMU_HANA_MIDI_IN , 0x19 ) ; /* MIDI Route */
snd_emu1010_fpga_write ( emu , EMU_HANA_MIDI_OUT , 0x0c ) ; /* Unknown */
snd_emu1010_fpga_read ( emu , EMU_HANA_SPDIF_MODE , & tmp ) ;
snd_emu1010_fpga_write ( emu , EMU_HANA_SPDIF_MODE , 0x10 ) ; /* SPDIF Format spdif (or 0x11 for aes/ebu) */
2006-10-01 10:48:04 +01:00
2007-07-23 17:52:27 +01:00
/* Start Micro/Audio Dock firmware loader thread */
2007-12-14 12:43:00 +01:00
if ( ! emu - > emu1010 . firmware_thread ) {
emu - > emu1010 . firmware_thread =
kthread_create ( emu1010_firmware_thread , emu ,
" emu1010_firmware " ) ;
wake_up_process ( emu - > emu1010 . firmware_thread ) ;
}
2007-07-14 02:18:26 +01:00
2006-10-01 10:48:04 +01:00
#if 0
snd_emu1010_fpga_link_dst_src_write ( emu ,
EMU_DST_HAMOA_DAC_LEFT1 , EMU_SRC_ALICE_EMU32B + 2 ) ; /* ALICE2 bus 0xa2 */
snd_emu1010_fpga_link_dst_src_write ( emu ,
EMU_DST_HAMOA_DAC_RIGHT1 , EMU_SRC_ALICE_EMU32B + 3 ) ; /* ALICE2 bus 0xa3 */
snd_emu1010_fpga_link_dst_src_write ( emu ,
EMU_DST_HANA_SPDIF_LEFT1 , EMU_SRC_ALICE_EMU32A + 2 ) ; /* ALICE2 bus 0xb2 */
snd_emu1010_fpga_link_dst_src_write ( emu ,
EMU_DST_HANA_SPDIF_RIGHT1 , EMU_SRC_ALICE_EMU32A + 3 ) ; /* ALICE2 bus 0xb3 */
# endif
/* Default outputs */
2007-12-21 16:33:32 +01:00
if ( emu - > card_capabilities - > emu_model = = EMU_MODEL_EMU1616 ) {
2007-12-13 16:27:13 +01:00
/* 1616(M) cardbus default outputs */
/* ALICE2 bus 0xa0 */
snd_emu1010_fpga_link_dst_src_write ( emu ,
EMU_DST_DOCK_DAC1_LEFT1 , EMU_SRC_ALICE_EMU32A + 0 ) ;
emu - > emu1010 . output_source [ 0 ] = 17 ;
snd_emu1010_fpga_link_dst_src_write ( emu ,
EMU_DST_DOCK_DAC1_RIGHT1 , EMU_SRC_ALICE_EMU32A + 1 ) ;
emu - > emu1010 . output_source [ 1 ] = 18 ;
snd_emu1010_fpga_link_dst_src_write ( emu ,
EMU_DST_DOCK_DAC2_LEFT1 , EMU_SRC_ALICE_EMU32A + 2 ) ;
emu - > emu1010 . output_source [ 2 ] = 19 ;
snd_emu1010_fpga_link_dst_src_write ( emu ,
EMU_DST_DOCK_DAC2_RIGHT1 , EMU_SRC_ALICE_EMU32A + 3 ) ;
emu - > emu1010 . output_source [ 3 ] = 20 ;
snd_emu1010_fpga_link_dst_src_write ( emu ,
EMU_DST_DOCK_DAC3_LEFT1 , EMU_SRC_ALICE_EMU32A + 4 ) ;
emu - > emu1010 . output_source [ 4 ] = 21 ;
snd_emu1010_fpga_link_dst_src_write ( emu ,
EMU_DST_DOCK_DAC3_RIGHT1 , EMU_SRC_ALICE_EMU32A + 5 ) ;
emu - > emu1010 . output_source [ 5 ] = 22 ;
/* ALICE2 bus 0xa0 */
snd_emu1010_fpga_link_dst_src_write ( emu ,
EMU_DST_MANA_DAC_LEFT , EMU_SRC_ALICE_EMU32A + 0 ) ;
emu - > emu1010 . output_source [ 16 ] = 17 ;
snd_emu1010_fpga_link_dst_src_write ( emu ,
EMU_DST_MANA_DAC_RIGHT , EMU_SRC_ALICE_EMU32A + 1 ) ;
emu - > emu1010 . output_source [ 17 ] = 18 ;
} else {
/* ALICE2 bus 0xa0 */
snd_emu1010_fpga_link_dst_src_write ( emu ,
EMU_DST_DOCK_DAC1_LEFT1 , EMU_SRC_ALICE_EMU32A + 0 ) ;
emu - > emu1010 . output_source [ 0 ] = 21 ;
snd_emu1010_fpga_link_dst_src_write ( emu ,
EMU_DST_DOCK_DAC1_RIGHT1 , EMU_SRC_ALICE_EMU32A + 1 ) ;
emu - > emu1010 . output_source [ 1 ] = 22 ;
snd_emu1010_fpga_link_dst_src_write ( emu ,
EMU_DST_DOCK_DAC2_LEFT1 , EMU_SRC_ALICE_EMU32A + 2 ) ;
emu - > emu1010 . output_source [ 2 ] = 23 ;
snd_emu1010_fpga_link_dst_src_write ( emu ,
EMU_DST_DOCK_DAC2_RIGHT1 , EMU_SRC_ALICE_EMU32A + 3 ) ;
emu - > emu1010 . output_source [ 3 ] = 24 ;
snd_emu1010_fpga_link_dst_src_write ( emu ,
EMU_DST_DOCK_DAC3_LEFT1 , EMU_SRC_ALICE_EMU32A + 4 ) ;
emu - > emu1010 . output_source [ 4 ] = 25 ;
snd_emu1010_fpga_link_dst_src_write ( emu ,
EMU_DST_DOCK_DAC3_RIGHT1 , EMU_SRC_ALICE_EMU32A + 5 ) ;
emu - > emu1010 . output_source [ 5 ] = 26 ;
snd_emu1010_fpga_link_dst_src_write ( emu ,
EMU_DST_DOCK_DAC4_LEFT1 , EMU_SRC_ALICE_EMU32A + 6 ) ;
emu - > emu1010 . output_source [ 6 ] = 27 ;
snd_emu1010_fpga_link_dst_src_write ( emu ,
EMU_DST_DOCK_DAC4_RIGHT1 , EMU_SRC_ALICE_EMU32A + 7 ) ;
emu - > emu1010 . output_source [ 7 ] = 28 ;
/* ALICE2 bus 0xa0 */
snd_emu1010_fpga_link_dst_src_write ( emu ,
EMU_DST_DOCK_PHONES_LEFT1 , EMU_SRC_ALICE_EMU32A + 0 ) ;
emu - > emu1010 . output_source [ 8 ] = 21 ;
snd_emu1010_fpga_link_dst_src_write ( emu ,
EMU_DST_DOCK_PHONES_RIGHT1 , EMU_SRC_ALICE_EMU32A + 1 ) ;
emu - > emu1010 . output_source [ 9 ] = 22 ;
/* ALICE2 bus 0xa0 */
snd_emu1010_fpga_link_dst_src_write ( emu ,
EMU_DST_DOCK_SPDIF_LEFT1 , EMU_SRC_ALICE_EMU32A + 0 ) ;
emu - > emu1010 . output_source [ 10 ] = 21 ;
snd_emu1010_fpga_link_dst_src_write ( emu ,
EMU_DST_DOCK_SPDIF_RIGHT1 , EMU_SRC_ALICE_EMU32A + 1 ) ;
emu - > emu1010 . output_source [ 11 ] = 22 ;
/* ALICE2 bus 0xa0 */
snd_emu1010_fpga_link_dst_src_write ( emu ,
EMU_DST_HANA_SPDIF_LEFT1 , EMU_SRC_ALICE_EMU32A + 0 ) ;
emu - > emu1010 . output_source [ 12 ] = 21 ;
snd_emu1010_fpga_link_dst_src_write ( emu ,
EMU_DST_HANA_SPDIF_RIGHT1 , EMU_SRC_ALICE_EMU32A + 1 ) ;
emu - > emu1010 . output_source [ 13 ] = 22 ;
/* ALICE2 bus 0xa0 */
snd_emu1010_fpga_link_dst_src_write ( emu ,
EMU_DST_HAMOA_DAC_LEFT1 , EMU_SRC_ALICE_EMU32A + 0 ) ;
emu - > emu1010 . output_source [ 14 ] = 21 ;
snd_emu1010_fpga_link_dst_src_write ( emu ,
EMU_DST_HAMOA_DAC_RIGHT1 , EMU_SRC_ALICE_EMU32A + 1 ) ;
emu - > emu1010 . output_source [ 15 ] = 22 ;
/* ALICE2 bus 0xa0 */
snd_emu1010_fpga_link_dst_src_write ( emu ,
EMU_DST_HANA_ADAT , EMU_SRC_ALICE_EMU32A + 0 ) ;
emu - > emu1010 . output_source [ 16 ] = 21 ;
snd_emu1010_fpga_link_dst_src_write ( emu ,
EMU_DST_HANA_ADAT + 1 , EMU_SRC_ALICE_EMU32A + 1 ) ;
emu - > emu1010 . output_source [ 17 ] = 22 ;
snd_emu1010_fpga_link_dst_src_write ( emu ,
EMU_DST_HANA_ADAT + 2 , EMU_SRC_ALICE_EMU32A + 2 ) ;
emu - > emu1010 . output_source [ 18 ] = 23 ;
snd_emu1010_fpga_link_dst_src_write ( emu ,
EMU_DST_HANA_ADAT + 3 , EMU_SRC_ALICE_EMU32A + 3 ) ;
emu - > emu1010 . output_source [ 19 ] = 24 ;
snd_emu1010_fpga_link_dst_src_write ( emu ,
EMU_DST_HANA_ADAT + 4 , EMU_SRC_ALICE_EMU32A + 4 ) ;
emu - > emu1010 . output_source [ 20 ] = 25 ;
snd_emu1010_fpga_link_dst_src_write ( emu ,
EMU_DST_HANA_ADAT + 5 , EMU_SRC_ALICE_EMU32A + 5 ) ;
emu - > emu1010 . output_source [ 21 ] = 26 ;
snd_emu1010_fpga_link_dst_src_write ( emu ,
EMU_DST_HANA_ADAT + 6 , EMU_SRC_ALICE_EMU32A + 6 ) ;
emu - > emu1010 . output_source [ 22 ] = 27 ;
snd_emu1010_fpga_link_dst_src_write ( emu ,
EMU_DST_HANA_ADAT + 7 , EMU_SRC_ALICE_EMU32A + 7 ) ;
emu - > emu1010 . output_source [ 23 ] = 28 ;
}
2006-10-01 10:48:04 +01:00
/* TEMP: Select SPDIF in/out */
2008-10-23 18:51:00 +02:00
/* snd_emu1010_fpga_write(emu, EMU_HANA_OPTICAL_TYPE, 0x0); */ /* Output spdif */
2006-10-01 10:48:04 +01:00
/* TEMP: Select 48kHz SPDIF out */
snd_emu1010_fpga_write ( emu , EMU_HANA_UNMUTE , 0x0 ) ; /* Mute all */
snd_emu1010_fpga_write ( emu , EMU_HANA_DEFCLOCK , 0x0 ) ; /* Default fallback clock 48kHz */
/* Word Clock source, Internal 48kHz x1 */
2008-10-23 18:51:00 +02:00
snd_emu1010_fpga_write ( emu , EMU_HANA_WCLOCK , EMU_HANA_WCLOCK_INT_48K ) ;
/* snd_emu1010_fpga_write(emu, EMU_HANA_WCLOCK, EMU_HANA_WCLOCK_INT_48K | EMU_HANA_WCLOCK_4X); */
2006-10-10 18:08:45 +01:00
emu - > emu1010 . internal_clock = 1 ; /* 48000 */
2008-10-23 18:51:00 +02:00
snd_emu1010_fpga_write ( emu , EMU_HANA_DOCK_LEDS_2 , 0x12 ) ; /* Set LEDs on Audio Dock */
2006-10-01 10:48:04 +01:00
snd_emu1010_fpga_write ( emu , EMU_HANA_UNMUTE , 0x1 ) ; /* Unmute all */
2008-10-23 18:51:00 +02:00
/* snd_emu1010_fpga_write(emu, 0x7, 0x0); */ /* Mute all */
/* snd_emu1010_fpga_write(emu, 0x7, 0x1); */ /* Unmute all */
/* snd_emu1010_fpga_write(emu, 0xe, 0x12); */ /* Set LEDs on Audio Dock */
2005-12-04 18:03:03 +01:00
return 0 ;
}
2005-04-16 15:20:36 -07:00
/*
* Create the EMU10K1 instance
*/
2012-08-14 18:12:04 +02:00
# ifdef CONFIG_PM_SLEEP
2005-11-17 16:14:10 +01:00
static int alloc_pm_buffer ( struct snd_emu10k1 * emu ) ;
static void free_pm_buffer ( struct snd_emu10k1 * emu ) ;
# endif
2005-11-17 14:50:13 +01:00
static int snd_emu10k1_free ( struct snd_emu10k1 * emu )
2005-04-16 15:20:36 -07:00
{
if ( emu - > port ) { /* avoid access to already used hardware */
2008-10-23 18:51:00 +02:00
snd_emu10k1_fx8010_tram_setup ( emu , 0 ) ;
2005-04-16 15:20:36 -07:00
snd_emu10k1_done ( emu ) ;
2005-11-17 16:14:10 +01:00
snd_emu10k1_free_efx ( emu ) ;
2008-10-23 18:51:00 +02:00
}
2007-12-21 16:33:32 +01:00
if ( emu - > card_capabilities - > emu_model = = EMU_MODEL_EMU1010 ) {
2006-10-01 10:48:04 +01:00
/* Disable 48Volt power to Audio Dock */
2008-10-23 18:51:00 +02:00
snd_emu1010_fpga_write ( emu , EMU_HANA_DOCK_PWR , 0 ) ;
2006-10-01 10:48:04 +01:00
}
2007-12-14 12:43:00 +01:00
if ( emu - > emu1010 . firmware_thread )
2007-11-04 14:08:26 +00:00
kthread_stop ( emu - > emu1010 . firmware_thread ) ;
2014-11-03 14:54:36 +01:00
release_firmware ( emu - > firmware ) ;
release_firmware ( emu - > dock_fw ) ;
2008-04-22 17:28:11 +02:00
if ( emu - > irq > = 0 )
free_irq ( emu - > irq , emu ) ;
/* remove reserved page */
if ( emu - > reserved_page ) {
snd_emu10k1_synth_free ( emu ,
( struct snd_util_memblk * ) emu - > reserved_page ) ;
emu - > reserved_page = NULL ;
}
2014-11-03 14:54:36 +01:00
snd_util_memhdr_free ( emu - > memhdr ) ;
2005-04-16 15:20:36 -07:00
if ( emu - > silent_page . area )
snd_dma_free_pages ( & emu - > silent_page ) ;
if ( emu - > ptb_pages . area )
snd_dma_free_pages ( & emu - > ptb_pages ) ;
vfree ( emu - > page_ptr_table ) ;
vfree ( emu - > page_addr_table ) ;
2012-08-14 18:12:04 +02:00
# ifdef CONFIG_PM_SLEEP
2005-11-17 16:14:10 +01:00
free_pm_buffer ( emu ) ;
# endif
2005-04-16 15:20:36 -07:00
if ( emu - > port )
pci_release_regions ( emu - > pci ) ;
2008-10-23 18:51:00 +02:00
if ( emu - > card_capabilities - > ca0151_chip ) /* P16V */
2005-04-16 15:20:36 -07:00
snd_p16v_free ( emu ) ;
2005-11-17 16:14:10 +01:00
pci_disable_device ( emu - > pci ) ;
2005-04-16 15:20:36 -07:00
kfree ( emu ) ;
return 0 ;
}
2005-11-17 14:50:13 +01:00
static int snd_emu10k1_dev_free ( struct snd_device * device )
2005-04-16 15:20:36 -07:00
{
2005-11-17 14:50:13 +01:00
struct snd_emu10k1 * emu = device - > device_data ;
2005-04-16 15:20:36 -07:00
return snd_emu10k1_free ( emu ) ;
}
2005-11-17 14:50:13 +01:00
static struct snd_emu_chip_details emu_chip_details [ ] = {
2015-03-28 19:20:35 +01:00
/* Audigy 5/Rx SB1550 */
/* Tested by michael@gernoth.net 28 Mar 2015 */
/* DSP: CA10300-IAT LF
* DAC : Cirrus Logic CS4382 - KQZ
* ADC : Philips 1361 T
* AC97 : Sigmatel STAC9750
* CA0151 : None
*/
{ . vendor = 0x1102 , . device = 0x0008 , . subsystem = 0x10241102 ,
. driver = " Audigy2 " , . name = " SB Audigy 5/Rx [SB1550] " ,
. id = " Audigy2 " ,
. emu10k2_chip = 1 ,
. ca0108_chip = 1 ,
. spk71 = 1 ,
. adc_1361t = 1 , /* 24 bit capture instead of 16bit */
. ac97_chip = 1 } ,
2006-04-09 17:36:39 +01:00
/* Audigy4 (Not PRO) SB0610 */
/* Tested by James@superbug.co.uk 4th April 2006 */
/* A_IOCFG bits
* Output
* 0 : ?
* 1 : ?
* 2 : ?
* 3 : 0 - Digital Out , 1 - Line in
* 4 : ?
* 5 : ?
* 6 : ?
* 7 : ?
* Input
* 8 : ?
* 9 : ?
* A : Green jack sense ( Front )
* B : ?
* C : Black jack sense ( Rear / Side Right )
* D : Yellow jack sense ( Center / LFE / Side Left )
* E : ?
* F : ?
*
* Digital Out / Line in switch using A_IOCFG bit 3 ( 0x08 )
* 0 - Digital Out
* 1 - Line in
*/
/* Mic input not tested.
* Analog CD input not tested
* Digital Out not tested .
* Line in working .
* Audio output 5.1 working . Side outputs not working .
*/
/* DSP: CA10300-IAT LF
* DAC : Cirrus Logic CS4382 - KQZ
* ADC : Philips 1361 T
* AC97 : Sigmatel STAC9750
* CA0151 : None
*/
{ . vendor = 0x1102 , . device = 0x0008 , . subsystem = 0x10211102 ,
2008-10-21 17:42:54 +02:00
. driver = " Audigy2 " , . name = " SB Audigy 4 [SB0610] " ,
2006-04-09 17:36:39 +01:00
. id = " Audigy2 " ,
. emu10k2_chip = 1 ,
. ca0108_chip = 1 ,
. spk71 = 1 ,
. adc_1361t = 1 , /* 24 bit capture instead of 16bit */
. ac97_chip = 1 } ,
2008-10-21 17:42:54 +02:00
/* Audigy 2 Value AC3 out does not work yet.
* Need to find out how to turn off interpolators .
*/
/* Tested by James@superbug.co.uk 3rd July 2005 */
/* DSP: CA0108-IAT
* DAC : CS4382 - KQ
* ADC : Philips 1361 T
* AC97 : STAC9750
* CA0151 : None
*/
{ . vendor = 0x1102 , . device = 0x0008 , . subsystem = 0x10011102 ,
. driver = " Audigy2 " , . name = " SB Audigy 2 Value [SB0400] " ,
. id = " Audigy2 " ,
. emu10k2_chip = 1 ,
. ca0108_chip = 1 ,
. spk71 = 1 ,
. ac97_chip = 1 } ,
2005-10-31 10:27:41 +00:00
/* Audigy 2 ZS Notebook Cardbus card.*/
2006-12-06 15:58:02 +00:00
/* Tested by James@superbug.co.uk 6th November 2006 */
2005-12-22 13:05:23 +01:00
/* Audio output 7.1/Headphones working.
* Digital output working . ( AC3 not checked , only PCM )
2006-12-06 15:58:02 +00:00
* Audio Mic / Line inputs working .
* Digital input not tested .
2008-10-21 17:42:54 +02:00
*/
2006-04-09 17:36:39 +01:00
/* DSP: Tina2
2005-12-22 13:05:23 +01:00
* DAC : Wolfson WM8768 / WM8568
* ADC : Wolfson WM8775
* AC97 : None
* CA0151 : None
*/
2006-12-06 15:58:02 +00:00
/* Tested by James@superbug.co.uk 4th April 2006 */
/* A_IOCFG bits
* Output
* 0 : Not Used
* 1 : 0 = Mute all the 7.1 channel out . 1 = unmute .
* 2 : Analog input 0 = line in , 1 = mic in
* 3 : Not Used
* 4 : Digital output 0 = off , 1 = on .
* 5 : Not Used
* 6 : Not Used
* 7 : Not Used
* Input
* All bits 1 ( 0x3f xx ) means nothing plugged in .
* 8 - 9 : 0 = Line in / Mic , 2 = Optical in , 3 = Nothing .
* A - B : 0 = Headphones , 2 = Optical out , 3 = Nothing .
* C - D : 2 = Front / Rear / etc , 3 = nothing .
* E - F : Always 0
*
*/
2005-10-31 10:27:41 +00:00
{ . vendor = 0x1102 , . device = 0x0008 , . subsystem = 0x20011102 ,
2008-10-21 17:42:54 +02:00
. driver = " Audigy2 " , . name = " SB Audigy 2 ZS Notebook [SB0530] " ,
2005-10-31 10:27:41 +00:00
. id = " Audigy2 " ,
. emu10k2_chip = 1 ,
. ca0108_chip = 1 ,
. ca_cardbus_chip = 1 ,
2005-12-21 15:06:08 +01:00
. spi_dac = 1 ,
2006-12-06 15:58:02 +00:00
. i2c_adc = 1 ,
2005-10-31 10:27:41 +00:00
. spk71 = 1 } ,
2007-11-04 14:08:26 +00:00
/* Tested by James@superbug.co.uk 4th Nov 2007. */
2007-04-19 11:14:41 +01:00
{ . vendor = 0x1102 , . device = 0x0008 , . subsystem = 0x42011102 ,
2008-10-21 17:42:54 +02:00
. driver = " Audigy2 " , . name = " E-mu 1010 Notebook [MAEM8950] " ,
2007-04-19 11:14:41 +01:00
. id = " EMU1010 " ,
. emu10k2_chip = 1 ,
. ca0108_chip = 1 ,
. ca_cardbus_chip = 1 ,
2007-07-14 10:24:49 +01:00
. spk71 = 1 ,
2007-12-21 16:33:32 +01:00
. emu_model = EMU_MODEL_EMU1616 } ,
2007-11-04 14:08:26 +00:00
/* Tested by James@superbug.co.uk 4th Nov 2007. */
2008-10-21 17:42:54 +02:00
/* This is MAEM8960, 0202 is MAEM 8980 */
2007-07-14 02:18:26 +01:00
{ . vendor = 0x1102 , . device = 0x0008 , . subsystem = 0x40041102 ,
2008-10-21 17:42:54 +02:00
. driver = " Audigy2 " , . name = " E-mu 1010b PCI [MAEM8960] " ,
2007-07-14 02:18:26 +01:00
. id = " EMU1010 " ,
. emu10k2_chip = 1 ,
. ca0108_chip = 1 ,
2007-11-04 14:08:26 +00:00
. spk71 = 1 ,
2008-10-21 17:42:54 +02:00
. emu_model = EMU_MODEL_EMU1010B } , /* EMU 1010 new revision */
2012-10-17 18:18:10 +02:00
/* Tested by Maxim Kachur <mcdebugger@duganet.ru> 17th Oct 2012. */
/* This is MAEM8986, 0202 is MAEM8980 */
{ . vendor = 0x1102 , . device = 0x0008 , . subsystem = 0x40071102 ,
. driver = " Audigy2 " , . name = " E-mu 1010 PCIe [MAEM8986] " ,
. id = " EMU1010 " ,
. emu10k2_chip = 1 ,
. ca0108_chip = 1 ,
. spk71 = 1 ,
. emu_model = EMU_MODEL_EMU1010B } , /* EMU 1010 PCIe */
2007-11-04 14:08:26 +00:00
/* Tested by James@superbug.co.uk 8th July 2005. */
2008-10-21 17:42:54 +02:00
/* This is MAEM8810, 0202 is MAEM8820 */
2007-11-04 14:08:26 +00:00
{ . vendor = 0x1102 , . device = 0x0004 , . subsystem = 0x40011102 ,
2008-10-21 17:42:54 +02:00
. driver = " Audigy2 " , . name = " E-mu 1010 [MAEM8810] " ,
2007-11-04 14:08:26 +00:00
. id = " EMU1010 " ,
. emu10k2_chip = 1 ,
. ca0102_chip = 1 ,
. spk71 = 1 ,
2008-10-21 17:42:54 +02:00
. emu_model = EMU_MODEL_EMU1010 } , /* EMU 1010 old revision */
2008-01-07 12:36:56 +01:00
/* EMU0404b */
{ . vendor = 0x1102 , . device = 0x0008 , . subsystem = 0x40021102 ,
2008-10-21 17:42:54 +02:00
. driver = " Audigy2 " , . name = " E-mu 0404b PCI [MAEM8852] " ,
2008-01-07 12:36:56 +01:00
. id = " EMU0404 " ,
. emu10k2_chip = 1 ,
. ca0108_chip = 1 ,
. spk71 = 1 ,
2008-10-21 17:42:54 +02:00
. emu_model = EMU_MODEL_EMU0404 } , /* EMU 0404 new revision */
2008-01-07 12:36:56 +01:00
/* Tested by James@superbug.co.uk 20-3-2007. */
{ . vendor = 0x1102 , . device = 0x0004 , . subsystem = 0x40021102 ,
2008-10-21 17:42:54 +02:00
. driver = " Audigy2 " , . name = " E-mu 0404 [MAEM8850] " ,
2008-01-07 12:36:56 +01:00
. id = " EMU0404 " ,
. emu10k2_chip = 1 ,
. ca0102_chip = 1 ,
. spk71 = 1 ,
. emu_model = EMU_MODEL_EMU0404 } , /* EMU 0404 */
2011-06-12 01:15:42 +02:00
/* EMU0404 PCIe */
{ . vendor = 0x1102 , . device = 0x0008 , . subsystem = 0x40051102 ,
. driver = " Audigy2 " , . name = " E-mu 0404 PCIe [MAEM8984] " ,
. id = " EMU0404 " ,
. emu10k2_chip = 1 ,
. ca0108_chip = 1 ,
. spk71 = 1 ,
. emu_model = EMU_MODEL_EMU0404 } , /* EMU 0404 PCIe ver_03 */
2008-10-21 21:31:27 +02:00
/* Note that all E-mu cards require kernel 2.6 or newer. */
2008-10-21 17:42:54 +02:00
{ . vendor = 0x1102 , . device = 0x0008 ,
. driver = " Audigy2 " , . name = " SB Audigy 2 Value [Unknown] " ,
2005-03-30 14:22:25 +02:00
. id = " Audigy2 " ,
2005-04-16 15:20:36 -07:00
. emu10k2_chip = 1 ,
2005-04-01 11:15:07 +02:00
. ca0108_chip = 1 ,
. ac97_chip = 1 } ,
2005-07-03 12:54:29 +02:00
/* Tested by James@superbug.co.uk 3rd July 2005 */
2005-04-16 15:20:36 -07:00
{ . vendor = 0x1102 , . device = 0x0004 , . subsystem = 0x20071102 ,
2008-10-21 17:42:54 +02:00
. driver = " Audigy2 " , . name = " SB Audigy 4 PRO [SB0380] " ,
2005-03-30 14:22:25 +02:00
. id = " Audigy2 " ,
2005-04-16 15:20:36 -07:00
. emu10k2_chip = 1 ,
. ca0102_chip = 1 ,
. ca0151_chip = 1 ,
. spk71 = 1 ,
. spdif_bug = 1 ,
. ac97_chip = 1 } ,
2005-11-07 14:59:19 +01:00
/* Tested by shane-alsa@cm.nu 5th Nov 2005 */
2006-04-09 22:45:58 +02:00
/* The 0x20061102 does have SB0350 written on it
* Just like 0x20021102
*/
2005-11-07 14:59:19 +01:00
{ . vendor = 0x1102 , . device = 0x0004 , . subsystem = 0x20061102 ,
2008-10-21 17:42:54 +02:00
. driver = " Audigy2 " , . name = " SB Audigy 2 [SB0350b] " ,
2005-11-07 14:59:19 +01:00
. id = " Audigy2 " ,
. emu10k2_chip = 1 ,
. ca0102_chip = 1 ,
. ca0151_chip = 1 ,
. spk71 = 1 ,
. spdif_bug = 1 ,
2008-11-03 10:21:36 +01:00
. invert_shared_spdif = 1 , /* digital/analog switch swapped */
2005-11-07 14:59:19 +01:00
. ac97_chip = 1 } ,
2011-12-29 18:50:56 +00:00
/* 0x20051102 also has SB0350 written on it, treated as Audigy 2 ZS by
Creative ' s Windows driver */
{ . vendor = 0x1102 , . device = 0x0004 , . subsystem = 0x20051102 ,
. driver = " Audigy2 " , . name = " SB Audigy 2 ZS [SB0350a] " ,
. id = " Audigy2 " ,
. emu10k2_chip = 1 ,
. ca0102_chip = 1 ,
. ca0151_chip = 1 ,
. spk71 = 1 ,
. spdif_bug = 1 ,
. invert_shared_spdif = 1 , /* digital/analog switch swapped */
. ac97_chip = 1 } ,
2005-04-16 15:20:36 -07:00
{ . vendor = 0x1102 , . device = 0x0004 , . subsystem = 0x20021102 ,
2008-10-21 17:42:54 +02:00
. driver = " Audigy2 " , . name = " SB Audigy 2 ZS [SB0350] " ,
2005-03-30 14:22:25 +02:00
. id = " Audigy2 " ,
2005-04-16 15:20:36 -07:00
. emu10k2_chip = 1 ,
. ca0102_chip = 1 ,
. ca0151_chip = 1 ,
. spk71 = 1 ,
. spdif_bug = 1 ,
2008-11-03 10:21:36 +01:00
. invert_shared_spdif = 1 , /* digital/analog switch swapped */
2005-04-16 15:20:36 -07:00
. ac97_chip = 1 } ,
{ . vendor = 0x1102 , . device = 0x0004 , . subsystem = 0x20011102 ,
2008-10-21 17:42:54 +02:00
. driver = " Audigy2 " , . name = " SB Audigy 2 ZS [SB0360] " ,
2005-03-30 14:22:25 +02:00
. id = " Audigy2 " ,
2005-04-16 15:20:36 -07:00
. emu10k2_chip = 1 ,
. ca0102_chip = 1 ,
. ca0151_chip = 1 ,
. spk71 = 1 ,
. spdif_bug = 1 ,
2008-11-03 10:21:36 +01:00
. invert_shared_spdif = 1 , /* digital/analog switch swapped */
2005-04-16 15:20:36 -07:00
. ac97_chip = 1 } ,
2005-12-22 12:58:41 +01:00
/* Audigy 2 */
/* Tested by James@superbug.co.uk 3rd July 2005 */
/* DSP: CA0102-IAT
* DAC : CS4382 - KQ
* ADC : Philips 1361 T
* AC97 : STAC9721
* CA0151 : Yes
*/
2005-04-16 15:20:36 -07:00
{ . vendor = 0x1102 , . device = 0x0004 , . subsystem = 0x10071102 ,
2008-10-21 17:42:54 +02:00
. driver = " Audigy2 " , . name = " SB Audigy 2 [SB0240] " ,
2005-03-30 14:22:25 +02:00
. id = " Audigy2 " ,
2005-04-16 15:20:36 -07:00
. emu10k2_chip = 1 ,
. ca0102_chip = 1 ,
. ca0151_chip = 1 ,
. spk71 = 1 ,
. spdif_bug = 1 ,
2006-07-08 16:39:30 +01:00
. adc_1361t = 1 , /* 24 bit capture instead of 16bit */
2005-04-16 15:20:36 -07:00
. ac97_chip = 1 } ,
{ . vendor = 0x1102 , . device = 0x0004 , . subsystem = 0x10051102 ,
2008-10-21 17:42:54 +02:00
. driver = " Audigy2 " , . name = " SB Audigy 2 Platinum EX [SB0280] " ,
2005-03-30 14:22:25 +02:00
. id = " Audigy2 " ,
2005-04-16 15:20:36 -07:00
. emu10k2_chip = 1 ,
. ca0102_chip = 1 ,
. ca0151_chip = 1 ,
2005-11-07 14:54:24 +01:00
. spk71 = 1 ,
2005-04-16 15:20:36 -07:00
. spdif_bug = 1 } ,
2006-07-30 17:17:59 +01:00
/* Dell OEM/Creative Labs Audigy 2 ZS */
/* See ALSA bug#1365 */
{ . vendor = 0x1102 , . device = 0x0004 , . subsystem = 0x10031102 ,
2008-10-21 17:42:54 +02:00
. driver = " Audigy2 " , . name = " SB Audigy 2 ZS [SB0353] " ,
2006-07-30 17:17:59 +01:00
. id = " Audigy2 " ,
. emu10k2_chip = 1 ,
. ca0102_chip = 1 ,
. ca0151_chip = 1 ,
. spk71 = 1 ,
. spdif_bug = 1 ,
2009-02-24 15:31:02 +01:00
. invert_shared_spdif = 1 , /* digital/analog switch swapped */
2006-07-30 17:17:59 +01:00
. ac97_chip = 1 } ,
2005-04-16 15:20:36 -07:00
{ . vendor = 0x1102 , . device = 0x0004 , . subsystem = 0x10021102 ,
2008-10-21 17:42:54 +02:00
. driver = " Audigy2 " , . name = " SB Audigy 2 Platinum [SB0240P] " ,
2005-03-30 14:22:25 +02:00
. id = " Audigy2 " ,
2005-04-16 15:20:36 -07:00
. emu10k2_chip = 1 ,
. ca0102_chip = 1 ,
. ca0151_chip = 1 ,
. spk71 = 1 ,
. spdif_bug = 1 ,
2008-06-02 11:45:53 +02:00
. invert_shared_spdif = 1 , /* digital/analog switch swapped */
2006-11-25 22:02:47 +00:00
. adc_1361t = 1 , /* 24 bit capture instead of 16bit. Fixes ALSA bug#324 */
2005-04-16 15:20:36 -07:00
. ac97_chip = 1 } ,
2005-04-07 15:48:42 +02:00
{ . vendor = 0x1102 , . device = 0x0004 , . revision = 0x04 ,
2008-10-21 17:42:54 +02:00
. driver = " Audigy2 " , . name = " SB Audigy 2 [Unknown] " ,
2005-04-07 15:48:42 +02:00
. id = " Audigy2 " ,
. emu10k2_chip = 1 ,
. ca0102_chip = 1 ,
. ca0151_chip = 1 ,
. spdif_bug = 1 ,
. ac97_chip = 1 } ,
2005-07-06 22:36:18 +02:00
{ . vendor = 0x1102 , . device = 0x0004 , . subsystem = 0x00531102 ,
2008-10-21 17:42:54 +02:00
. driver = " Audigy " , . name = " SB Audigy 1 [SB0092] " ,
2005-03-30 14:22:25 +02:00
. id = " Audigy " ,
2005-03-27 15:00:54 +02:00
. emu10k2_chip = 1 ,
. ca0102_chip = 1 ,
2005-04-01 11:15:07 +02:00
. ac97_chip = 1 } ,
2005-07-06 22:36:18 +02:00
{ . vendor = 0x1102 , . device = 0x0004 , . subsystem = 0x00521102 ,
2008-10-21 17:42:54 +02:00
. driver = " Audigy " , . name = " SB Audigy 1 ES [SB0160] " ,
2005-04-01 11:15:07 +02:00
. id = " Audigy " ,
. emu10k2_chip = 1 ,
. ca0102_chip = 1 ,
2005-07-06 22:36:18 +02:00
. spdif_bug = 1 ,
2005-04-01 11:15:07 +02:00
. ac97_chip = 1 } ,
2005-05-27 12:31:34 +02:00
{ . vendor = 0x1102 , . device = 0x0004 , . subsystem = 0x00511102 ,
2008-10-21 17:42:54 +02:00
. driver = " Audigy " , . name = " SB Audigy 1 [SB0090] " ,
2005-05-27 12:31:34 +02:00
. id = " Audigy " ,
. emu10k2_chip = 1 ,
. ca0102_chip = 1 ,
. ac97_chip = 1 } ,
2005-04-16 15:20:36 -07:00
{ . vendor = 0x1102 , . device = 0x0004 ,
2008-10-21 17:42:54 +02:00
. driver = " Audigy " , . name = " Audigy 1 [Unknown] " ,
2005-03-30 14:22:25 +02:00
. id = " Audigy " ,
2005-04-16 15:20:36 -07:00
. emu10k2_chip = 1 ,
. ca0102_chip = 1 ,
2005-04-01 11:15:07 +02:00
. ac97_chip = 1 } ,
2008-10-21 17:42:54 +02:00
{ . vendor = 0x1102 , . device = 0x0002 , . subsystem = 0x100a1102 ,
. driver = " EMU10K1 " , . name = " SB Live! 5.1 [SB0220] " ,
. id = " Live " ,
. emu10k1_chip = 1 ,
. ac97_chip = 1 ,
. sblive51 = 1 } ,
{ . vendor = 0x1102 , . device = 0x0002 , . subsystem = 0x806b1102 ,
. driver = " EMU10K1 " , . name = " SB Live! [SB0105] " ,
2005-05-11 11:13:26 +02:00
. id = " Live " ,
. emu10k1_chip = 1 ,
. ac97_chip = 1 ,
. sblive51 = 1 } ,
2008-10-21 17:42:54 +02:00
{ . vendor = 0x1102 , . device = 0x0002 , . subsystem = 0x806a1102 ,
. driver = " EMU10K1 " , . name = " SB Live! Value [SB0103] " ,
2005-03-30 14:22:25 +02:00
. id = " Live " ,
2005-04-16 15:20:36 -07:00
. emu10k1_chip = 1 ,
2005-03-30 13:51:18 +02:00
. ac97_chip = 1 ,
. sblive51 = 1 } ,
2005-07-03 12:32:40 +02:00
{ . vendor = 0x1102 , . device = 0x0002 , . subsystem = 0x80691102 ,
2008-10-21 17:42:54 +02:00
. driver = " EMU10K1 " , . name = " SB Live! Value [SB0101] " ,
2005-06-18 13:50:22 +02:00
. id = " Live " ,
. emu10k1_chip = 1 ,
. ac97_chip = 1 ,
. sblive51 = 1 } ,
2005-12-26 15:30:03 +01:00
/* Tested by ALSA bug#1680 26th December 2005 */
2008-10-21 17:42:54 +02:00
/* note: It really has SB0220 written on the card, */
/* but it's SB0228 according to kx.inf */
2005-12-26 15:30:03 +01:00
{ . vendor = 0x1102 , . device = 0x0002 , . subsystem = 0x80661102 ,
2008-10-21 17:42:54 +02:00
. driver = " EMU10K1 " , . name = " SB Live! 5.1 Dell OEM [SB0228] " ,
2005-12-26 15:30:03 +01:00
. id = " Live " ,
. emu10k1_chip = 1 ,
. ac97_chip = 1 ,
. sblive51 = 1 } ,
2005-08-29 17:42:00 +02:00
/* Tested by Thomas Zehetbauer 27th Aug 2005 */
{ . vendor = 0x1102 , . device = 0x0002 , . subsystem = 0x80651102 ,
2008-10-21 17:42:54 +02:00
. driver = " EMU10K1 " , . name = " SB Live! 5.1 [SB0220] " ,
2005-12-06 14:10:57 +01:00
. id = " Live " ,
. emu10k1_chip = 1 ,
. ac97_chip = 1 ,
. sblive51 = 1 } ,
2005-07-03 12:32:40 +02:00
{ . vendor = 0x1102 , . device = 0x0002 , . subsystem = 0x80641102 ,
2008-10-21 17:42:54 +02:00
. driver = " EMU10K1 " , . name = " SB Live! 5.1 " ,
2005-06-18 13:50:22 +02:00
. id = " Live " ,
. emu10k1_chip = 1 ,
. ac97_chip = 1 ,
. sblive51 = 1 } ,
2005-09-10 10:24:10 +02:00
/* Tested by alsa bugtrack user "hus" bug #1297 12th Aug 2005 */
2005-07-03 12:32:40 +02:00
{ . vendor = 0x1102 , . device = 0x0002 , . subsystem = 0x80611102 ,
2008-10-21 17:42:54 +02:00
. driver = " EMU10K1 " , . name = " SB Live! 5.1 [SB0060] " ,
2005-06-18 13:50:22 +02:00
. id = " Live " ,
. emu10k1_chip = 1 ,
2005-09-30 16:56:59 +02:00
. ac97_chip = 2 , /* ac97 is optional; both SBLive 5.1 and platinum
* share the same IDs !
*/
2005-06-18 13:50:22 +02:00
. sblive51 = 1 } ,
2005-07-03 12:32:40 +02:00
{ . vendor = 0x1102 , . device = 0x0002 , . subsystem = 0x80511102 ,
2008-10-21 17:42:54 +02:00
. driver = " EMU10K1 " , . name = " SB Live! Value [CT4850] " ,
2005-06-18 13:50:22 +02:00
. id = " Live " ,
. emu10k1_chip = 1 ,
. ac97_chip = 1 ,
. sblive51 = 1 } ,
2005-07-03 12:32:40 +02:00
{ . vendor = 0x1102 , . device = 0x0002 , . subsystem = 0x80401102 ,
2008-10-21 17:42:54 +02:00
. driver = " EMU10K1 " , . name = " SB Live! Platinum [CT4760P] " ,
2005-07-03 12:32:40 +02:00
. id = " Live " ,
. emu10k1_chip = 1 ,
. ac97_chip = 1 } ,
{ . vendor = 0x1102 , . device = 0x0002 , . subsystem = 0x80321102 ,
2008-10-21 17:42:54 +02:00
. driver = " EMU10K1 " , . name = " SB Live! Value [CT4871] " ,
2005-06-18 13:50:22 +02:00
. id = " Live " ,
. emu10k1_chip = 1 ,
. ac97_chip = 1 ,
. sblive51 = 1 } ,
{ . vendor = 0x1102 , . device = 0x0002 , . subsystem = 0x80311102 ,
2008-10-21 17:42:54 +02:00
. driver = " EMU10K1 " , . name = " SB Live! Value [CT4831] " ,
2005-06-18 13:50:22 +02:00
. id = " Live " ,
. emu10k1_chip = 1 ,
. ac97_chip = 1 ,
. sblive51 = 1 } ,
2005-07-03 12:32:40 +02:00
{ . vendor = 0x1102 , . device = 0x0002 , . subsystem = 0x80281102 ,
2008-10-21 17:42:54 +02:00
. driver = " EMU10K1 " , . name = " SB Live! Value [CT4870] " ,
2005-03-30 14:22:25 +02:00
. id = " Live " ,
2005-03-30 13:51:18 +02:00
. emu10k1_chip = 1 ,
. ac97_chip = 1 ,
. sblive51 = 1 } ,
2005-07-03 12:54:29 +02:00
/* Tested by James@superbug.co.uk 3rd July 2005 */
2005-07-03 12:32:40 +02:00
{ . vendor = 0x1102 , . device = 0x0002 , . subsystem = 0x80271102 ,
2008-10-21 17:42:54 +02:00
. driver = " EMU10K1 " , . name = " SB Live! Value [CT4832] " ,
2005-06-18 13:50:22 +02:00
. id = " Live " ,
. emu10k1_chip = 1 ,
. ac97_chip = 1 ,
. sblive51 = 1 } ,
2005-07-03 12:32:40 +02:00
{ . vendor = 0x1102 , . device = 0x0002 , . subsystem = 0x80261102 ,
2008-10-21 17:42:54 +02:00
. driver = " EMU10K1 " , . name = " SB Live! Value [CT4830] " ,
2005-06-18 13:50:22 +02:00
. id = " Live " ,
. emu10k1_chip = 1 ,
. ac97_chip = 1 ,
. sblive51 = 1 } ,
2005-07-03 12:32:40 +02:00
{ . vendor = 0x1102 , . device = 0x0002 , . subsystem = 0x80231102 ,
2008-10-21 17:42:54 +02:00
. driver = " EMU10K1 " , . name = " SB PCI512 [CT4790] " ,
2005-06-18 13:50:22 +02:00
. id = " Live " ,
. emu10k1_chip = 1 ,
. ac97_chip = 1 ,
. sblive51 = 1 } ,
2005-07-03 12:32:40 +02:00
{ . vendor = 0x1102 , . device = 0x0002 , . subsystem = 0x80221102 ,
2008-10-21 17:42:54 +02:00
. driver = " EMU10K1 " , . name = " SB Live! Value [CT4780] " ,
2005-06-18 13:50:22 +02:00
. id = " Live " ,
. emu10k1_chip = 1 ,
. ac97_chip = 1 ,
. sblive51 = 1 } ,
2005-07-03 12:32:40 +02:00
{ . vendor = 0x1102 , . device = 0x0002 , . subsystem = 0x40011102 ,
2008-10-21 17:42:54 +02:00
. driver = " EMU10K1 " , . name = " E-mu APS [PC545] " ,
2005-07-03 12:32:40 +02:00
. id = " APS " ,
2005-06-18 13:50:22 +02:00
. emu10k1_chip = 1 ,
2005-07-03 12:32:40 +02:00
. ecard = 1 } ,
{ . vendor = 0x1102 , . device = 0x0002 , . subsystem = 0x00211102 ,
2008-10-21 17:42:54 +02:00
. driver = " EMU10K1 " , . name = " SB Live! [CT4620] " ,
2005-06-18 13:50:22 +02:00
. id = " Live " ,
. emu10k1_chip = 1 ,
. ac97_chip = 1 ,
. sblive51 = 1 } ,
2005-07-03 12:32:40 +02:00
{ . vendor = 0x1102 , . device = 0x0002 , . subsystem = 0x00201102 ,
2008-10-21 17:42:54 +02:00
. driver = " EMU10K1 " , . name = " SB Live! Value [CT4670] " ,
2005-06-18 13:50:22 +02:00
. id = " Live " ,
. emu10k1_chip = 1 ,
. ac97_chip = 1 ,
. sblive51 = 1 } ,
2005-04-16 15:20:36 -07:00
{ . vendor = 0x1102 , . device = 0x0002 ,
2008-10-21 17:42:54 +02:00
. driver = " EMU10K1 " , . name = " SB Live! [Unknown] " ,
2005-03-30 14:22:25 +02:00
. id = " Live " ,
2005-04-16 15:20:36 -07:00
. emu10k1_chip = 1 ,
2005-03-30 13:51:18 +02:00
. ac97_chip = 1 ,
. sblive51 = 1 } ,
2005-04-16 15:20:36 -07:00
{ } /* terminator */
} ;
2012-12-06 12:35:10 -05:00
int snd_emu10k1_create ( struct snd_card * card ,
2008-10-23 18:51:00 +02:00
struct pci_dev * pci ,
2005-04-16 15:20:36 -07:00
unsigned short extin_mask ,
unsigned short extout_mask ,
long max_cache_bytes ,
int enable_ir ,
2005-07-06 22:21:51 +02:00
uint subsystem ,
2008-10-23 18:51:00 +02:00
struct snd_emu10k1 * * remu )
2005-04-16 15:20:36 -07:00
{
2005-11-17 14:50:13 +01:00
struct snd_emu10k1 * emu ;
2005-11-17 16:14:10 +01:00
int idx , err ;
2005-04-16 15:20:36 -07:00
int is_audigy ;
2005-11-17 16:14:10 +01:00
unsigned int silent_page ;
2005-11-17 14:50:13 +01:00
const struct snd_emu_chip_details * c ;
static struct snd_device_ops ops = {
2005-04-16 15:20:36 -07:00
. dev_free = snd_emu10k1_dev_free ,
} ;
2008-10-23 18:51:00 +02:00
2005-04-16 15:20:36 -07:00
* remu = NULL ;
/* enable PCI device */
2008-10-23 18:51:00 +02:00
err = pci_enable_device ( pci ) ;
if ( err < 0 )
2005-04-16 15:20:36 -07:00
return err ;
[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 14:21:46 +02:00
emu = kzalloc ( sizeof ( * emu ) , GFP_KERNEL ) ;
2005-04-16 15:20:36 -07:00
if ( emu = = NULL ) {
pci_disable_device ( pci ) ;
return - ENOMEM ;
}
emu - > card = card ;
spin_lock_init ( & emu - > reg_lock ) ;
spin_lock_init ( & emu - > emu_lock ) ;
2007-11-10 17:55:14 +00:00
spin_lock_init ( & emu - > spi_lock ) ;
spin_lock_init ( & emu - > i2c_lock ) ;
2005-04-16 15:20:36 -07:00
spin_lock_init ( & emu - > voice_lock ) ;
spin_lock_init ( & emu - > synth_lock ) ;
spin_lock_init ( & emu - > memblk_lock ) ;
2006-01-16 16:34:20 +01:00
mutex_init ( & emu - > fx8010 . lock ) ;
2005-04-16 15:20:36 -07:00
INIT_LIST_HEAD ( & emu - > mapped_link_head ) ;
INIT_LIST_HEAD ( & emu - > mapped_order_link_head ) ;
emu - > pci = pci ;
emu - > irq = - 1 ;
emu - > synth = NULL ;
emu - > get_synth_voice = NULL ;
/* read revision & serial */
2007-06-08 15:46:36 -07:00
emu - > revision = pci - > revision ;
2005-04-16 15:20:36 -07:00
pci_read_config_dword ( pci , PCI_SUBSYSTEM_VENDOR_ID , & emu - > serial ) ;
pci_read_config_word ( pci , PCI_SUBSYSTEM_ID , & emu - > model ) ;
2014-02-25 17:02:09 +01:00
dev_dbg ( card - > dev ,
" vendor = 0x%x, device = 0x%x, subsystem_vendor_id = 0x%x, subsystem_id = 0x%x \n " ,
pci - > vendor , pci - > device , emu - > serial , emu - > model ) ;
2005-04-16 15:20:36 -07:00
for ( c = emu_chip_details ; c - > vendor ; c + + ) {
if ( c - > vendor = = pci - > vendor & & c - > device = = pci - > device ) {
2005-07-06 22:21:51 +02:00
if ( subsystem ) {
2008-10-23 18:51:00 +02:00
if ( c - > subsystem & & ( c - > subsystem = = subsystem ) )
2005-07-06 22:21:51 +02:00
break ;
2008-10-23 18:51:00 +02:00
else
continue ;
2005-07-06 22:21:51 +02:00
} else {
2008-10-23 18:51:00 +02:00
if ( c - > subsystem & & ( c - > subsystem ! = emu - > serial ) )
2005-07-06 22:21:51 +02:00
continue ;
if ( c - > revision & & c - > revision ! = emu - > revision )
continue ;
}
2005-04-07 15:48:42 +02:00
break ;
2005-04-16 15:20:36 -07:00
}
}
if ( c - > vendor = = 0 ) {
2014-02-25 17:02:09 +01:00
dev_err ( card - > dev , " emu10k1: Card not recognised \n " ) ;
2005-04-16 15:20:36 -07:00
kfree ( emu ) ;
pci_disable_device ( pci ) ;
return - ENOENT ;
}
emu - > card_capabilities = c ;
2005-07-06 22:21:51 +02:00
if ( c - > subsystem & & ! subsystem )
2014-02-25 17:02:09 +01:00
dev_dbg ( card - > dev , " Sound card name = %s \n " , c - > name ) ;
2008-10-23 18:51:00 +02:00
else if ( subsystem )
2014-02-25 17:02:09 +01:00
dev_dbg ( card - > dev , " Sound card name = %s, "
2008-10-23 18:51:00 +02:00
" vendor = 0x%x, device = 0x%x, subsystem = 0x%x. "
2010-03-16 11:47:56 +01:00
" Forced to subsystem = 0x%x \n " , c - > name ,
2008-10-23 18:51:00 +02:00
pci - > vendor , pci - > device , emu - > serial , c - > subsystem ) ;
else
2014-02-25 17:02:09 +01:00
dev_dbg ( card - > dev , " Sound card name = %s, "
2008-10-23 18:51:00 +02:00
" vendor = 0x%x, device = 0x%x, subsystem = 0x%x. \n " ,
c - > name , pci - > vendor , pci - > device ,
emu - > serial ) ;
2005-03-30 14:40:25 +02:00
if ( ! * card - > id & & c - > id ) {
int i , n = 0 ;
2005-03-30 14:22:25 +02:00
strlcpy ( card - > id , c - > id , sizeof ( card - > id ) ) ;
2005-03-30 14:40:25 +02:00
for ( ; ; ) {
for ( i = 0 ; i < snd_ecards_limit ; i + + ) {
if ( snd_cards [ i ] & & ! strcmp ( snd_cards [ i ] - > id , card - > id ) )
break ;
}
if ( i > = snd_ecards_limit )
break ;
n + + ;
if ( n > = SNDRV_CARDS )
break ;
snprintf ( card - > id , sizeof ( card - > id ) , " %s_%d " , c - > id , n ) ;
}
}
2005-03-30 14:22:25 +02:00
2005-04-16 15:20:36 -07:00
is_audigy = emu - > audigy = c - > emu10k2_chip ;
/* set the DMA transfer mask */
emu - > dma_mask = is_audigy ? AUDIGY_DMA_MASK : EMU10K1_DMA_MASK ;
if ( pci_set_dma_mask ( pci , emu - > dma_mask ) < 0 | |
pci_set_consistent_dma_mask ( pci , emu - > dma_mask ) < 0 ) {
2014-02-25 17:02:09 +01:00
dev_err ( card - > dev ,
" architecture does not support PCI busmaster DMA with mask 0x%lx \n " ,
emu - > dma_mask ) ;
2005-04-16 15:20:36 -07:00
kfree ( emu ) ;
pci_disable_device ( pci ) ;
return - ENXIO ;
}
if ( is_audigy )
emu - > gpr_base = A_FXGPREGBASE ;
else
emu - > gpr_base = FXGPREGBASE ;
2008-10-23 18:51:00 +02:00
err = pci_request_regions ( pci , " EMU10K1 " ) ;
if ( err < 0 ) {
2005-04-16 15:20:36 -07:00
kfree ( emu ) ;
pci_disable_device ( pci ) ;
return err ;
}
emu - > port = pci_resource_start ( pci , 0 ) ;
emu - > max_cache_pages = max_cache_bytes > > PAGE_SHIFT ;
if ( snd_dma_alloc_pages ( SNDRV_DMA_TYPE_DEV , snd_dma_pci_data ( pci ) ,
32 * 1024 , & emu - > ptb_pages ) < 0 ) {
2005-11-17 16:14:10 +01:00
err = - ENOMEM ;
goto error ;
2005-04-16 15:20:36 -07:00
}
2007-08-28 15:21:33 +02:00
emu - > page_ptr_table = vmalloc ( emu - > max_cache_pages * sizeof ( void * ) ) ;
emu - > page_addr_table = vmalloc ( emu - > max_cache_pages *
sizeof ( unsigned long ) ) ;
2005-04-16 15:20:36 -07:00
if ( emu - > page_ptr_table = = NULL | | emu - > page_addr_table = = NULL ) {
2005-11-17 16:14:10 +01:00
err = - ENOMEM ;
goto error ;
2005-04-16 15:20:36 -07:00
}
if ( snd_dma_alloc_pages ( SNDRV_DMA_TYPE_DEV , snd_dma_pci_data ( pci ) ,
EMUPAGESIZE , & emu - > silent_page ) < 0 ) {
2005-11-17 16:14:10 +01:00
err = - ENOMEM ;
goto error ;
2005-04-16 15:20:36 -07:00
}
emu - > memhdr = snd_util_memhdr_new ( emu - > max_cache_pages * PAGE_SIZE ) ;
if ( emu - > memhdr = = NULL ) {
2005-11-17 16:14:10 +01:00
err = - ENOMEM ;
goto error ;
2005-04-16 15:20:36 -07:00
}
2005-11-17 14:50:13 +01:00
emu - > memhdr - > block_extra_size = sizeof ( struct snd_emu10k1_memblk ) -
sizeof ( struct snd_util_memblk ) ;
2005-04-16 15:20:36 -07:00
pci_set_master ( pci ) ;
emu - > fx8010 . fxbus_mask = 0x303f ;
if ( extin_mask = = 0 )
extin_mask = 0x3fcf ;
if ( extout_mask = = 0 )
extout_mask = 0x7fff ;
emu - > fx8010 . extin_mask = extin_mask ;
emu - > fx8010 . extout_mask = extout_mask ;
2005-11-17 16:14:10 +01:00
emu - > enable_ir = enable_ir ;
2005-04-16 15:20:36 -07:00
2007-07-14 10:24:49 +01:00
if ( emu - > card_capabilities - > ca_cardbus_chip ) {
2008-10-23 18:51:00 +02:00
err = snd_emu10k1_cardbus_init ( emu ) ;
if ( err < 0 )
2007-07-14 10:24:49 +01:00
goto error ;
}
2005-03-30 13:51:18 +02:00
if ( emu - > card_capabilities - > ecard ) {
2008-10-23 18:51:00 +02:00
err = snd_emu10k1_ecard_init ( emu ) ;
if ( err < 0 )
2005-11-17 16:14:10 +01:00
goto error ;
2007-11-04 14:08:26 +00:00
} else if ( emu - > card_capabilities - > emu_model ) {
2008-10-23 18:51:00 +02:00
err = snd_emu10k1_emu1010_init ( emu ) ;
if ( err < 0 ) {
snd_emu10k1_free ( emu ) ;
return err ;
}
2005-04-16 15:20:36 -07:00
} else {
/* 5.1: Enable the additional AC97 Slots. If the emu10k1 version
does not support this , it shouldn ' t do any harm */
2008-10-23 18:51:00 +02:00
snd_emu10k1_ptr_write ( emu , AC97SLOT , 0 ,
AC97SLOT_CNTR | AC97SLOT_LFE ) ;
2005-04-16 15:20:36 -07:00
}
2005-11-17 16:14:10 +01:00
/* initialize TRAM setup */
emu - > fx8010 . itram_size = ( 16 * 1024 ) / 2 ;
emu - > fx8010 . etram_pages . area = NULL ;
emu - > fx8010 . etram_pages . bytes = 0 ;
2005-04-16 15:20:36 -07:00
2008-06-06 11:04:19 +02:00
/* irq handler must be registered after I/O ports are activated */
if ( request_irq ( pci - > irq , snd_emu10k1_interrupt , IRQF_SHARED ,
2011-06-10 16:36:37 +02:00
KBUILD_MODNAME , emu ) ) {
2008-06-06 11:04:19 +02:00
err = - EBUSY ;
goto error ;
}
emu - > irq = pci - > irq ;
2005-11-17 16:14:10 +01:00
/*
* Init to 0x02109204 :
* Clock accuracy = 0 ( 1000 ppm )
* Sample Rate = 2 ( 48 kHz )
* Audio Channel = 1 ( Left of 2 )
* Source Number = 0 ( Unspecified )
* Generation Status = 1 ( Original for Cat Code 12 )
* Cat Code = 12 ( Digital Signal Mixer )
* Mode = 0 ( Mode 0 )
* Emphasis = 0 ( None )
* CP = 1 ( Copyright unasserted )
* AN = 0 ( Audio data )
* P = 0 ( Consumer )
*/
emu - > spdif_bits [ 0 ] = emu - > spdif_bits [ 1 ] =
emu - > spdif_bits [ 2 ] = SPCS_CLKACCY_1000PPM | SPCS_SAMPLERATE_48 |
SPCS_CHANNELNUM_LEFT | SPCS_SOURCENUM_UNSPEC |
SPCS_GENERATIONSTATUS | 0x00001200 |
0x00000000 | SPCS_EMPHASIS_NONE | SPCS_COPYRIGHT ;
emu - > reserved_page = ( struct snd_emu10k1_memblk * )
snd_emu10k1_synth_alloc ( emu , 4096 ) ;
if ( emu - > reserved_page )
emu - > reserved_page - > map_locked = 1 ;
2008-10-23 18:51:00 +02:00
2005-11-17 16:14:10 +01:00
/* Clear silent pages and set up pointers */
memset ( emu - > silent_page . area , 0 , PAGE_SIZE ) ;
silent_page = emu - > silent_page . addr < < 1 ;
for ( idx = 0 ; idx < MAXPAGES ; idx + + )
( ( u32 * ) emu - > ptb_pages . area ) [ idx ] = cpu_to_le32 ( silent_page | idx ) ;
/* set up voice indices */
for ( idx = 0 ; idx < NUM_G ; idx + + ) {
emu - > voices [ idx ] . emu = emu ;
emu - > voices [ idx ] . number = idx ;
2005-04-16 15:20:36 -07:00
}
2008-10-23 18:51:00 +02:00
err = snd_emu10k1_init ( emu , enable_ir , 0 ) ;
if ( err < 0 )
2005-11-17 16:14:10 +01:00
goto error ;
2012-08-14 18:12:04 +02:00
# ifdef CONFIG_PM_SLEEP
2008-10-23 18:51:00 +02:00
err = alloc_pm_buffer ( emu ) ;
if ( err < 0 )
2005-11-17 16:14:10 +01:00
goto error ;
# endif
/* Initialize the effect engine */
2008-10-23 18:51:00 +02:00
err = snd_emu10k1_init_efx ( emu ) ;
if ( err < 0 )
2005-11-17 16:14:10 +01:00
goto error ;
snd_emu10k1_audio_enable ( emu ) ;
2008-10-23 18:51:00 +02:00
err = snd_device_new ( card , SNDRV_DEV_LOWLEVEL , emu , & ops ) ;
if ( err < 0 )
2005-11-17 16:14:10 +01:00
goto error ;
2005-12-01 10:49:58 +01:00
# ifdef CONFIG_PROC_FS
2005-04-16 15:20:36 -07:00
snd_emu10k1_proc_init ( emu ) ;
2005-12-01 10:49:58 +01:00
# endif
2005-04-16 15:20:36 -07:00
* remu = emu ;
return 0 ;
2005-11-17 16:14:10 +01:00
error :
snd_emu10k1_free ( emu ) ;
return err ;
2005-04-16 15:20:36 -07:00
}
2012-08-14 18:12:04 +02:00
# ifdef CONFIG_PM_SLEEP
2005-11-17 16:14:10 +01:00
static unsigned char saved_regs [ ] = {
CPF , PTRX , CVCF , VTFT , Z1 , Z2 , PSST , DSL , CCCA , CCR , CLP ,
FXRT , MAPA , MAPB , ENVVOL , ATKHLDV , DCYSUSV , LFOVAL1 , ENVVAL ,
ATKHLDM , DCYSUSM , LFOVAL2 , IP , IFATN , PEFE , FMMOD , TREMFRQ , FM2FRQ2 ,
TEMPENV , ADCCR , FXWC , MICBA , ADCBA , FXBA ,
MICBS , ADCBS , FXBS , CDCS , GPSCS , SPCS0 , SPCS1 , SPCS2 ,
SPBYPASS , AC97SLOT , CDSRCS , GPSRCS , ZVSRCS , MICIDX , ADCIDX , FXIDX ,
0xff /* end */
} ;
static unsigned char saved_regs_audigy [ ] = {
A_ADCIDX , A_MICIDX , A_FXWC1 , A_FXWC2 , A_SAMPLE_RATE ,
A_FXRT2 , A_SENDAMOUNTS , A_FXRT1 ,
0xff /* end */
} ;
2012-12-06 12:35:10 -05:00
static int alloc_pm_buffer ( struct snd_emu10k1 * emu )
2005-11-17 16:14:10 +01:00
{
int size ;
size = ARRAY_SIZE ( saved_regs ) ;
if ( emu - > audigy )
size + = ARRAY_SIZE ( saved_regs_audigy ) ;
emu - > saved_ptr = vmalloc ( 4 * NUM_G * size ) ;
2008-10-23 18:51:00 +02:00
if ( ! emu - > saved_ptr )
2005-11-17 16:14:10 +01:00
return - ENOMEM ;
if ( snd_emu10k1_efx_alloc_pm_buffer ( emu ) < 0 )
return - ENOMEM ;
if ( emu - > card_capabilities - > ca0151_chip & &
snd_p16v_alloc_pm_buffer ( emu ) < 0 )
return - ENOMEM ;
return 0 ;
}
static void free_pm_buffer ( struct snd_emu10k1 * emu )
{
vfree ( emu - > saved_ptr ) ;
snd_emu10k1_efx_free_pm_buffer ( emu ) ;
if ( emu - > card_capabilities - > ca0151_chip )
snd_p16v_free_pm_buffer ( emu ) ;
}
void snd_emu10k1_suspend_regs ( struct snd_emu10k1 * emu )
{
int i ;
unsigned char * reg ;
unsigned int * val ;
val = emu - > saved_ptr ;
for ( reg = saved_regs ; * reg ! = 0xff ; reg + + )
for ( i = 0 ; i < NUM_G ; i + + , val + + )
* val = snd_emu10k1_ptr_read ( emu , * reg , i ) ;
if ( emu - > audigy ) {
for ( reg = saved_regs_audigy ; * reg ! = 0xff ; reg + + )
for ( i = 0 ; i < NUM_G ; i + + , val + + )
* val = snd_emu10k1_ptr_read ( emu , * reg , i ) ;
}
if ( emu - > audigy )
emu - > saved_a_iocfg = inl ( emu - > port + A_IOCFG ) ;
emu - > saved_hcfg = inl ( emu - > port + HCFG ) ;
}
void snd_emu10k1_resume_init ( struct snd_emu10k1 * emu )
{
2007-07-14 10:24:49 +01:00
if ( emu - > card_capabilities - > ca_cardbus_chip )
snd_emu10k1_cardbus_init ( emu ) ;
2005-11-17 16:14:10 +01:00
if ( emu - > card_capabilities - > ecard )
snd_emu10k1_ecard_init ( emu ) ;
2007-11-04 14:08:26 +00:00
else if ( emu - > card_capabilities - > emu_model )
2008-10-23 18:51:00 +02:00
snd_emu10k1_emu1010_init ( emu ) ;
2005-11-17 16:14:10 +01:00
else
snd_emu10k1_ptr_write ( emu , AC97SLOT , 0 , AC97SLOT_CNTR | AC97SLOT_LFE ) ;
snd_emu10k1_init ( emu , emu - > enable_ir , 1 ) ;
}
void snd_emu10k1_resume_regs ( struct snd_emu10k1 * emu )
{
int i ;
unsigned char * reg ;
unsigned int * val ;
snd_emu10k1_audio_enable ( emu ) ;
/* resore for spdif */
if ( emu - > audigy )
2006-10-04 18:21:05 +02:00
outl ( emu - > saved_a_iocfg , emu - > port + A_IOCFG ) ;
outl ( emu - > saved_hcfg , emu - > port + HCFG ) ;
2005-11-17 16:14:10 +01:00
val = emu - > saved_ptr ;
for ( reg = saved_regs ; * reg ! = 0xff ; reg + + )
for ( i = 0 ; i < NUM_G ; i + + , val + + )
snd_emu10k1_ptr_write ( emu , * reg , i , * val ) ;
if ( emu - > audigy ) {
for ( reg = saved_regs_audigy ; * reg ! = 0xff ; reg + + )
for ( i = 0 ; i < NUM_G ; i + + , val + + )
snd_emu10k1_ptr_write ( emu , * reg , i , * val ) ;
}
}
# endif