summaryrefslogtreecommitdiffstats
path: root/drivers/sound/trident.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/sound/trident.c')
-rw-r--r--drivers/sound/trident.c414
1 files changed, 309 insertions, 105 deletions
diff --git a/drivers/sound/trident.c b/drivers/sound/trident.c
index 0a8192439..07d2c7e08 100644
--- a/drivers/sound/trident.c
+++ b/drivers/sound/trident.c
@@ -13,6 +13,7 @@
* 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
+ * Matt Wu <mattwu@acersoftech.com.cn> ALi 5451 Audio Core Support
*
*
* This program is free software; you can redistribute it and/or modify
@@ -30,6 +31,12 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
* History
+ * v0.14.7
+ * Feb 06 2001 Matt Wu
+ * Fix ac97 initialization
+ * Fix bug: an extra tail will be played when playing
+ * Jan 05 2001 Matt Wu
+ * Implement multi-channels and S/PDIF in support for ALi 1535+
* v0.14.6
* Nov 1 2000 Ching-Ling Lee
* Fix the bug of memory leak when swithing 5.1-channels to 2 channels.
@@ -140,12 +147,12 @@
/* maxinum nuber of AC97 codecs connected, AC97 2.0 defined 4, but 7018 and 4D-NX only
have 2 SDATA_IN lines (currently) */
-#define NR_AC97 2
+#define NR_AC97 2
/* minor number of /dev/swmodem (temporary, experimental) */
#define SND_DEV_SWMODEM 7
-static const unsigned ali_multi_channels_5_1[] = { ALI_CENTER_CHANNEL, ALI_LEF_CHANNEL, ALI_SURR_LEFT_CHANNEL, ALI_SURR_RIGHT_CHANNEL};
+static const unsigned ali_multi_channels_5_1[] = { /*ALI_SURR_LEFT_CHANNEL, ALI_SURR_RIGHT_CHANNEL,*/ ALI_CENTER_CHANNEL, ALI_LEF_CHANNEL, ALI_SURR_LEFT_CHANNEL, ALI_SURR_RIGHT_CHANNEL};
static const unsigned sample_size[] = { 1, 2, 2, 4 };
static const unsigned sample_shift[] = { 0, 1, 1, 2 };
@@ -312,6 +319,10 @@ struct trident_card {
struct trident_channel *(*alloc_rec_pcm_channel)(struct trident_card *);
void (*free_pcm_channel)(struct trident_card *, unsigned int chan);
void (*address_interrupt)(struct trident_card *);
+
+ /* Add by Matt Wu 01-05-2001 for spdif in */
+ int multi_channel_use_count;
+ int rec_channel_use_count;
};
/* table to map from CHANNELMASK to channel attribute for SiS 7018 */
@@ -327,6 +338,11 @@ static int attr2mask [] = {
DSP_BIND_I2S, DSP_BIND_CENTER_LFE, DSP_BIND_SURR, DSP_BIND_SPDIF
};
+/* Add by Matt Wu 01-05-2001 for spdif in */
+static int ali_close_multi_channels(void);
+static void ali_delay(struct trident_card *card,int interval);
+static void ali_detect_spdif_rate(struct trident_card *card);
+
static struct trident_card *devs;
static void trident_ac97_set(struct ac97_codec *codec, u8 reg, u16 val);
@@ -760,6 +776,8 @@ static void trident_play_setup(struct trident_state *state)
static void trident_rec_setup(struct trident_state *state)
{
u16 w;
+ u8 bval;
+
struct trident_card *card = state->card;
struct dmabuf *dmabuf = &state->dmabuf;
struct trident_channel *channel = dmabuf->channel;
@@ -794,6 +812,18 @@ static void trident_rec_setup(struct trident_state *state)
channel->delta = compute_rate_rec(dmabuf->rate);
if ((card->pci_id == PCI_DEVICE_ID_ALI_5451) && (channel->num == ALI_SPDIF_IN_CHANNEL)) {
rate = ali_get_spdif_in_rate(card);
+ if (rate == 0)
+ {
+ printk(KERN_WARNING "trident: ALi 5451 S/PDIF input setup error!\n");
+ rate = 48000;
+ }
+ bval = inb(TRID_REG(card,ALI_SPDIF_CTRL));
+ if (bval & 0x10)
+ {
+ outb(bval,TRID_REG(card,ALI_SPDIF_CTRL));
+ printk(KERN_WARNING "trident: cleared ALi 5451 S/PDIF parity error flag.\n");
+ }
+
if (rate != 48000)
channel->delta = ((rate << 12) / dmabuf->rate) & 0x0000ffff;
}
@@ -959,7 +989,7 @@ static void start_dac(struct trident_state *state)
static int alloc_dmabuf(struct trident_state *state)
{
struct dmabuf *dmabuf = &state->dmabuf;
- void *rawbuf;
+ void *rawbuf=NULL;
int order;
struct page *page, *pend;
@@ -1138,11 +1168,13 @@ static void trident_clear_tail(struct trident_state *state)
len = dmabuf->dmasize - swptr;
memset(dmabuf->rawbuf + swptr, silence, len);
-
- spin_lock_irqsave(&state->card->lock, flags);
- dmabuf->swptr += len;
- dmabuf->count += len;
- spin_unlock_irqrestore(&state->card->lock, flags);
+ if(state->card->pci_id != PCI_DEVICE_ID_ALI_5451)
+ {
+ spin_lock_irqsave(&state->card->lock, flags);
+ dmabuf->swptr += len;
+ dmabuf->count += len;
+ spin_unlock_irqrestore(&state->card->lock, flags);
+ }
/* restart the dma machine in case it is halted */
start_dac(state);
@@ -1155,6 +1187,7 @@ static int drain_dac(struct trident_state *state, int nonblock)
unsigned long flags;
unsigned long tmo;
int count;
+ unsigned long diff = 0;
if (dmabuf->mapped || !dmabuf->ready)
return 0;
@@ -1183,10 +1216,19 @@ static int drain_dac(struct trident_state *state, int nonblock)
/* No matter how much data left in the buffer, we have to wait untill
CSO == ESO/2 or CSO == ESO when address engine interrupts */
- tmo = (dmabuf->dmasize * HZ) / dmabuf->rate;
+ if (state->card->pci_id == PCI_DEVICE_ID_ALI_5451)
+ {
+ diff = dmabuf->swptr - trident_get_dma_addr(state) + dmabuf->dmasize ;
+ diff = diff % (dmabuf->dmasize);
+ tmo = (diff * HZ) / dmabuf->rate;
+ }
+ else
+ {
+ tmo = (dmabuf->dmasize * HZ) / dmabuf->rate;
+ }
tmo >>= sample_shift[dmabuf->fmt];
+// printk("trident: diff=%d count= %d/%d total=%d tmo=%d hwptr=%d swptr=%d curptr=%d\n",diff,dmabuf->count,dmabuf->dmasize,dmabuf->total_bytes,tmo,dmabuf->hwptr,dmabuf->swptr,trident_get_dma_addr(state));
if (!schedule_timeout(tmo ? tmo : 1) && tmo){
- printk(KERN_ERR "trident: drain_dac, dma timeout?\n");
break;
}
}
@@ -1412,7 +1454,7 @@ static ssize_t trident_read(struct file *file, char *buffer, size_t count, loff_
if (!ret) ret = -EAGAIN;
return ret;
}
- /* No matter how much space left in the buffer, we have to wait untill
+ /* No matter how much space left in the buffer, we have to wait until
CSO == ESO/2 or CSO == ESO when address engine interrupts */
tmo = (dmabuf->dmasize * HZ) / (dmabuf->rate * 2);
tmo >>= sample_shift[dmabuf->fmt];
@@ -1430,7 +1472,7 @@ static ssize_t trident_read(struct file *file, char *buffer, size_t count, loff_
dmabuf->dmasize, dmabuf->fragsize, dmabuf->count,
dmabuf->hwptr, dmabuf->swptr);
#endif
- /* a buffer overrun, we delay the recovery untill next time the
+ /* a buffer overrun, we delay the recovery until next time the
while loop begin and we REALLY have space to record */
}
if (signal_pending(current)) {
@@ -1512,7 +1554,7 @@ static ssize_t trident_write(struct file *file, const char *buffer, size_t count
if (!ret) ret = -EAGAIN;
return ret;
}
- /* No matter how much data left in the buffer, we have to wait untill
+ /* No matter how much data left in the buffer, we have to wait until
CSO == ESO/2 or CSO == ESO when address engine interrupts */
lock_set_fmt(state);
tmo = (dmabuf->dmasize * HZ) / (dmabuf->rate * 2);
@@ -1532,7 +1574,7 @@ static ssize_t trident_write(struct file *file, const char *buffer, size_t count
dmabuf->dmasize, dmabuf->fragsize, dmabuf->count,
dmabuf->hwptr, dmabuf->swptr);
#endif
- /* a buffer underrun, we delay the recovery untill next time the
+ /* a buffer underrun, we delay the recovery until next time the
while loop begin and we REALLY have data to play */
}
if (signal_pending(current)) {
@@ -1671,6 +1713,8 @@ static int trident_ioctl(struct inode *inode, struct file *file, unsigned int cm
count_info cinfo;
int val, mapped, ret;
+ struct trident_card *card = state->card;
+
VALIDATE_STATE(state);
mapped = ((file->f_mode & FMODE_WRITE) && dmabuf->mapped) ||
((file->f_mode & FMODE_READ) && dmabuf->mapped);
@@ -1807,17 +1851,32 @@ static int trident_ioctl(struct inode *inode, struct file *file, unsigned int cm
state->chans_num = 1;
}
- if (val >= 2) {
+ if (val >= 2)
+ {
+
dmabuf->fmt |= TRIDENT_FMT_STEREO;
if ((val == 6) && (state->card->pci_id == PCI_DEVICE_ID_ALI_5451)) {
- ali_setup_multi_channels(state->card, 6);
+
+ if( card->rec_channel_use_count > 0 )
+ {
+ printk("Err: Record is working on the card!\n");
+ return -EBUSY;
+ }
+
+ ret = ali_setup_multi_channels(state->card, 6);
+ if (ret < 0) {
+ unlock_set_fmt(state);
+ return ret;
+ }
down(&state->card->open_sem);
ret = ali_allocate_other_states_resources(state, 6);
- up(&state->card->open_sem);
if (ret < 0) {
+ up(&state->card->open_sem);
unlock_set_fmt(state);
return ret;
}
+ state->card->multi_channel_use_count ++;
+ up(&state->card->open_sem);
}
else val = 2; /*yield to 2-channels*/
}
@@ -2031,10 +2090,20 @@ static int trident_open(struct inode *inode, struct file *file)
struct trident_card *card = devs;
struct trident_state *state = NULL;
struct dmabuf *dmabuf = NULL;
-
+
/* find an avaiable virtual channel (instance of /dev/dsp) */
while (card != NULL) {
down(&card->open_sem);
+ if(file->f_mode & FMODE_READ)
+ {
+ /* Skip opens on cards that are in 6 channel mode */
+ if (card->multi_channel_use_count > 0)
+ {
+ up(&card->open_sem);
+ card = card->next;
+ continue;
+ }
+ }
for (i = 0; i < NR_HW_CH; i++) {
if (card->states[i] == NULL) {
state = card->states[i] = (struct trident_state *)
@@ -2107,6 +2176,7 @@ static int trident_open(struct inode *inode, struct file *file)
(CHANNEL_REC|PCM_LR|MONO_MIX);
}
trident_set_adc_rate(state, 8000);
+ card->rec_channel_use_count ++;
}
state->open_mode |= file->f_mode & (FMODE_READ | FMODE_WRITE);
@@ -2143,16 +2213,29 @@ static int trident_release(struct inode *inode, struct file *file)
if (file->f_mode & FMODE_WRITE) {
stop_dac(state);
lock_set_fmt(state);
- if (state->chans_num > 2)
- ali_free_other_states_resources(state);
+
unlock_set_fmt(state);
dealloc_dmabuf(state);
state->card->free_pcm_channel(state->card, dmabuf->channel->num);
+
+ if (state->chans_num > 2)
+ {
+ if( card->multi_channel_use_count-- < 0 )
+ card->multi_channel_use_count = 0;
+
+ if (card->multi_channel_use_count == 0)
+ ali_close_multi_channels();
+
+ ali_free_other_states_resources(state);
+ }
}
if (file->f_mode & FMODE_READ) {
stop_adc(state);
dealloc_dmabuf(state);
state->card->free_pcm_channel(state->card, dmabuf->channel->num);
+
+ if( card->rec_channel_use_count-- < 0 )
+ card->rec_channel_use_count = 0;
}
card->states[state->virt] = NULL;
@@ -2295,6 +2378,9 @@ static void ali_ac97_set(struct ac97_codec *codec, u8 reg, u16 val)
data = ((u32) val) << 16;
+ if(!card)
+ BUG();
+
address = ALI_AC97_WRITE;
mask = ALI_AC97_WRITE_ACTION | ALI_AC97_AUDIO_BUSY;
if (codec->id)
@@ -2391,11 +2477,29 @@ static void ali_enable_special_channel(struct trident_state *stat)
flag: ALI_SPDIF_OUT_TO_SPDIF_OUT
ALI_PCM_TO_SPDIF_OUT
*/
+
static void ali_setup_spdif_out(struct trident_card *card, int flag)
{
unsigned long spdif;
unsigned char ch;
+ char temp;
+ struct pci_dev *pci_dev = NULL;
+
+ pci_dev = pci_find_device(PCI_VENDOR_ID_AL,PCI_DEVICE_ID_AL_M1533, pci_dev);
+ if (pci_dev == NULL)
+ return;
+ pci_read_config_byte(pci_dev, 0x61, &temp);
+ temp |= 0x40;
+ pci_write_config_byte(pci_dev, 0x61, temp);
+ pci_read_config_byte(pci_dev, 0x7d, &temp);
+ temp |= 0x01;
+ pci_write_config_byte(pci_dev, 0x7d, temp);
+ pci_read_config_byte(pci_dev, 0x7e, &temp);
+ temp &= (~0x20);
+ temp |= 0x10;
+ pci_write_config_byte(pci_dev, 0x7e, temp);
+
ch = inb(TRID_REG(card, ALI_SCTRL));
outb(ch | ALI_SPDIF_OUT_ENABLE, TRID_REG(card, ALI_SCTRL));
ch = inb(TRID_REG(card, ALI_SPDIF_CTRL));
@@ -2448,112 +2552,207 @@ static void ali_setup_spdif_in(struct trident_card *card)
spdif |= ALI_SPDIF_IN_SUPPORT;
outl(spdif, TRID_REG(card, ALI_GLOBAL_CONTROL));
- spdif = inb(TRID_REG(card, ALI_SPDIF_CTRL));
- spdif |= ALI_SPDIF_IN_CH_STATUS;
- outb(spdif, TRID_REG(card, ALI_SPDIF_CTRL));
-
//Set SPDIF IN Rec
spdif = inl(TRID_REG(card, ALI_GLOBAL_CONTROL));
spdif |= ALI_SPDIF_IN_CH_ENABLE;
outl(spdif, TRID_REG(card, ALI_GLOBAL_CONTROL));
spdif = inb(TRID_REG(card, ALI_SPDIF_CTRL));
+ spdif |= ALI_SPDIF_IN_CH_STATUS;
+ outb(spdif, TRID_REG(card, ALI_SPDIF_CTRL));
+/*
+ spdif = inb(TRID_REG(card, ALI_SPDIF_CTRL));
spdif |= ALI_SPDIF_IN_FUNC_ENABLE;
outb(spdif, TRID_REG(card, ALI_SPDIF_CTRL));
+*/
}
-static unsigned int ali_get_spdif_in_rate(struct trident_card *card)
+static void ali_delay(struct trident_card *card,int interval)
{
- unsigned long spdif, time1, time2;
- unsigned count1, count2, count3;
- unsigned char R1, R2 = 0;
-
- outb(0xAA, TRID_REG(card, ALI_SPDIF_CTRL + 1));
- count1 = 0xFFFF;
- while(--count1)
+ unsigned long begintimer,currenttimer;
+
+ begintimer = inl(TRID_REG(card, ALI_STIMER));
+ currenttimer = inl(TRID_REG(card, ALI_STIMER));
+
+ while (currenttimer < begintimer + interval)
+ currenttimer = inl(TRID_REG(card, ALI_STIMER));
+}
+
+static void ali_detect_spdif_rate(struct trident_card *card)
+{
+ u16 wval = 0;
+ u16 count = 0;
+ u8 bval = 0, R1 = 0, R2 = 0;
+
+ bval = inb(TRID_REG(card,ALI_SPDIF_CTRL));
+ bval |= 0x02;
+ outb(bval,TRID_REG(card,ALI_SPDIF_CTRL));
+
+ bval = inb(TRID_REG(card,ALI_SPDIF_CTRL + 1));
+ bval |= 0x1F;
+ outb(bval,TRID_REG(card,ALI_SPDIF_CTRL + 1));
+
+ while (((R1 < 0x0B )||(R1 > 0x0E)) && (R1 != 0x12) && count <= 50000)
{
- count2 = 0xffff;
- do{
- count3 = 0xffff;
- time1 = inl(TRID_REG(card, ALI_STIMER));
-
- do{
- time2 = inl(TRID_REG(card, ALI_STIMER));
- }while((count3--) && (time2 <= (time1 + 5)));
- if (!count3) {
- printk("ali: STimer is stopped! Error!\n");
- return FALSE;
- }
- R1 = inb(TRID_REG(card, ALI_SPDIF_CTRL + 1));
- }while((count2--) && (!((R1 == 0x0B)||(R1 == 0x0C)||(R1 == 0x0D)||(R1 == 0x0E)||(R1 == 0x12))));
- if (!count2)
- continue;
+ count ++;
- count2 = 0xffff;
- time1 = inl(TRID_REG(card, ALI_STIMER));
- do{
- time2 = inl(TRID_REG(card, ALI_STIMER));
- }while((count2--) && (time2 <= (time1 + 5)));
- if (!count2)
- continue;
+ ali_delay(card, 6);
- R2 = inb(TRID_REG(card, ALI_SPDIF_CTRL + 1));
- count2 = 0xffff;
- while((--count2) && (R2 != R1))
- {
+ bval = inb(TRID_REG(card,ALI_SPDIF_CTRL + 1));
+ R1 = bval & 0x1F;
+ }
+
+ if (count > 50000)
+ {
+ printk(KERN_WARNING "trident: Error in ali_detect_spdif_rate!\n");
+ return;
+ }
+
+ count = 0;
+
+ while (count <= 50000)
+ {
+ count ++;
+
+ ali_delay(card, 6);
+
+ bval = inb(TRID_REG(card,ALI_SPDIF_CTRL + 1));
+ R2 = bval & 0x1F;
+
+ if(R2 != R1)
R1 = R2;
- count3 = 0xffff;
- time1 = inl(TRID_REG(card, ALI_STIMER));
- do{
- time2 = inl(TRID_REG(card, ALI_STIMER));
- }while((count3--) && (time2 <= (time1 + 5)));
- if (!count3) {
- printk("ali: STimer is stopped! Error!\n");
- return FALSE;
- }
- R2 = inb(TRID_REG(card, ALI_SPDIF_CTRL + 1));
- }
- if(R2 == R1)
+ else
break;
}
- if(!count1) {
- printk("ali: Can not Detect the sample rate from SPDIF IN!\n");
- return FALSE;
+ if (count > 50000)
+ {
+ printk(KERN_WARNING "trident: Error in ali_detect_spdif_rate!\n");
+ return;
}
- spdif = inb(TRID_REG(card, ALI_SPDIF_CTRL)) | ALI_SPDIF_IN_CH_STATUS;
- outb(spdif, TRID_REG(card, ALI_SPDIF_CTRL));
+ switch (R2)
+ {
+ case 0x0b:
+ case 0x0c:
+ case 0x0d:
+ case 0x0e:
+ wval = inw(TRID_REG(card,ALI_SPDIF_CTRL + 2));
+ wval &= 0xE0F0;
+ wval |= (u16)0x09 << 8 | (u16)0x05;
+ outw(wval,TRID_REG(card,ALI_SPDIF_CTRL + 2));
+
+ bval = inb(TRID_REG(card,ALI_SPDIF_CS +3)) & 0xF0;
+ outb(bval|0x02,TRID_REG(card,ALI_SPDIF_CS + 3));
+ break;
- /* SPDIF only supprts 48k, 44.1k, 32k */
- switch(R2) {
case 0x12:
- outw(0x0E08, TRID_REG(card, ALI_SPDIF_CTRL + 2));
- return 32000;
- case 0x0B:
- case 0x0C:
- case 0x0D:
- case 0x0E:
+ wval = inw(TRID_REG(card,ALI_SPDIF_CTRL + 2));
+ wval &= 0xE0F0;
+ wval |= (u16)0x0E << 8 | (u16)0x08;
+ outw(wval,TRID_REG(card,ALI_SPDIF_CTRL + 2));
+
+ bval = inb(TRID_REG(card,ALI_SPDIF_CS +3)) & 0xF0;
+ outb(bval|0x03,TRID_REG(card,ALI_SPDIF_CS + 3));
+ break;
+
default:
- outw(0x0905, TRID_REG(card, ALI_SPDIF_CTRL + 2));
break;
}
+
+}
+
+static unsigned int ali_get_spdif_in_rate(struct trident_card *card)
+{
+ u32 dwRate = 0;
+ u8 bval = 0;
+
+ ali_detect_spdif_rate(card);
+
+ bval = inb(TRID_REG(card,ALI_SPDIF_CTRL));
+ bval &= 0x7F;
+ bval |= 0x40;
+ outb(bval,TRID_REG(card,ALI_SPDIF_CTRL));
+
+ bval = inb(TRID_REG(card,ALI_SPDIF_CS + 3));
+ bval &= 0x0F;
+
+ switch (bval)
+ {
+ case 0:
+ dwRate = 44100;
+ break;
+ case 1:
+ dwRate = 48000;
+ break;
+ case 2:
+ dwRate = 32000;
+ break;
+ default:
+ // Error occurs
+ break;
+ }
+
+ return dwRate;
+
+}
+
+static int ali_close_multi_channels(void)
+{
+ char temp = 0;
+ struct pci_dev *pci_dev = NULL;
+
+ pci_dev = pci_find_device(PCI_VENDOR_ID_AL,PCI_DEVICE_ID_AL_M1533, pci_dev);
+ if (pci_dev == NULL)
+ return -1;
+ temp = 0x80;
+ pci_write_config_byte(pci_dev, 0x59, ~temp);
- spdif = inb(TRID_REG(card, ALI_SPDIF_CS + 3)) & 0xf;
- if (spdif == 0)
- return 44100;
- else return 48000;
+ pci_dev = pci_find_device(PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M7101, pci_dev);
+ if (pci_dev == NULL)
+ return -1;
+
+ temp = 0x20;
+ pci_write_config_byte(pci_dev, 0xB8, ~temp);
+
+ return 0;
}
static int ali_setup_multi_channels(struct trident_card *card, int chan_nums)
{
unsigned long dwValue;
+ char temp = 0;
+ struct pci_dev *pci_dev = NULL;
+
+ pci_dev = pci_find_device(PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M1533, pci_dev);
+ if (pci_dev == NULL)
+ return -1;
+ temp = 0x80;
+ pci_write_config_byte(pci_dev, 0x59, temp);
+ pci_dev = pci_find_device(PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M7101, pci_dev);
+ if (pci_dev == NULL)
+ return -1;
+ temp = 0x20;
+ pci_write_config_byte(pci_dev, (int)0xB8,(u8) temp);
if (chan_nums == 6) {
dwValue = inl(TRID_REG(card, ALI_SCTRL)) | 0x000f0000;
outl(dwValue, TRID_REG(card, ALI_SCTRL));
+ mdelay(4);
+ dwValue = inl(TRID_REG(card, ALI_SCTRL));
+ if (dwValue & 0x2000000) {
+ ali_ac97_set(card->ac97_codec[0], 0x02, 8080);
+ ali_ac97_set(card->ac97_codec[0], 0x36, 0);
+ ali_ac97_set(card->ac97_codec[0], 0x38, 0);
+ ali_ac97_set(card->ac97_codec[1], 0x36, 0);
+ ali_ac97_set(card->ac97_codec[1], 0x38, 0);
+ ali_ac97_set(card->ac97_codec[1], 0x02, 0);
+ ali_ac97_set(card->ac97_codec[1], 0x18, 0x0808);
+ ali_ac97_set(card->ac97_codec[1], 0x74, 0x3);
+ return 1;
+ }
}
- return 1;
+ return -EINVAL;
}
static void ali_free_pcm_channel(struct trident_card *card, unsigned int channel)
@@ -2746,7 +2945,7 @@ static struct trident_channel *ali_alloc_pcm_channel(struct trident_card *card)
}
/* no more free channels avaliable */
- printk(KERN_ERR "ali: no more channels available on Bank A.\n");
+// printk(KERN_ERR "ali: no more channels available on Bank A.\n");
return NULL;
}
@@ -2769,7 +2968,7 @@ static struct trident_channel *ali_alloc_rec_pcm_channel(struct trident_card *ca
}
/* no free recordable channels avaliable */
- printk(KERN_ERR "ali: no recordable channels available on Bank A.\n");
+// printk(KERN_ERR "ali: no recordable channels available on Bank A.\n");
return NULL;
}
@@ -2778,9 +2977,6 @@ static void ali_set_spdif_out_rate(struct trident_card *card, unsigned int rate)
unsigned char ch_st_sel;
unsigned short status_rate;
-#ifdef DEBUG
- printk("ali: spdif out rate =%d\n", rate);
-#endif
switch(rate) {
case 44100:
status_rate = 0;
@@ -2803,9 +2999,6 @@ static void ali_set_spdif_out_rate(struct trident_card *card, unsigned int rate)
ch_st_sel &= (~0x80); //select left
outb(ch_st_sel, TRID_REG(card, ALI_SPDIF_CTRL));
outw(status_rate | 0x10, TRID_REG(card, ALI_SPDIF_CS + 2));
-#ifdef DEBUG
- printk("ali: SPDIF_CS=%lxh\n", inl(TRID_REG(card, ALI_SPDIF_CS)));
-#endif
}
static void ali_address_interrupt(struct trident_card *card)
@@ -2822,6 +3015,7 @@ static void ali_address_interrupt(struct trident_card *card)
if ((channel_mask = 1 << channel) & mask) {
mask &= ~channel_mask;
trident_ack_channel_interrupt(card, channel);
+ udelay(100);
state->dmabuf.update_flag |= ALI_ADDRESS_INT_UPDATE;
trident_update_ptr(state);
}
@@ -2986,7 +3180,7 @@ static int ali_write_proc(struct file *file, const char *buffer, unsigned long c
/* OSS /dev/mixer file operation methods */
static int trident_open_mixdev(struct inode *inode, struct file *file)
{
- int i;
+ int i = 0;
int minor = MINOR(inode->i_rdev);
struct trident_card *card = devs;
@@ -3033,10 +3227,17 @@ static int __init trident_ac97_init(struct trident_card *card)
switch (card->pci_id)
{
case PCI_DEVICE_ID_ALI_5451:
+ outl(0x80000000,TRID_REG(card, ALI_GLOBAL_CONTROL));
+ outl(0x00000000,TRID_REG(card, 0xa4));
+ outl(0xffffffff,TRID_REG(card, 0x98));
+ outl(0x00000000,TRID_REG(card, 0xa8));
+ outb(0x10, TRID_REG(card, 0x22));
ready_2nd = inl(TRID_REG(card, ALI_SCTRL));
- outl(ready_2nd | PCMOUT | SECONDARY_ID, TRID_REG(card, ALI_SCTRL));
+ ready_2nd &= 0x3fff;
+ outl(ready_2nd | PCMOUT | 0x8000, TRID_REG(card, ALI_SCTRL));
ready_2nd = inl(TRID_REG(card, ALI_SCTRL));
ready_2nd &= SI_AC97_SECONDARY_READY;
+// printk("codec 2 ready flag= %lx\n", ready_2nd);
break;
case PCI_DEVICE_ID_SI_7018:
/* disable AC97 GPIO interrupt */
@@ -3097,18 +3298,18 @@ static int __init trident_ac97_init(struct trident_card *card)
return num_ac97+1;
}
- return num_ac97;
+ return 1/*num_ac97*/;
}
/* install the driver, we do not allocate hardware channel nor DMA buffer now, they are defered
- untill "ACCESS" time (in prog_dmabuf called by open/read/write/ioctl/mmap) */
+ until "ACCESS" time (in prog_dmabuf called by open/read/write/ioctl/mmap) */
static int __init trident_probe(struct pci_dev *pci_dev, const struct pci_device_id *pci_id)
{
unsigned long iobase;
struct trident_card *card;
u8 revision;
- if (!pci_dma_supported(pci_dev, TRIDENT_DMA_MASK)) {
+ if (pci_set_dma_mask(pci_dev, TRIDENT_DMA_MASK)) {
printk(KERN_ERR "trident: architecture does not support"
" 30bit PCI busmaster DMA\n");
return -ENODEV;
@@ -3167,6 +3368,10 @@ static int __init trident_probe(struct pci_dev *pci_dev, const struct pci_device
card->address_interrupt = ali_address_interrupt;
+ /* Added by Matt Wu 01-05-2001 for spdif in */
+ card->multi_channel_use_count = 0;
+ card->rec_channel_use_count = 0;
+
/* ALi SPDIF OUT function */
if(card->revision == ALI_5451_V02) {
ali_setup_spdif_out(card, ALI_PCM_TO_SPDIF_OUT);
@@ -3203,7 +3408,7 @@ static int __init trident_probe(struct pci_dev *pci_dev, const struct pci_device
kfree(card);
return -ENODEV;
}
- /* initilize AC97 codec and register /dev/mixer */
+ /* initialize AC97 codec and register /dev/mixer */
if (trident_ac97_init(card) <= 0) {
unregister_sound_dsp(card->dev_audio);
release_region(iobase, 256);
@@ -3224,7 +3429,6 @@ static int __init trident_probe(struct pci_dev *pci_dev, const struct pci_device
}
pci_set_drvdata(pci_dev, card);
- pci_dev->dma_mask = TRIDENT_DMA_MASK;
/* Enable Address Engine Interrupts */
trident_enable_loop_interrupts(card);