summaryrefslogtreecommitdiffstats
path: root/drivers/sound/trident.c
diff options
context:
space:
mode:
authorRalf Baechle <ralf@linux-mips.org>2000-04-28 01:09:25 +0000
committerRalf Baechle <ralf@linux-mips.org>2000-04-28 01:09:25 +0000
commitb9ba7aeb165cffecdffb60aec8c3fa8d590d9ca9 (patch)
tree42d07b0c7246ae2536a702e7c5de9e2732341116 /drivers/sound/trident.c
parent7406b0a326f2d70ade2671c37d1beef62249db97 (diff)
Merge with 2.3.99-pre6.
Diffstat (limited to 'drivers/sound/trident.c')
-rw-r--r--drivers/sound/trident.c368
1 files changed, 334 insertions, 34 deletions
diff --git a/drivers/sound/trident.c b/drivers/sound/trident.c
index 38afc31c9..575a65616 100644
--- a/drivers/sound/trident.c
+++ b/drivers/sound/trident.c
@@ -29,6 +29,13 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
* History
+ * 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
+ * v0.14.1 Mar 24 2000 Ching Ling Lee
+ * ALi 5451 support added, playback and recording O.K.
+ * ALi 5451 originally developed and structured based on sonicvibes, and
+ * suggested to merge into this file by Alan Cox.
* v0.14 Mar 15 2000 Ollie Lho
* 5.1 channel output support with channel binding. What's the Matrix ?
* v0.13.1 Mar 10 2000 Ollie Lho
@@ -74,6 +81,7 @@
* new pci device driver interface for 2.4 kernel (done)
*/
+#include <linux/config.h>
#include <linux/module.h>
#include <linux/version.h>
#include <linux/string.h>
@@ -127,13 +135,15 @@ static const char invalid_magic[] = KERN_CRIT "trident: invalid magic value in %
enum {
TRIDENT_4D_DX = 0,
TRIDENT_4D_NX,
- SIS_7018
+ SIS_7018,
+ ALI_5451
};
static char * card_names[] = {
"Trident 4DWave DX",
"Trident 4DWave NX",
- "SiS 7018 PCI Audio"
+ "SiS 7018 PCI Audio",
+ "ALi Audio Accelerator"
};
static struct pci_device_id trident_pci_tbl [] __initdata = {
@@ -143,6 +153,9 @@ static struct pci_device_id trident_pci_tbl [] __initdata = {
PCI_ANY_ID, PCI_ANY_ID, 0, 0, TRIDENT_4D_NX},
{PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_7018,
PCI_ANY_ID, PCI_ANY_ID, 0, 0, SIS_7018},
+ {PCI_VENDOR_ID_ALI, PCI_DEVICE_ID_ALI_5451,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0, ALI_5451},
+ {0,}
};
MODULE_DEVICE_TABLE (pci, trident_pci_tbl);
@@ -170,7 +183,7 @@ struct trident_state {
/* hardware channel */
struct trident_channel *channel;
- /* OSS buffer manangemeent stuff */
+ /* OSS buffer management stuff */
void *rawbuf;
dma_addr_t dma_handle;
unsigned buforder;
@@ -194,6 +207,8 @@ struct trident_state {
/* OSS stuff */
unsigned mapped:1;
unsigned ready:1;
+ unsigned endcleared:1;
+ unsigned update_flag;
unsigned ossfragshift;
int ossmaxfrags;
unsigned subdivision;
@@ -252,6 +267,7 @@ struct trident_card {
/* PCI device stuff */
struct pci_dev * pci_dev;
u16 pci_id;
+ u8 revision;
/* soundcore stuff */
int dev_audio;
@@ -264,6 +280,12 @@ struct trident_card {
/* hardware resources */
unsigned long iobase;
u32 irq;
+
+ /* Function support */
+ struct trident_channel *(*alloc_pcm_channel)(struct trident_card *);
+ struct trident_channel *(*alloc_rec_pcm_channel)(struct trident_card *);
+ void (*free_pcm_channel)(struct trident_card *, int chan);
+ void (*address_interrupt)(struct trident_card *);
};
/* table to map from CHANNELMASK to channel attribute for SiS 7018 */
@@ -281,6 +303,9 @@ static int attr2mask [] = {
static struct trident_card *devs = NULL;
+static void ali_ac97_set(struct ac97_codec *codec, u8 reg, u16 val);
+static u16 ali_ac97_get(struct ac97_codec *codec, u8 reg);
+
static void trident_ac97_set(struct ac97_codec *codec, u8 reg, u16 val);
static u16 trident_ac97_get(struct ac97_codec *codec, u8 reg);
@@ -301,6 +326,7 @@ static int trident_enable_loop_interrupts(struct trident_card * card)
case PCI_DEVICE_ID_SI_7018:
global_control |= (ENDLP_IE | MIDLP_IE| BANK_B_EN);
break;
+ case PCI_DEVICE_ID_ALI_5451:
case PCI_DEVICE_ID_TRIDENT_4DWAVE_DX:
case PCI_DEVICE_ID_TRIDENT_4DWAVE_NX:
global_control |= (ENDLP_IE | MIDLP_IE);
@@ -463,6 +489,46 @@ static struct trident_channel * trident_alloc_pcm_channel(struct trident_card *c
return NULL;
}
+static struct trident_channel *ali_alloc_pcm_channel(struct trident_card *card)
+{
+ struct trident_pcm_bank *bank;
+ int idx;
+
+ bank = &card->banks[BANK_A];
+
+ if (bank->bitmap == ~0UL) {
+ /* no more free channels avaliable */
+ printk(KERN_ERR "trident: no more channels available on Bank B.\n");
+ return NULL;
+ }
+ for (idx = 0; idx <= 31; idx++) {
+ if (!(bank->bitmap & (1 << idx))) {
+ struct trident_channel *channel = &bank->channels[idx];
+ bank->bitmap |= 1 << idx;
+ channel->num = idx;
+ return channel;
+ }
+ }
+ return NULL;
+}
+
+static struct trident_channel *ali_alloc_rec_pcm_channel(struct trident_card *card)
+{
+ struct trident_pcm_bank *bank;
+ int idx = ALI_PCM_IN_CHANNEL;
+
+ bank = &card->banks[BANK_A];
+
+ if (!(bank->bitmap & (1 << idx))) {
+ struct trident_channel *channel = &bank->channels[idx];
+ bank->bitmap |= 1 << idx;
+ channel->num = idx;
+ return channel;
+ }
+ return NULL;
+}
+
+
static void trident_free_pcm_channel(struct trident_card *card, int channel)
{
int bank;
@@ -478,7 +544,24 @@ static void trident_free_pcm_channel(struct trident_card *card, int channel)
}
}
+static void ali_free_pcm_channel(struct trident_card *card, int channel)
+{
+ int bank;
+
+ if (channel > 31)
+ return;
+
+ bank = channel >> 5;
+ channel = channel & 0x1f;
+
+ if (card->banks[bank].bitmap & (1 << (channel))) {
+ card->banks[bank].bitmap &= ~(1 << (channel));
+ }
+}
+
+
/* called with spin lock held */
+
static int trident_load_channel_registers(struct trident_card *card, u32 *data, unsigned int channel)
{
int i;
@@ -491,6 +574,9 @@ static int trident_load_channel_registers(struct trident_card *card, u32 *data,
/* output the channel registers */
for (i = 0; i < CHANNEL_REGS; i++) {
outl(data[i], TRID_REG(card, CHANNEL_START + 4*i));
+ if (i == 2)
+ if (card->pci_id == PCI_DEVICE_ID_ALI_5451)
+ i++; //skip i=3
}
return TRUE;
@@ -509,6 +595,11 @@ static int trident_write_voice_regs(struct trident_state *state)
switch (state->card->pci_id)
{
+ case PCI_DEVICE_ID_ALI_5451:
+ data[0] = 0; /* Current Sample Offset */
+ data[2] = (channel->eso << 16) | (channel->delta & 0xffff);
+ data[3] = 0;
+ break;
case PCI_DEVICE_ID_SI_7018:
data[0] = 0; /* Current Sample Offset */
data[2] = (channel->eso << 16) | (channel->delta & 0xffff);
@@ -654,6 +745,7 @@ static void trident_rec_setup(struct trident_state *state)
/* Enable AC-97 ADC (capture) */
switch (card->pci_id)
{
+ case PCI_DEVICE_ID_ALI_5451:
case PCI_DEVICE_ID_SI_7018:
/* for 7018, the ac97 is always in playback/record (duplex) mode */
break;
@@ -717,6 +809,7 @@ extern __inline__ unsigned trident_get_dma_addr(struct trident_state *state)
switch (state->card->pci_id)
{
+ case PCI_DEVICE_ID_ALI_5451:
case PCI_DEVICE_ID_SI_7018:
case PCI_DEVICE_ID_TRIDENT_4DWAVE_DX:
/* 16 bits ESO, CSO for 7018 and DX */
@@ -1029,8 +1122,11 @@ static int drain_dac(struct trident_state *state, int nonblock)
static void trident_update_ptr(struct trident_state *state)
{
struct dmabuf *dmabuf = &state->dmabuf;
- unsigned hwptr;
+ unsigned hwptr, swptr;
+ int clear_cnt = 0;
int diff;
+ unsigned char silence;
+ unsigned half_dmasize;
/* update hardware pointer */
hwptr = trident_get_dma_addr(state);
@@ -1054,6 +1150,31 @@ static void trident_update_ptr(struct trident_state *state)
__stop_adc(state);
dmabuf->error++;
}
+ else if (!dmabuf->endcleared) {
+ swptr = dmabuf->swptr;
+ silence = (dmabuf->fmt & TRIDENT_FMT_16BIT ? 0 : 0x80);
+ if (dmabuf->update_flag & ALI_ADDRESS_INT_UPDATE) {
+ /* We must clear end data of 1/2 dmabuf if needed.
+ According to 1/2 algorithm of Address Engine Interrupt,
+ check the validation of the data of half dmasize. */
+ half_dmasize = dmabuf->dmasize / 2;
+ if ((diff = hwptr - half_dmasize) < 0 )
+ diff = hwptr;
+ if ((dmabuf->count + diff) < half_dmasize) {
+ //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
+ dmabuf->endcleared = 1;
+ }
+ } else if (dmabuf->count < (signed) dmabuf->fragsize) {
+ clear_cnt = dmabuf->fragsize;
+ if ((swptr + clear_cnt) > dmabuf->dmasize)
+ clear_cnt = dmabuf->dmasize - swptr;
+ 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);
@@ -1080,13 +1201,54 @@ static void trident_update_ptr(struct trident_state *state)
wake_up(&dmabuf->wait);
}
}
+ dmabuf->update_flag &= ~ALI_ADDRESS_INT_UPDATE;
}
-static void trident_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+static void trident_address_interrupt(struct trident_card *card)
{
+ int i;
struct trident_state *state;
- struct trident_card *card = (struct trident_card *)dev_id;
+
+ /* Update the pointers for all channels we are running. */
+ /* FIXME: should read interrupt status only once */
+ for (i = 0; i < NR_HW_CH; i++) {
+ if (trident_check_channel_interrupt(card, 63 - i)) {
+ trident_ack_channel_interrupt(card, 63 - i);
+ if ((state = card->states[i]) != NULL) {
+ trident_update_ptr(state);
+ } else {
+ printk("trident: spurious channel irq %d.\n",
+ 63 - i);
+ trident_stop_voice(card, 63 - i);
+ trident_disable_voice_irq(card, 63 - i);
+ }
+ }
+ }
+}
+
+static void ali_address_interrupt(struct trident_card *card)
+{
int i;
+ struct trident_state *state;
+
+ for (i = 0; i < NR_HW_CH; i++) {
+ if (trident_check_channel_interrupt(card, i)) {
+ trident_ack_channel_interrupt(card, i);
+ if ((state = card->states[i]) != NULL) {
+ state->dmabuf.update_flag |= ALI_ADDRESS_INT_UPDATE;
+ trident_update_ptr(state);
+ } else {
+ printk("ali: spurious channel irq %d.\n", i);
+ trident_stop_voice(card, i);
+ trident_disable_voice_irq(card, i);
+ }
+ }
+ }
+}
+
+static void trident_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+{
+ struct trident_card *card = (struct trident_card *)dev_id;
u32 event;
spin_lock(&card->lock);
@@ -1097,21 +1259,7 @@ static void trident_interrupt(int irq, void *dev_id, struct pt_regs *regs)
#endif
if (event & ADDRESS_IRQ) {
- /* Update the pointers for all channels we are running. */
- /* FIXME: should read interrupt status only once */
- for (i = 0; i < NR_HW_CH; i++) {
- if (trident_check_channel_interrupt(card, 63 - i)) {
- trident_ack_channel_interrupt(card, 63 - i);
- if ((state = card->states[i]) != NULL) {
- trident_update_ptr(state);
- } else {
- printk("trident: spurious channel irq %d.\n",
- 63 - i);
- trident_stop_voice(card, 63 - i);
- trident_disable_voice_irq(card, 63 - i);
- }
- }
- }
+ card->address_interrupt(card);
}
/* manually clear interrupt status, bad hardware design, blame T^2 */
@@ -1151,6 +1299,9 @@ static ssize_t trident_read(struct file *file, char *buffer, size_t count, loff_
return -EFAULT;
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));
+
while (count > 0) {
spin_lock_irqsave(&state->card->lock, flags);
if (dmabuf->count > (signed) dmabuf->dmasize) {
@@ -1250,6 +1401,10 @@ static ssize_t trident_write(struct file *file, const char *buffer, size_t count
return -EFAULT;
ret = 0;
+ 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));
+
while (count > 0) {
spin_lock_irqsave(&state->card->lock, flags);
if (dmabuf->count < 0) {
@@ -1312,6 +1467,7 @@ static ssize_t trident_write(struct file *file, const char *buffer, size_t count
spin_lock_irqsave(&state->card->lock, flags);
dmabuf->swptr = swptr;
dmabuf->count += cnt;
+ dmabuf->endcleared = 0;
spin_unlock_irqrestore(&state->card->lock, flags);
count -= cnt;
@@ -1322,6 +1478,7 @@ static ssize_t trident_write(struct file *file, const char *buffer, size_t count
return ret;
}
+/* No kernel lock - we have our own spinlock */
static unsigned int trident_poll(struct file *file, struct poll_table_struct *wait)
{
struct trident_state *state = (struct trident_state *)file->private_data;
@@ -1733,7 +1890,12 @@ static int trident_open(struct inode *inode, struct file *file)
found_virt:
/* found a free virtual channel, allocate hardware channels */
- if ((dmabuf->channel = trident_alloc_pcm_channel(card)) == NULL) {
+ if(file->f_mode & FMODE_READ)
+ dmabuf->channel = card->alloc_rec_pcm_channel(card);
+ else
+ dmabuf->channel = card->alloc_pcm_channel(card);
+
+ if (dmabuf->channel == NULL) {
kfree (card->states[i]);
card->states[i] = NULL;;
return -ENODEV;
@@ -1767,7 +1929,12 @@ static int trident_open(struct inode *inode, struct file *file)
}
if (file->f_mode & FMODE_READ) {
- /* FIXME: Trident 4d can only record in singed 16-bits stereo, 48kHz sample,
+ if (card->pci_id == PCI_DEVICE_ID_ALI_5451) {
+ card->states[ALI_PCM_IN_CHANNEL] = state;
+ card->states[i] = NULL;
+ state->virt = ALI_PCM_IN_CHANNEL;
+ }
+ /* FIXME: Trident 4d can only record in signed 16-bits stereo, 48kHz sample,
to be dealed with in trident_set_adc_rate() ?? */
dmabuf->fmt &= ~TRIDENT_FMT_MASK;
if ((minor & 0x0f) == SND_DEV_DSP16)
@@ -1809,12 +1976,12 @@ static int trident_release(struct inode *inode, struct file *file)
if (file->f_mode & FMODE_WRITE) {
stop_dac(state);
dealloc_dmabuf(state);
- trident_free_pcm_channel(state->card, dmabuf->channel->num);
+ state->card->free_pcm_channel(state->card, dmabuf->channel->num);
}
if (file->f_mode & FMODE_READ) {
stop_adc(state);
dealloc_dmabuf(state);
- trident_free_pcm_channel(state->card, dmabuf->channel->num);
+ state->card->free_pcm_channel(state->card, dmabuf->channel->num);
}
kfree(state->card->states[state->virt]);
@@ -1944,6 +2111,101 @@ static u16 trident_ac97_get(struct ac97_codec *codec, u8 reg)
return ((u16) (data >> 16));
}
+/* Write AC97 codec registers for ALi*/
+static void ali_ac97_set(struct ac97_codec *codec, u8 reg, u16 val)
+{
+ struct trident_card *card = (struct trident_card *)codec->private_data;
+ unsigned int address, mask;
+ unsigned int wCount1 = 0xffff;
+ unsigned int wCount2= 0xffff;
+ unsigned long chk1, chk2;
+ unsigned long flags;
+ u32 data;
+
+ data = ((u32) val) << 16;
+
+ address = ALI_AC97_WRITE;
+ mask = ALI_AC97_WRITE_ACTION | ALI_AC97_AUDIO_BUSY;
+ if (codec->id)
+ mask |= ALI_AC97_SECONDARY;
+ if (card->revision == 0x02)
+ mask |= ALI_AC97_WRITE_MIXER_REGISTER;
+
+ spin_lock_irqsave(&card->lock, flags);
+ while (wCount1--) {
+ if ((inw(TRID_REG(card, address)) & ALI_AC97_BUSY_WRITE) == 0) {
+ data |= (mask | (reg & AC97_REG_ADDR));
+
+ chk1 = inl(TRID_REG(card, ALI_STIMER));
+ chk2 = inl(TRID_REG(card, ALI_STIMER));
+ while (wCount2-- && (chk1 == chk2))
+ chk2 = inl(TRID_REG(card, ALI_STIMER));
+ if (wCount2 == 0) {
+ spin_unlock_irqrestore(&card->lock, flags);
+ return;
+ }
+ outl(data, TRID_REG(card, address)); //write!
+ spin_unlock_irqrestore(&card->lock, flags);
+ return; //success
+ }
+ inw(TRID_REG(card, address)); //wait a read cycle
+ }
+
+ printk(KERN_ERR "ali: AC97 CODEC write timed out.\n");
+ spin_unlock_irqrestore(&card->lock, flags);
+ return;
+}
+
+/* Read AC97 codec registers for ALi*/
+static u16 ali_ac97_get(struct ac97_codec *codec, u8 reg)
+{
+ struct trident_card *card = (struct trident_card *)codec->private_data;
+ unsigned int address, mask;
+ unsigned int wCount1 = 0xffff;
+ unsigned int wCount2= 0xffff;
+ unsigned long chk1, chk2;
+ unsigned long flags;
+ u32 data;
+
+ address = ALI_AC97_READ;
+ if (card->revision == 0x02) {
+ address = ALI_AC97_WRITE;
+ mask &= ALI_AC97_READ_MIXER_REGISTER;
+ }
+ mask = ALI_AC97_READ_ACTION | ALI_AC97_AUDIO_BUSY;
+ if (codec->id)
+ mask |= ALI_AC97_SECONDARY;
+
+ spin_lock_irqsave(&card->lock, flags);
+ data = (mask | (reg & AC97_REG_ADDR));
+ while (wCount1--) {
+ if ((inw(TRID_REG(card, address)) & ALI_AC97_BUSY_READ) == 0) {
+ chk1 = inl(TRID_REG(card, ALI_STIMER));
+ chk2 = inl(TRID_REG(card, ALI_STIMER));
+ while (wCount2-- && (chk1 == chk2))
+ chk2 = inl(TRID_REG(card, ALI_STIMER));
+ if (wCount2 == 0) {
+ printk(KERN_ERR "ali: AC97 CODEC read timed out.\n");
+ spin_unlock_irqrestore(&card->lock, flags);
+ return 0;
+ }
+ outl(data, TRID_REG(card, address)); //read!
+ wCount2 = 0xffff;
+ while (wCount2--) {
+ if ((inw(TRID_REG(card, address)) & ALI_AC97_BUSY_READ) == 0) {
+ data = inl(TRID_REG(card, address));
+ spin_unlock_irqrestore(&card->lock, flags);
+ return ((u16) (data >> 16));
+ }
+ }
+ }
+ inw(TRID_REG(card, address)); //wait a read cycle
+ }
+ spin_unlock_irqrestore(&card->lock, flags);
+ printk(KERN_ERR "ali: AC97 CODEC read timed out.\n");
+ return 0;
+}
+
/* OSS /dev/mixer file operation methods */
static int trident_open_mixdev(struct inode *inode, struct file *file)
{
@@ -1999,6 +2261,11 @@ static int __init trident_ac97_init(struct trident_card *card)
really exist */
switch (card->pci_id)
{
+ case PCI_DEVICE_ID_ALI_5451:
+ outl(PCMOUT|SECONDARY_ID, TRID_REG(card, SI_SERIAL_INTF_CTRL));
+ ready_2nd = inl(TRID_REG(card, SI_SERIAL_INTF_CTRL));
+ ready_2nd &= SI_AC97_SECONDARY_READY;
+ break;
case PCI_DEVICE_ID_SI_7018:
/* disable AC97 GPIO interrupt */
outl(0x00, TRID_REG(card, SI_AC97_GPIO));
@@ -2032,10 +2299,16 @@ static int __init trident_ac97_init(struct trident_card *card)
in ac97_probe_codec */
codec->private_data = card;
codec->id = num_ac97;
- /* controller specific low level AC97 access function */
- codec->codec_read = trident_ac97_get;
- codec->codec_write = trident_ac97_set;
+ if (card->pci_id == PCI_DEVICE_ID_ALI_5451) {
+ codec->codec_read = ali_ac97_get;
+ codec->codec_write = ali_ac97_set;
+ }
+ else {
+ codec->codec_read = trident_ac97_get;
+ codec->codec_write = trident_ac97_set;
+ }
+
if (ac97_probe_codec(codec) == 0)
break;
@@ -2061,12 +2334,14 @@ static int __init trident_probe(struct pci_dev *pci_dev, const struct pci_device
{
unsigned long iobase;
struct trident_card *card;
+ u8 revision;
if (!pci_dma_supported(pci_dev, TRIDENT_DMA_MASK)) {
printk(KERN_ERR "trident: architecture does not support"
" 30bit PCI busmaster DMA\n");
return -ENODEV;
}
+ pci_read_config_byte(pci_dev, PCI_CLASS_REVISION, &revision);
iobase = pci_dev->resource[0].start;
if (check_region(iobase, 256)) {
@@ -2084,6 +2359,7 @@ static int __init trident_probe(struct pci_dev *pci_dev, const struct pci_device
card->iobase = iobase;
card->pci_dev = pci_dev;
card->pci_id = pci_id->device;
+ card->revision = revision;
card->irq = pci_dev->irq;
card->next = devs;
card->magic = TRIDENT_CARD_MAGIC;
@@ -2100,6 +2376,20 @@ static int __init trident_probe(struct pci_dev *pci_dev, const struct pci_device
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)
+ {
+ 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
+ {
+ 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,
@@ -2111,7 +2401,7 @@ static int __init trident_probe(struct pci_dev *pci_dev, const struct pci_device
}
/* register /dev/dsp */
if ((card->dev_audio = register_sound_dsp(&trident_audio_fops, -1)) < 0) {
- printk(KERN_ERR "trident: coundn't register DSP device!\n");
+ printk(KERN_ERR "trident: couldn't register DSP device!\n");
release_region(iobase, 256);
free_irq(card->irq, card);
kfree(card);
@@ -2127,6 +2417,16 @@ static int __init trident_probe(struct pci_dev *pci_dev, const struct pci_device
}
outl(0x00, TRID_REG(card, T4D_MUSICVOL_WAVEVOL));
+ 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);
+#endif
+ /* edited by HMSEO for GT sound*/
+ }
+
pci_dev->driver_data = card;
pci_dev->dma_mask = TRIDENT_DMA_MASK;
@@ -2145,12 +2445,12 @@ static void __exit trident_remove(struct pci_dev *pci_dev)
trident_disable_loop_interrupts(card);
/* free hardware resources */
- free_irq(card->irq, devs);
+ free_irq(card->irq, card);
release_region(card->iobase, 256);
/* unregister audio devices */
for (i = 0; i < NR_AC97; i++)
- if (devs->ac97_codec[i] != NULL) {
+ if (card->ac97_codec[i] != NULL) {
unregister_sound_mixer(card->ac97_codec[i]->dev_mixer);
kfree (card->ac97_codec[i]);
}
@@ -2159,8 +2459,8 @@ static void __exit trident_remove(struct pci_dev *pci_dev)
kfree(card);
}
-MODULE_AUTHOR("Alan Cox, Aaron Holtzman, Ollie Lho");
-MODULE_DESCRIPTION("Trident 4DWave/SiS 7018 PCI Audio Driver");
+MODULE_AUTHOR("Alan Cox, Aaron Holtzman, Ollie Lho, Ching Ling Lee");
+MODULE_DESCRIPTION("Trident 4DWave/SiS 7018/ALi 5451 PCI Audio Driver");
#define TRIDENT_MODULE_NAME "trident"
@@ -2176,7 +2476,7 @@ static int __init trident_init_module (void)
if (!pci_present()) /* No PCI bus in this machine! */
return -ENODEV;
- printk(KERN_INFO "Trident 4DWave/SiS 7018 PCI Audio, version "
+ printk(KERN_INFO "Trident 4DWave/SiS 7018/ALi 5451 PCI Audio, version "
DRIVER_VERSION ", " __TIME__ " " __DATE__ "\n");
if (!pci_register_driver(&trident_pci_driver)) {