patch-2.4.0-test2 linux/drivers/sound/trident.c
Next file: linux/drivers/sound/via82cxxx_audio.c
Previous file: linux/drivers/sound/soundcard.c
Back to the patch index
Back to the overall index
- Lines: 373
- Date:
Tue Jun 20 07:52:36 2000
- Orig file:
v2.4.0-test1/linux/drivers/sound/trident.c
- Orig date:
Tue May 23 15:31:35 2000
diff -u --recursive --new-file v2.4.0-test1/linux/drivers/sound/trident.c linux/drivers/sound/trident.c
@@ -1,6 +1,6 @@
/*
*
- * Trident 4D-Wave/SiS 7018 OSS driver for Linux 2.2.x
+ * Trident 4D-Wave/SiS 7018/ALi 5451 OSS driver for Linux 2.2.x
*
* Driver: Alan Cox <alan@redhat.com>
*
@@ -12,6 +12,7 @@
* Hacked up by:
* Aaron Holtzman <aholtzma@ess.engr.uvic.ca>
* Ollie Lho <ollie@sis.com.tw> SiS 7018 Audio Core Support
+ * Ching Ling Lee <cling-li@ali.com.tw> ALi 5451 Audio Core Support
*
*
* This program is free software; you can redistribute it and/or modify
@@ -29,10 +30,14 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
* History
- * v0.14.3 May 20 2000 Aaron Holtzman
- * Fix kfree'd memory access in release
- * Fix race in open while looking for a free virtual channel slot
- * remove open_wait wq (which appears to be unused)
+ * v0.14.5 May 23 2000 Ollie Lho
+ * Misc bug fix from the Net
+ * v0.14.4 May 20 2000 Aaron Holtzman
+ * Fix kfree'd memory access in release
+ * Fix race in open while looking for a free virtual channel slot
+ * remove open_wait wq (which appears to be unused)
+ * v0.14.3 May 10 2000 Ollie Lho
+ * fixed a small bug in trident_update_ptr, xmms 1.0.1 no longer uses 100% CPU
* v0.14.2 Mar 29 2000 Ching Ling Lee
* Add clear to silence advance in trident_update_ptr
* fix invalid data of the end of the sound
@@ -109,13 +114,13 @@
#include "trident.h"
-#define DRIVER_VERSION "0.14"
+#define DRIVER_VERSION "0.14.5"
/* magic numbers to protect our data structures */
#define TRIDENT_CARD_MAGIC 0x5072696E /* "Prin" */
#define TRIDENT_STATE_MAGIC 0x63657373 /* "cess" */
-#define TRIDENT_DMA_MASK 0x3fffffff /* DMA buffer mask for pci_alloc_consist */
+#define TRIDENT_DMA_MASK 0x3fffffff /* DMA buffer mask for pci_alloc_consist */
#define NR_HW_CH 32
@@ -151,7 +156,7 @@
"ALi Audio Accelerator"
};
-static struct pci_device_id trident_pci_tbl [] __initdata = {
+static struct pci_device_id trident_pci_tbl [] __devinitdata = {
{PCI_VENDOR_ID_TRIDENT, PCI_DEVICE_ID_TRIDENT_4DWAVE_DX,
PCI_ANY_ID, PCI_ANY_ID, 0, 0, TRIDENT_4D_DX},
{PCI_VENDOR_ID_TRIDENT, PCI_DEVICE_ID_TRIDENT_4DWAVE_NX,
@@ -314,7 +319,6 @@
static u16 trident_ac97_get(struct ac97_codec *codec, u8 reg);
static int trident_open_mixdev(struct inode *inode, struct file *file);
-static int trident_release_mixdev(struct inode *inode, struct file *file);
static int trident_ioctl_mixdev(struct inode *inode, struct file *file, unsigned int cmd,
unsigned long arg);
static loff_t trident_llseek(struct file *file, loff_t offset, int origin);
@@ -438,16 +442,14 @@
#endif
}
-static u32 trident_get_interrupt_mask (struct trident_card * card,
- unsigned int b)
+static u32 trident_get_interrupt_mask (struct trident_card * card, unsigned int channel)
{
- struct trident_pcm_bank *bank = &card->banks[b];
+ struct trident_pcm_bank *bank = &card->banks[channel];
u32 addr = bank->addresses->aint;
return inl(TRID_REG(card, addr));
}
-static int trident_check_channel_interrupt(struct trident_card * card,
- unsigned int channel)
+static int trident_check_channel_interrupt(struct trident_card * card, unsigned int channel)
{
unsigned int mask = 1 << (channel & 0x1f);
u32 reg = trident_get_interrupt_mask (card, channel >> 5);
@@ -460,8 +462,7 @@
return (reg & mask) ? TRUE : FALSE;
}
-static void trident_ack_channel_interrupt(struct trident_card * card,
- unsigned int channel)
+static void trident_ack_channel_interrupt(struct trident_card * card, unsigned int channel)
{
unsigned int mask = 1 << (channel & 0x1f);
struct trident_pcm_bank *bank = &card->banks[channel >> 5];
@@ -537,8 +538,7 @@
}
-static void trident_free_pcm_channel(struct trident_card *card,
- unsigned int channel)
+static void trident_free_pcm_channel(struct trident_card *card, int channel)
{
int bank;
@@ -551,7 +551,7 @@
card->banks[bank].bitmap &= ~(1 << (channel));
}
-static void ali_free_pcm_channel(struct trident_card *card, unsigned int channel)
+static void ali_free_pcm_channel(struct trident_card *card, int channel)
{
int bank;
@@ -574,18 +574,16 @@
if (channel > 63)
return FALSE;
- /* select hardware channel to write */
+ /* select hardware channel to write */
outb(channel, TRID_REG(card, T4D_LFO_GC_CIR));
/* Output the channel registers, but don't write register
three to an ALI chip. */
-
for (i = 0; i < CHANNEL_REGS; i++) {
if (i == 3 && card->pci_id == PCI_DEVICE_ID_ALI_5451)
continue;
outl(data[i], TRID_REG(card, CHANNEL_START + 4*i));
}
-
return TRUE;
}
@@ -1141,7 +1139,7 @@
dmabuf->hwptr = hwptr;
dmabuf->total_bytes += diff;
- /* error handling and process wake up for DAC */
+ /* error handling and process wake up for ADC */
if (dmabuf->enable == ADC_RUNNING) {
if (dmabuf->mapped) {
dmabuf->count -= diff;
@@ -1171,7 +1169,10 @@
//there is invalid data in the end of half buffer
if ((clear_cnt = half_dmasize - swptr) < 0)
clear_cnt += half_dmasize;
- memset (dmabuf->rawbuf + swptr, silence, clear_cnt); //clear the invalid data
+ //clear the invalid data
+ memset (dmabuf->rawbuf + swptr,
+ silence, clear_cnt);
+
dmabuf->endcleared = 1;
}
} else if (dmabuf->count < (signed) dmabuf->fragsize) {
@@ -1181,12 +1182,15 @@
memset (dmabuf->rawbuf + swptr, silence, clear_cnt);
dmabuf->endcleared = 1;
}
- }
- /* since dma machine only interrupts at ESO and ESO/2, we sure have at
- least half of dma buffer free, so wake up the process unconditionally */
- wake_up(&dmabuf->wait);
+ }
+ /* trident_update_ptr is called by interrupt handler or by process via
+ ioctl/poll, we only wake up the waiting process when we have more
+ than 1/2 buffer of data to process (always true for interrupt handler) */
+ if (dmabuf->count > (signed)dmabuf->dmasize/2)
+ wake_up(&dmabuf->wait);
}
}
+
/* error handling and process wake up for DAC */
if (dmabuf->enable == DAC_RUNNING) {
if (dmabuf->mapped) {
@@ -1203,9 +1207,11 @@
__stop_dac(state);
dmabuf->error++;
}
- /* since dma machine only interrupts at ESO and ESO/2, we sure have at
- least half of dma buffer free, so wake up the process unconditionally */
- wake_up(&dmabuf->wait);
+ /* trident_update_ptr is called by interrupt handler or by process via
+ ioctl/poll, we only wake up the waiting process when we have more
+ than 1/2 buffer free (always true for interrupt handler) */
+ if (dmabuf->count < (signed)dmabuf->dmasize/2)
+ wake_up(&dmabuf->wait);
}
}
dmabuf->update_flag &= ~ALI_ADDRESS_INT_UPDATE;
@@ -1336,7 +1342,8 @@
ret = 0;
if (state->card->pci_id == PCI_DEVICE_ID_ALI_5451)
- outl ( inl (TRID_REG (state->card, ALI_GLOBAL_CONTROL)) | ALI_PCM_IN_ENABLE, TRID_REG (state->card, ALI_GLOBAL_CONTROL));
+ outl(inl(TRID_REG (state->card, ALI_GLOBAL_CONTROL)) | ALI_PCM_IN_ENABLE,
+ TRID_REG (state->card, ALI_GLOBAL_CONTROL));
while (count > 0) {
spin_lock_irqsave(&state->card->lock, flags);
@@ -1439,7 +1446,8 @@
if (state->card->pci_id == PCI_DEVICE_ID_ALI_5451)
if (dmabuf->channel->num == ALI_PCM_IN_CHANNEL)
- outl ( inl (TRID_REG (state->card, ALI_GLOBAL_CONTROL)) & ALI_PCM_IN_DISABLE, TRID_REG (state->card, ALI_GLOBAL_CONTROL));
+ outl ( inl (TRID_REG (state->card, ALI_GLOBAL_CONTROL)) &
+ ALI_PCM_IN_DISABLE, TRID_REG (state->card, ALI_GLOBAL_CONTROL));
while (count > 0) {
spin_lock_irqsave(&state->card->lock, flags);
@@ -1912,8 +1920,9 @@
if (card->states[i] == NULL) {
state = card->states[i] = (struct trident_state *)
kmalloc(sizeof(struct trident_state), GFP_KERNEL);
- if (state == NULL)
+ if (state == NULL) {
return -ENOMEM;
+ }
memset(state, 0, sizeof(struct trident_state));
dmabuf = &state->dmabuf;
goto found_virt;
@@ -1923,9 +1932,9 @@
card = card->next;
}
/* no more virtual channel avaiable */
- if (!state)
+ if (!state) {
return -ENODEV;
-
+ }
found_virt:
/* found a free virtual channel, allocate hardware channels */
if(file->f_mode & FMODE_READ)
@@ -1946,7 +1955,6 @@
init_waitqueue_head(&dmabuf->wait);
file->private_data = state;
-
/* set default sample format. According to OSS Programmer's Guide /dev/dsp
should be default to unsigned 8-bits, mono, with sample rate 8kHz and
/dev/dspW will accept 16-bits sample */
@@ -1991,11 +1999,10 @@
up(&card->open_sem);
#ifdef DEBUG
- printk(KERN_ERR "trident: open virtual channel %d, hard channel %d\n",
- state->virt,
- dmabuf->channel->num);
+ printk(KERN_ERR "trident: open virtual channel %d, hard channel %d\n",
+ state->virt, dmabuf->channel->num);
#endif
- MOD_INC_USE_COUNT;
+
return 0;
}
@@ -2020,7 +2027,6 @@
dealloc_dmabuf(state);
state->card->free_pcm_channel(state->card, dmabuf->channel->num);
}
-
if (file->f_mode & FMODE_READ) {
stop_adc(state);
dealloc_dmabuf(state);
@@ -2033,11 +2039,11 @@
/* we're covered by the open_sem */
up(&card->open_sem);
- MOD_DEC_USE_COUNT;
return 0;
}
static /*const*/ struct file_operations trident_audio_fops = {
+ owner: THIS_MODULE,
llseek: trident_llseek,
read: trident_read,
write: trident_write,
@@ -2261,19 +2267,13 @@
card->ac97_codec[i]->dev_mixer == minor)
goto match;
- if (!card)
+ if (!card) {
return -ENODEV;
-
+ }
match:
file->private_data = card->ac97_codec[i];
- MOD_INC_USE_COUNT;
- return 0;
-}
-static int trident_release_mixdev(struct inode *inode, struct file *file)
-{
- MOD_DEC_USE_COUNT;
return 0;
}
@@ -2286,10 +2286,10 @@
}
static /*const*/ struct file_operations trident_mixer_fops = {
+ owner: THIS_MODULE,
llseek: trident_llseek,
ioctl: trident_ioctl_mixdev,
open: trident_open_mixdev,
- release: trident_release_mixdev,
};
/* AC97 codec initialisation. */
@@ -2385,7 +2385,7 @@
}
pci_read_config_byte(pci_dev, PCI_CLASS_REVISION, &revision);
- iobase = pci_resource_start (pci_dev, 0);
+ iobase = pci_resource_start(pci_dev, 0);
if (check_region(iobase, 256)) {
printk(KERN_ERR "trident: can't allocate I/O space at 0x%4.4lx\n",
iobase);
@@ -2393,7 +2393,7 @@
}
if (pci_enable_device(pci_dev))
- return -ENODEV;
+ return -ENODEV;
if ((card = kmalloc(sizeof(struct trident_card), GFP_KERNEL)) == NULL) {
printk(KERN_ERR "trident: out of memory\n");
@@ -2421,20 +2421,19 @@
printk(KERN_INFO "trident: %s found at IO 0x%04lx, IRQ %d\n",
card_names[pci_id->driver_data], card->iobase, card->irq);
- if(card->pci_id == PCI_DEVICE_ID_ALI_5451)
- {
+ if(card->pci_id == PCI_DEVICE_ID_ALI_5451) {
card->alloc_pcm_channel = ali_alloc_pcm_channel;
card->alloc_rec_pcm_channel = ali_alloc_rec_pcm_channel;
card->free_pcm_channel = ali_free_pcm_channel;
card->address_interrupt = ali_address_interrupt;
}
- else
- {
+ else {
card->alloc_pcm_channel = trident_alloc_pcm_channel;
card->alloc_rec_pcm_channel = trident_alloc_pcm_channel;
card->free_pcm_channel = trident_free_pcm_channel;
card->address_interrupt = trident_address_interrupt;
}
+
/* claim our iospace and irq */
request_region(card->iobase, 256, card_names[pci_id->driver_data]);
if (request_irq(card->irq, &trident_interrupt, SA_SHIRQ,
@@ -2462,12 +2461,12 @@
}
outl(0x00, TRID_REG(card, T4D_MUSICVOL_WAVEVOL));
- if (card->pci_id == PCI_DEVICE_ID_ALI_5451)
- {
+ if (card->pci_id == PCI_DEVICE_ID_ALI_5451) {
/* edited by HMSEO for GT sound */
#ifdef CONFIG_ALPHA_NAUTILUS
- ac97_data = trident_ac97_get (card->ac97_codec[0], AC97_POWER_CONTROL);
- trident_ac97_set (card->ac97_codec[0], AC97_POWER_CONTROL, ac97_data | ALI_EAPD_POWER_DOWN);
+ u16 ac97_data = trident_ac97_get (card->ac97_codec[0], AC97_POWER_CONTROL);
+ trident_ac97_set (card->ac97_codec[0], AC97_POWER_CONTROL,
+ ac97_data | ALI_EAPD_POWER_DOWN);
#endif
/* edited by HMSEO for GT sound*/
}
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)