patch-2.4.5 linux/drivers/sound/cs46xx.c
Next file: linux/drivers/sound/emu10k1/cardwo.c
Previous file: linux/drivers/sound/cs4281/cs4281m.c
Back to the patch index
Back to the overall index
- Lines: 652
- Date:
Thu May 24 15:14:08 2001
- Orig file:
v2.4.4/linux/drivers/sound/cs46xx.c
- Orig date:
Thu Apr 12 12:16:36 2001
diff -u --recursive --new-file v2.4.4/linux/drivers/sound/cs46xx.c linux/drivers/sound/cs46xx.c
@@ -47,6 +47,9 @@
* 20010117-tw 2.4.0 pci cleanup, wrapper code for 2.2.16-2.4.0
* 20010118-tw basic PM support for 2.2.16+ and 2.4.0/2.4.2.
* 20010228-dh patch from David Huggins - cs_update_ptr recursion.
+ * 20010409-tw add hercules game theatre XP amp code.
+ * 20010420-tw cleanup powerdown/up code.
+ * 20010521-tw eliminate pops, and fixes for powerdown.
*
* Status:
* Playback/Capture supported from 8k-48k.
@@ -56,9 +59,9 @@
* be enabled for 2.4.x by modifying the CS46XX_ACPI_SUPPORT macro
* definition.
*
- * Hercules Game Pro XP - the EGPIO2 pin controls the external Amp,
- * but the static image can not modify the EGPIO pins, so we can not
- * turn on the external amp.
+ * Hercules Game Theatre XP - the EGPIO2 pin controls the external Amp,
+ * so, use the drain/polarity to enable.
+ * hercules_egpio_disable set to 1, will force a 0 to EGPIODR.
*
* VTB Santa Cruz - the GPIO7/GPIO8 on the Secondary Codec control
* the external amplifier for the "back" speakers, since we do not
@@ -109,6 +112,11 @@
#define CS_TRUE 1
#define CS_FALSE 0
+#define CS_INC_USE_COUNT(m) (atomic_inc(m))
+#define CS_DEC_USE_COUNT(m) (atomic_dec(m))
+#define CS_DEC_AND_TEST(m) (atomic_dec_and_test(m))
+#define CS_IN_USE(m) (atomic_read(m) != 0)
+
#define CS_DBGBREAKPOINT {__asm__("INT $3");}
/*
* CS461x definitions
@@ -167,6 +175,8 @@
static unsigned long cs_debugmask=CS_INIT | CS_ERROR; /* use CS_DBGOUT with various mask values */
MODULE_PARM(cs_debugmask, "i");
#endif
+static unsigned long hercules_egpio_disable=0; /* if non-zero set all EGPIO to 0 */
+MODULE_PARM(hercules_egpio_disable, "i");
static unsigned long initdelay=700; /* PM delay in millisecs */
MODULE_PARM(initdelay, "i");
static unsigned long powerdown=1; /* turn on/off powerdown processing in driver */
@@ -189,7 +199,7 @@
};
#define CS46XX_MAJOR_VERSION "1"
-#define CS46XX_MINOR_VERSION "22"
+#define CS46XX_MINOR_VERSION "27"
#ifdef __ia64__
#define CS46XX_ARCH "64" //architecture key
@@ -287,6 +297,9 @@
so we use a single per card lock */
spinlock_t lock;
+ /* mixer use count */
+ atomic_t mixer_use_cnt;
+
/* PCI device stuff */
struct pci_dev * pci_dev;
struct list_head list;
@@ -358,6 +371,7 @@
static int cs_hardware_init(struct cs_card *card);
static int cs46xx_powerup(struct cs_card *card, unsigned int type);
static int cs461x_powerdown(struct cs_card *card, unsigned int type);
+static void cs461x_clear_serial_FIFOs(struct cs_card *card, int type);
static inline unsigned ld2(unsigned int x)
{
@@ -667,6 +681,45 @@
dmabuf->divisor) );
}
+/*
+* mute some of the more prevalent registers to avoid popping.
+*/
+static void cs_mute(struct cs_card *card, int state)
+{
+ struct ac97_codec *dev=card->ac97_codec[0];
+
+ CS_DBGOUT(CS_FUNCTION, 2, printk("cs46xx: cs_mute()+ %s\n",
+ (state == CS_TRUE) ? "Muting" : "UnMuting") );
+
+ if(state == CS_TRUE)
+ {
+ /*
+ * fix pops when powering up on thinkpads
+ */
+ card->pm.u32AC97_master_volume = (u32)cs_ac97_get( dev,
+ (u8)BA0_AC97_MASTER_VOLUME);
+ card->pm.u32AC97_headphone_volume = (u32)cs_ac97_get(dev,
+ (u8)BA0_AC97_HEADPHONE_VOLUME);
+ card->pm.u32AC97_master_volume_mono = (u32)cs_ac97_get(dev,
+ (u8)BA0_AC97_MASTER_VOLUME_MONO);
+ card->pm.u32AC97_pcm_out_volume = (u32)cs_ac97_get(dev,
+ (u8)BA0_AC97_PCM_OUT_VOLUME);
+
+ cs_ac97_set(dev, (u8)BA0_AC97_MASTER_VOLUME, 0x8000);
+ cs_ac97_set(dev, (u8)BA0_AC97_HEADPHONE_VOLUME, 0x8000);
+ cs_ac97_set(dev, (u8)BA0_AC97_MASTER_VOLUME_MONO, 0x8000);
+ cs_ac97_set(dev, (u8)BA0_AC97_PCM_OUT_VOLUME, 0x8000);
+ }
+ else
+ {
+ cs_ac97_set(dev, (u8)BA0_AC97_MASTER_VOLUME, card->pm.u32AC97_master_volume);
+ cs_ac97_set(dev, (u8)BA0_AC97_HEADPHONE_VOLUME, card->pm.u32AC97_headphone_volume);
+ cs_ac97_set(dev, (u8)BA0_AC97_MASTER_VOLUME_MONO, card->pm.u32AC97_master_volume_mono);
+ cs_ac97_set(dev, (u8)BA0_AC97_PCM_OUT_VOLUME, card->pm.u32AC97_pcm_out_volume);
+ }
+ CS_DBGOUT(CS_FUNCTION, 2, printk("cs46xx: cs_mute()-\n"));
+}
+
/* set playback sample rate */
static unsigned int cs_set_dac_rate(struct cs_state * state, unsigned int rate)
{
@@ -1386,12 +1439,17 @@
{
DECLARE_WAITQUEUE(wait, current);
struct dmabuf *dmabuf = &state->dmabuf;
+ struct cs_card *card=state->card;
unsigned long flags;
unsigned long tmo;
int count;
+ CS_DBGOUT(CS_FUNCTION, 4, printk("cs46xx: drain_dac()+ \n"));
if (dmabuf->mapped || !dmabuf->ready)
+ {
+ CS_DBGOUT(CS_FUNCTION, 4, printk("cs46xx: drain_dac()- 0, not ready\n"));
return 0;
+ }
add_wait_queue(&dmabuf->wait, &wait);
for (;;) {
@@ -1427,8 +1485,16 @@
remove_wait_queue(&dmabuf->wait, &wait);
current->state = TASK_RUNNING;
if (signal_pending(current))
+ {
+ CS_DBGOUT(CS_FUNCTION, 4, printk("cs46xx: drain_dac()- -ERESTARTSYS\n"));
+ /*
+ * set to silence and let that clear the fifos.
+ */
+ cs461x_clear_serial_FIFOs(card, CS_TYPE_DAC);
return -ERESTARTSYS;
+ }
+ CS_DBGOUT(CS_FUNCTION, 4, printk("cs46xx: drain_dac()- 0\n"));
return 0;
}
@@ -1524,7 +1590,7 @@
}
if (dmabuf->count < 0 || dmabuf->count > dmabuf->dmasize) {
- CS_DBGOUT(CS_ERROR, 2, printk(
+ CS_DBGOUT(CS_ERROR, 2, printk(KERN_INFO
"cs46xx: ERROR DAC count<0 or count > dmasize (%d)\n",
dmabuf->count));
/*
@@ -1584,7 +1650,7 @@
struct cs_state *playstate = card->channel[1].state;
u32 status;
- CS_DBGOUT(CS_INTERRUPT, 4, printk("cs46xx: cs_interrupt()+ \n"));
+ CS_DBGOUT(CS_INTERRUPT, 9, printk("cs46xx: cs_interrupt()+ \n"));
spin_lock(&card->lock);
@@ -1614,7 +1680,7 @@
/* clear 'em */
cs461x_pokeBA0(card, BA0_HICR, HICR_CHGM|HICR_IEV);
spin_unlock(&card->lock);
- CS_DBGOUT(CS_INTERRUPT, 4, printk("cs46xx: cs_interrupt()- \n"));
+ CS_DBGOUT(CS_INTERRUPT, 9, printk("cs46xx: cs_interrupt()- \n"));
}
@@ -2298,7 +2364,7 @@
if(state)
{
CS_DBGOUT(CS_OPEN, 2, printk(
- "cs46xx: cs_mmap() VM_WRITE - state CS_TRUE prog_dmabuf DAC\n") );
+ "cs46xx: cs_mmap() VM_WRITE - state TRUE prog_dmabuf DAC\n") );
if ((ret = prog_dmabuf(state)) != 0)
return ret;
}
@@ -2307,7 +2373,7 @@
if(state)
{
CS_DBGOUT(CS_OPEN, 2, printk(
- "cs46xx: cs_mmap() VM_READ - state CS_TRUE prog_dmabuf ADC\n") );
+ "cs46xx: cs_mmap() VM_READ - state TRUE prog_dmabuf ADC\n") );
if ((ret = prog_dmabuf(state)) != 0)
return ret;
}
@@ -2955,31 +3021,36 @@
}
}
+
/*
- * For the VTB Santa Cruz card, the Secondary Codec must have the
- * GPIO pins 7 and 8 manipulated, not the Primary codec.
- * Currently, only the primary codec is supported, so the following
- * code will not function. Additionally, slot 12 must be setup
- * to allow proper output for 7 and 8 to occur (trw).
+ * Game Theatre XP card - EGPIO[2] is used to enable the external amp.
*/
-static void amp_voyetra_4294(struct cs_card *card, int change)
+static void amp_hercules(struct cs_card *card, int change)
{
- struct ac97_codec *c=card->ac97_codec[0];
-
+ int old=card->amplifier;
+ if(!card)
+ {
+ CS_DBGOUT(CS_ERROR, 2, printk(KERN_INFO
+ "cs46xx: amp_hercules() called before initialized.\n"));
+ return;
+ }
card->amplifier+=change;
-
- if(card->amplifier)
+ if( (card->amplifier && !old) && !(hercules_egpio_disable))
{
- /* Switch the GPIO pins 7 and 8 to open drain */
- cs_ac97_set(c, 0x4C, cs_ac97_get(c, 0x4C) & 0xFE7F);
- cs_ac97_set(c, 0x4E, cs_ac97_get(c, 0x4E) | 0x0180);
- /* Now wake the AMP (this might be backwards) */
- cs_ac97_set(c, 0x54, cs_ac97_get(c, 0x54) & ~0x0180);
+ CS_DBGOUT(CS_PARMS, 4, printk(KERN_INFO
+ "cs46xx: amp_hercules() external amp enabled\n"));
+ cs461x_pokeBA0(card, BA0_EGPIODR,
+ EGPIODR_GPOE2); /* enable EGPIO2 output */
+ cs461x_pokeBA0(card, BA0_EGPIOPTR,
+ EGPIOPTR_GPPT2); /* open-drain on output */
}
- else
+ else if(old && !card->amplifier)
{
- cs_ac97_set(c, 0x54, cs_ac97_get(c, 0x54) | 0x0180);
+ CS_DBGOUT(CS_PARMS, 4, printk(KERN_INFO
+ "cs46xx: amp_hercules() external amp disabled\n"));
+ cs461x_pokeBA0(card, BA0_EGPIODR, 0); /* disable */
+ cs461x_pokeBA0(card, BA0_EGPIOPTR, 0); /* disable */
}
}
@@ -3016,7 +3087,7 @@
/* Flip CLKRUN off while running */
if(!card->active && old)
{
- CS_DBGOUT(CS_PARMS , 9, printk(
+ CS_DBGOUT(CS_PARMS , 9, printk( KERN_INFO
"cs46xx: clkrun() enable clkrun - change=%d active=%d\n",
change,card->active));
outw(control|0x2000, port+0x10);
@@ -3026,7 +3097,7 @@
/*
* sometimes on a resume the bit is set, so always reset the bit.
*/
- CS_DBGOUT(CS_PARMS , 9, printk(
+ CS_DBGOUT(CS_PARMS , 9, printk( KERN_INFO
"cs46xx: clkrun() disable clkrun - change=%d active=%d\n",
change,card->active));
outw(control&~0x2000, port+0x10);
@@ -3404,7 +3475,7 @@
"cs46xx: cs46xx_ac97_suspend() failure (0x%x)\n",tmp) );
}
- CS_DBGOUT(CS_PM, 9, printk("cs4281: cs46xx_ac97_suspend()-\n"));
+ CS_DBGOUT(CS_PM, 9, printk("cs46xx: cs46xx_ac97_suspend()-\n"));
}
/****************************************************************************
@@ -3417,7 +3488,7 @@
int Count,i;
struct ac97_codec *dev=card->ac97_codec[0];
- CS_DBGOUT(CS_PM, 9, printk("cs4281: cs46xx_ac97_resume()+\n"));
+ CS_DBGOUT(CS_PM, 9, printk("cs46xx: cs46xx_ac97_resume()+\n"));
/*
* First, we restore the state of the general purpose register. This
@@ -3458,7 +3529,7 @@
if(card->amp_init)
card->amp_init(card);
- CS_DBGOUT(CS_PM, 9, printk("cs4281: cs46xx_ac97_resume()-\n"));
+ CS_DBGOUT(CS_PM, 9, printk("cs46xx: cs46xx_ac97_resume()-\n"));
}
@@ -3521,7 +3592,7 @@
{
unsigned int tmp;
CS_DBGOUT(CS_PM | CS_FUNCTION, 4,
- printk("cs46xx: cs46xx_suspend()+ flags=%d s=0x%x\n",
+ printk("cs46xx: cs46xx_suspend()+ flags=0x%x s=0x%x\n",
(unsigned)card->pm.flags,(unsigned)card));
/*
* check the current state, only suspend if IDLE
@@ -3604,7 +3675,7 @@
printpm(card);
CS_DBGOUT(CS_PM | CS_FUNCTION, 4,
- printk("cs46xx: cs46xx_suspend()- flags=%d\n",
+ printk("cs46xx: cs46xx_suspend()- flags=0x%x\n",
(unsigned)card->pm.flags));
return 0;
}
@@ -3614,7 +3685,7 @@
int i;
CS_DBGOUT(CS_PM | CS_FUNCTION, 4,
- printk( "cs46xx: cs46xx_resume()+ flags=%d\n",
+ printk( "cs46xx: cs46xx_resume()+ flags=0x%x\n",
(unsigned)card->pm.flags));
if(!(card->pm.flags & CS46XX_PM_SUSPENDED))
{
@@ -3654,7 +3725,7 @@
card->active_ctrl(card, -1);
- CS_DBGOUT(CS_PM | CS_FUNCTION, 4, printk("cs46xx: cs46xx_resume()- flags=%d\n",
+ CS_DBGOUT(CS_PM | CS_FUNCTION, 4, printk("cs46xx: cs46xx_resume()- flags=0x%x\n",
(unsigned)card->pm.flags));
return 0;
}
@@ -3919,12 +3990,17 @@
file->private_data = card->ac97_codec[i];
card->active_ctrl(card,1);
- if( (tmp = cs46xx_powerup(card, CS_POWER_MIXVON )) )
+ if(!CS_IN_USE(&card->mixer_use_cnt))
{
- CS_DBGOUT(CS_ERROR | CS_INIT, 1, printk(KERN_INFO
- "cs46xx: cs_open_mixdev() powerup failure (0x%x)\n",tmp) );
- return -EIO;
+ if( (tmp = cs46xx_powerup(card, CS_POWER_MIXVON )) )
+ {
+ CS_DBGOUT(CS_ERROR | CS_INIT, 1, printk(KERN_INFO
+ "cs46xx: cs_open_mixdev() powerup failure (0x%x)\n",tmp) );
+ return -EIO;
+ }
}
+ card->amplifier_ctrl(card, 1);
+ CS_INC_USE_COUNT(&card->mixer_use_cnt);
MOD_INC_USE_COUNT;
CS_DBGOUT(CS_FUNCTION | CS_OPEN, 4,
printk(KERN_INFO "cs46xx: cs_open_mixdev()- 0\n"));
@@ -3938,8 +4014,9 @@
struct list_head *entry;
int i;
unsigned int tmp;
-
-
+
+ CS_DBGOUT(CS_FUNCTION | CS_RELEASE, 4,
+ printk(KERN_INFO "cs46xx: cs_release_mixdev()+\n"));
list_for_each(entry, &cs46xx_devs)
{
card = list_entry(entry, struct cs_card, list);
@@ -3955,14 +4032,26 @@
return -ENODEV;
}
match:
+ card->active_ctrl(card, -1);
+ card->amplifier_ctrl(card, -1);
+ MOD_DEC_USE_COUNT;
+ if(!CS_DEC_AND_TEST(&card->mixer_use_cnt))
+ {
+ CS_DBGOUT(CS_FUNCTION | CS_RELEASE, 4,
+ printk(KERN_INFO "cs46xx: cs_release_mixdev()- no powerdown, usecnt>0\n"));
+ return 0;
+ }
+/*
+* ok, no outstanding mixer opens, so powerdown.
+*/
if( (tmp = cs461x_powerdown(card, CS_POWER_MIXVON )) )
{
CS_DBGOUT(CS_ERROR | CS_INIT, 1, printk(KERN_INFO
"cs46xx: cs_release_mixdev() powerdown MIXVON failure (0x%x)\n",tmp) );
return -EIO;
}
- card->active_ctrl(card, -1);
- MOD_DEC_USE_COUNT;
+ CS_DBGOUT(CS_FUNCTION | CS_RELEASE, 4,
+ printk(KERN_INFO "cs46xx: cs_release_mixdev()- 0\n"));
return 0;
}
@@ -4027,7 +4116,7 @@
else
{
CS_DBGOUT(CS_ERROR, 1, printk(KERN_INFO
- "cs4281: mixer_ioctl(): invalid APM cmd (%d)\n",
+ "cs46xx: mixer_ioctl(): invalid APM cmd (%d)\n",
val));
}
return 0;
@@ -4181,9 +4270,9 @@
cs461x_poke(card, BA1_FRMT, 0xadf);
}
-static void cs461x_clear_serial_FIFOs(struct cs_card *card)
+static void cs461x_clear_serial_FIFOs(struct cs_card *card, int type)
{
- int idx, loop, powerdown = 0;
+ int idx, loop, startfifo=0, endfifo=0, powerdown1 = 0;
unsigned int tmp;
/*
@@ -4192,7 +4281,7 @@
*/
if (!((tmp = cs461x_peekBA0(card, BA0_CLKCR1)) & CLKCR1_SWCE)) {
cs461x_pokeBA0(card, BA0_CLKCR1, tmp | CLKCR1_SWCE);
- powerdown = 1;
+ powerdown1 = 1;
}
/*
@@ -4203,9 +4292,25 @@
cs461x_pokeBA0(card, BA0_SERBWP, 0);
/*
- * Fill all 256 sample FIFO locations.
+ * Check for which FIFO locations to clear, if we are currently
+ * playing or capturing then we don't want to put in 128 bytes of
+ * "noise".
+ */
+ if(type & CS_TYPE_DAC)
+ {
+ startfifo = 128;
+ endfifo = 256;
+ }
+ if(type & CS_TYPE_ADC)
+ {
+ startfifo = 0;
+ if(!endfifo)
+ endfifo = 128;
+ }
+ /*
+ * Fill sample FIFO locations (256 locations total).
*/
- for (idx = 0; idx < 256; idx++) {
+ for (idx = startfifo; idx < endfifo; idx++) {
/*
* Make sure the previous FIFO write operation has completed.
*/
@@ -4215,7 +4320,7 @@
break;
}
if (cs461x_peekBA0(card, BA0_SERBST) & SERBST_WBSY) {
- if (powerdown)
+ if (powerdown1)
cs461x_pokeBA0(card, BA0_CLKCR1, tmp);
}
/*
@@ -4231,7 +4336,7 @@
* Now, if we powered up the devices, then power them back down again.
* This is kinda ugly, but should never happen.
*/
- if (powerdown)
+ if (powerdown1)
cs461x_pokeBA0(card, BA0_CLKCR1, tmp);
}
@@ -4268,6 +4373,15 @@
"cs46xx: cs461x_powerdown()- 0 unable to powerdown. tmp=0x%x\n",tmp));
return 0;
}
+/*
+* for now, always keep power to the mixer block.
+* not sure why it's a problem but it seems to be if we power off.
+*/
+ type &= ~CS_POWER_MIXVON;
+ type &= ~CS_POWER_MIXVOFF;
+
+ cs_mute(card, CS_TRUE);
+
/*
* Power down indicated areas.
*/
@@ -4443,6 +4557,7 @@
}
}
tmp = cs_ac97_get(card->ac97_codec[0], AC97_POWER_CONTROL);
+ cs_mute(card, CS_FALSE);
CS_DBGOUT(CS_FUNCTION, 4, printk(KERN_INFO
"cs46xx: cs461x_powerdown()- 0 tmp=0x%x\n",tmp));
return 0;
@@ -4462,6 +4577,8 @@
type |= CS_POWER_MIXVOFF;
if(type & (CS_POWER_DAC | CS_POWER_ADC))
type |= CS_POWER_MIXVON | CS_POWER_MIXVOFF;
+
+ cs_mute(card, CS_TRUE);
/*
* Power up indicated areas.
*/
@@ -4637,6 +4754,7 @@
}
}
tmp = cs_ac97_get(card->ac97_codec[0], AC97_POWER_CONTROL);
+ cs_mute(card, CS_FALSE);
CS_DBGOUT(CS_FUNCTION, 4, printk(KERN_INFO
"cs46xx: cs46xx_powerup()- 0 tmp=0x%x\n",tmp));
return 0;
@@ -4741,7 +4859,6 @@
*/
if(!(card->pm.flags & CS46XX_PM_IDLE))
mdelay(initdelay);
-
/*
* Write the selected clock control setup to the hardware. Do not turn on
* SWCE yet (if requested), so that the devices clocked by the output of
@@ -4770,7 +4887,7 @@
/*
* Fill the serial port FIFOs with silence.
*/
- cs461x_clear_serial_FIFOs(card);
+ cs461x_clear_serial_FIFOs(card,CS_TYPE_DAC | CS_TYPE_ADC);
/*
* Set the serial port FIFO pointer to the first sample in the FIFO.
@@ -4951,12 +5068,25 @@
*/
if(card->pm.flags & CS46XX_PM_IDLE)
{
- if( (tmp = cs461x_powerdown(card, CS_POWER_DAC | CS_POWER_ADC |
- CS_POWER_MIXVON )) )
+ if(!powerdown)
{
- CS_DBGOUT(CS_ERROR | CS_INIT, 1, printk(KERN_INFO
- "cs46xx: cs461x_powerdown() failure (0x%x)\n",tmp) );
- return -EIO;
+ if( (tmp = cs46xx_powerup(card, CS_POWER_DAC | CS_POWER_ADC |
+ CS_POWER_MIXVON )) )
+ {
+ CS_DBGOUT(CS_ERROR | CS_INIT, 1, printk(KERN_INFO
+ "cs46xx: cs461x_powerup() failure (0x%x)\n",tmp) );
+ return -EIO;
+ }
+ }
+ else
+ {
+ if( (tmp = cs461x_powerdown(card, CS_POWER_DAC | CS_POWER_ADC |
+ CS_POWER_MIXVON )) )
+ {
+ CS_DBGOUT(CS_ERROR | CS_INIT, 1, printk(KERN_INFO
+ "cs46xx: cs461x_powerdown() failure (0x%x)\n",tmp) );
+ return -EIO;
+ }
}
}
CS_DBGOUT(CS_FUNCTION | CS_INIT, 2, printk(KERN_INFO
@@ -4964,11 +5094,9 @@
return 0;
}
-
/* install the driver, we do not allocate hardware channel nor DMA buffer now, they are defered
until "ACCESS" time (in prog_dmabuf called by open/read/write/ioctl/mmap) */
-
/*
* Card subid table
*/
@@ -4987,8 +5115,12 @@
{0x1489, 0x7001, "Genius Soundmaker 128 value", amp_none, NULL, NULL},
{0x5053, 0x3357, "Voyetra", amp_voyetra, NULL, NULL},
{0x1071, 0x6003, "Mitac MI6020/21", amp_voyetra, NULL, NULL},
- {0x14AF, 0x0050, "Hercules Game Theatre XP", NULL, NULL, NULL},
- {0x1681, 0x0050, "Hercules Game Theatre XP", NULL, NULL, NULL},
+ {0x14AF, 0x0050, "Hercules Game Theatre XP", amp_hercules, NULL, NULL},
+ {0x1681, 0x0050, "Hercules Game Theatre XP", amp_hercules, NULL, NULL},
+ {0x1681, 0x0051, "Hercules Game Theatre XP", amp_hercules, NULL, NULL},
+ {0x1681, 0x0052, "Hercules Game Theatre XP", amp_hercules, NULL, NULL},
+ {0x1681, 0x0053, "Hercules Game Theatre XP", amp_hercules, NULL, NULL},
+ {0x1681, 0x0054, "Hercules Game Theatre XP", amp_hercules, NULL, NULL},
/* Not sure if the 570 needs the clkrun hack */
{PCI_VENDOR_ID_IBM, 0x0132, "Thinkpad 570", amp_none, NULL, clkrun_hack},
{PCI_VENDOR_ID_IBM, 0x0153, "Thinkpad 600X/A20/T20", amp_none, NULL, clkrun_hack},
@@ -5016,6 +5148,11 @@
CS_DBGOUT(CS_FUNCTION | CS_INIT, 2,
printk(KERN_INFO "cs46xx: probe()+\n"));
+ if (pci_enable_device(pci_dev)) {
+ CS_DBGOUT(CS_INIT | CS_ERROR, 1, printk(KERN_ERR
+ "cs46xx: pci_enable_device() failed\n"));
+ return -1;
+ }
if (!RSRCISMEMORYREGION(pci_dev, 0) ||
!RSRCISMEMORYREGION(pci_dev, 1)) {
CS_DBGOUT(CS_ERROR, 1, printk(KERN_ERR
@@ -5042,12 +5179,6 @@
return -ENOMEM;
}
memset(card, 0, sizeof(*card));
-
- if (pci_enable_device(pci_dev)) {
- CS_DBGOUT(CS_INIT | CS_ERROR, 1, printk(KERN_ERR
- "cs46xx: pci_enable_device() failed\n"));
- goto fail2;
- }
card->ba0_addr = RSRCADDRESS(pci_dev, 0);
card->ba1_addr = RSRCADDRESS(pci_dev, 1);
card->pci_dev = pci_dev;
@@ -5096,7 +5227,7 @@
card->amplifier_ctrl = amp_none;
card->active_ctrl = clkrun_hack;
}
-
+
if (external_amp == 1)
{
printk(KERN_INFO "cs46xx: Crystal EAPD support forced on.\n");
@@ -5120,7 +5251,7 @@
card->ba1.name.reg = ioremap_nocache(card->ba1_addr + BA1_SP_REG, CS461X_BA1_REG_SIZE);
CS_DBGOUT(CS_INIT, 4, printk(KERN_INFO
- "cs46xx: card->ba0=0x%.08x\n",(unsigned)card->ba0) );
+ "cs46xx: card=0x%x card->ba0=0x%.08x\n",(unsigned)card,(unsigned)card->ba0) );
CS_DBGOUT(CS_INIT, 4, printk(KERN_INFO
"cs46xx: card->ba1=0x%.08x 0x%.08x 0x%.08x 0x%.08x\n",
(unsigned)card->ba1.name.data0,
@@ -5319,9 +5450,9 @@
unregister_sound_dsp(card->dev_audio);
if(card->dev_midi)
unregister_sound_midi(card->dev_midi);
+ list_del(&card->list);
kfree(card);
PCI_SET_DRIVER_DATA(pci_dev,NULL);
- list_del(&card->list);
CS_DBGOUT(CS_INIT | CS_FUNCTION, 2, printk(KERN_INFO
"cs46xx: cs46xx_remove()-: remove successful\n"));
@@ -5329,8 +5460,8 @@
enum {
CS46XX_4610 = 0,
- CS46XX_4612, /* same as 4624 */
- CS46XX_4615, /* same as 4630 */
+ CS46XX_4612, /* same as 4630 */
+ CS46XX_4615, /* same as 4624 */
};
static struct pci_device_id cs46xx_pci_tbl[] __devinitdata = {
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)