patch-2.4.6 linux/drivers/sound/via82cxxx_audio.c
Next file: linux/drivers/sound/wavfront.c
Previous file: linux/drivers/sound/sb_card.c
Back to the patch index
Back to the overall index
- Lines: 279
- Date:
Mon Jul 2 14:03:04 2001
- Orig file:
v2.4.5/linux/drivers/sound/via82cxxx_audio.c
- Orig date:
Tue May 1 16:05:00 2001
diff -u --recursive --new-file v2.4.5/linux/drivers/sound/via82cxxx_audio.c linux/drivers/sound/via82cxxx_audio.c
@@ -39,6 +39,9 @@
#include <asm/uaccess.h>
#include <asm/hardirq.h>
#include <asm/semaphore.h>
+#include "sound_config.h"
+#include "dev_table.h"
+#include "mpu401.h"
#undef VIA_DEBUG /* define to enable debugging output and checks */
@@ -178,6 +181,8 @@
#define VIA_CR42_MIDI_ENABLE 0x02
#define VIA_CR42_FM_ENABLE 0x04
#define VIA_CR42_GAME_ENABLE 0x08
+#define VIA_CR42_MIDI_IRQMASK 0x40
+#define VIA_CR42_MIDI_PNP 0x80
#define VIA_CR44_SECOND_CODEC_SUPPORT (1 << 6)
#define VIA_CR44_AC_LINK_ACCESS (1 << 7)
@@ -290,6 +295,11 @@
struct via_channel ch_in;
struct via_channel ch_out;
struct via_channel ch_fm;
+
+#ifdef CONFIG_MIDI_VIA82CXXX
+ void *midi_devc;
+ struct address_info midi_info;
+#endif
};
@@ -720,12 +730,10 @@
/* set location of DMA-able scatter-gather info table */
DPRINTK ("outl (0x%X, 0x%04lX)\n",
- cpu_to_le32 (chan->sgt_handle),
- chan->iobase + VIA_PCM_TABLE_ADDR);
+ chan->sgt_handle, chan->iobase + VIA_PCM_TABLE_ADDR);
via_ac97_wait_idle (card);
- outl (cpu_to_le32 (chan->sgt_handle),
- chan->iobase + VIA_PCM_TABLE_ADDR);
+ outl (chan->sgt_handle, chan->iobase + VIA_PCM_TABLE_ADDR);
udelay (20);
via_ac97_wait_idle (card);
@@ -1216,25 +1224,28 @@
card = codec->private_data;
- data = (reg << 16) | VIA_CR80_READ;
+ /* Every time we write to register 80 we cause a transaction.
+ The only safe way to clear the valid bit is to write it at
+ the same time as the command */
+ data = (reg << 16) | VIA_CR80_READ | VIA_CR80_VALID;
outl (data, card->baseaddr + VIA_BASE0_AC97_CTRL);
- udelay (20);
-
for (counter = VIA_COUNTER_LIMIT; counter > 0; counter--) {
- if (inl (card->baseaddr + 0x80) & VIA_CR80_VALID)
+ udelay (1);
+ if ((((data = inl(card->baseaddr + 0x80)) &
+ (VIA_CR80_VALID|VIA_CR80_BUSY)) == VIA_CR80_VALID))
goto out;
-
- udelay (15);
}
printk (KERN_WARNING PFX "timeout while reading AC97 codec (0x%lX)\n", data);
goto err_out;
out:
+ /* Once the valid bit has become set, we must wait a complete AC97
+ frame before the data has settled. */
+ udelay(25);
data = (unsigned long) inl (card->baseaddr + 0x80);
- outb (0x02, card->baseaddr + 0x83);
-
+
if (((data & 0x007F0000) >> 16) == reg) {
DPRINTK ("EXIT, success, data=0x%lx, retval=0x%lx\n",
data, data & 0x0000FFFF);
@@ -1371,7 +1382,6 @@
static int __init via_ac97_reset (struct via_info *card)
{
struct pci_dev *pdev = card->pdev;
- u8 tmp8;
u16 tmp16;
DPRINTK ("ENTER\n");
@@ -1569,10 +1579,10 @@
* and advance the h/w ptr, wrapping around to zero if needed
*/
if (n == (chan->frag_number - 1)) {
- chan->sgtable[n].count = (chan->frag_size | VIA_EOL);
+ chan->sgtable[n].count = cpu_to_le32(chan->frag_size | VIA_EOL);
atomic_set (&chan->hw_ptr, 0);
} else {
- chan->sgtable[n].count = (chan->frag_size | VIA_FLAG);
+ chan->sgtable[n].count = cpu_to_le32(chan->frag_size | VIA_FLAG);
atomic_inc (&chan->hw_ptr);
}
@@ -1628,8 +1638,12 @@
*/
status32 = inl (card->baseaddr + VIA_BASE0_SGD_STATUS_SHADOW);
if (!(status32 & VIA_INTR_MASK))
+ {
+#ifdef CONFIG_MIDI_VIA82CXXX
+ uart401intr(irq, card->midi_devc, regs);
+#endif
return;
-
+ }
DPRINTK ("intr, status32 == 0x%08X\n", status32);
/* synchronize interrupt handling under SMP. this spinlock
@@ -1781,10 +1795,8 @@
/* turn off legacy features, if not already */
pci_read_config_byte (card->pdev, VIA_FUNC_ENABLE, &tmp8);
- if (tmp8 & (VIA_CR42_SB_ENABLE | VIA_CR42_MIDI_ENABLE |
- VIA_CR42_FM_ENABLE)) {
- tmp8 &= ~(VIA_CR42_SB_ENABLE | VIA_CR42_MIDI_ENABLE |
- VIA_CR42_FM_ENABLE);
+ if (tmp8 & (VIA_CR42_SB_ENABLE | VIA_CR42_FM_ENABLE)) {
+ tmp8 &= ~(VIA_CR42_SB_ENABLE | VIA_CR42_FM_ENABLE);
pci_write_config_byte (card->pdev, VIA_FUNC_ENABLE, tmp8);
}
@@ -2682,6 +2694,7 @@
/* wait until all buffers have been played, and then stop device */
case SNDCTL_DSP_SYNC:
DPRINTK ("DSP_SYNC\n");
+ rc = 0;
if (wr) {
DPRINTK ("SYNC EXIT (after calling via_dsp_drain_playback)\n");
rc = via_dsp_drain_playback (card, &card->ch_out, nonblock);
@@ -3010,9 +3023,11 @@
static int __init via_init_one (struct pci_dev *pdev, const struct pci_device_id *id)
{
+#ifdef CONFIG_MIDI_VIA82CXXX
+ u8 r42;
+#endif
int rc;
struct via_info *card;
- u8 tmp;
static int printed_version = 0;
DPRINTK ("ENTER\n");
@@ -3020,25 +3035,19 @@
if (printed_version++ == 0)
printk (KERN_INFO "Via 686a audio driver " VIA_VERSION "\n");
- if (pci_enable_device (pdev)) {
- rc = -EIO;
- goto err_out_none;
- }
-
- if (!request_region (pci_resource_start (pdev, 0),
- pci_resource_len (pdev, 0),
- VIA_MODULE_NAME)) {
- printk (KERN_ERR PFX "unable to obtain I/O resources, aborting\n");
- rc = -EBUSY;
+ rc = pci_enable_device (pdev);
+ if (rc)
goto err_out;
- }
+ rc = pci_request_regions (pdev, "via82cxxx_audio");
+ if (rc)
+ goto err_out_disable;
card = kmalloc (sizeof (*card), GFP_KERNEL);
if (!card) {
printk (KERN_ERR PFX "out of memory, aborting\n");
rc = -ENOMEM;
- goto err_out_none;
+ goto err_out_res;
}
pci_set_drvdata (pdev, card);
@@ -3109,22 +3118,37 @@
goto err_out_have_proc;
}
- pci_read_config_byte (pdev, 0x3C, &tmp);
- if ((tmp & 0x0F) != pdev->irq) {
- printk (KERN_WARNING PFX "IRQ fixup, 0x3C==0x%02X\n", tmp);
- udelay (15);
- tmp &= 0xF0;
- tmp |= pdev->irq;
- pci_write_config_byte (pdev, 0x3C, tmp);
- DPRINTK ("new 0x3c==0x%02x\n", tmp);
- } else {
- DPRINTK ("IRQ reg 0x3c==0x%02x, irq==%d\n",
- tmp, tmp & 0x0F);
- }
-
printk (KERN_INFO PFX "board #%d at 0x%04lX, IRQ %d\n",
card->card_num + 1, card->baseaddr, pdev->irq);
+#ifdef CONFIG_MIDI_VIA82CXXX
+ /* Disable by default */
+ card->midi_info.io_base = 0;
+
+ pci_read_config_byte (pdev, 0x42, &r42);
+ /* Disable MIDI interrupt */
+ pci_write_config_byte (pdev, 0x42, r42 | VIA_CR42_MIDI_IRQMASK);
+ if (r42 & VIA_CR42_MIDI_ENABLE)
+ {
+ if (r42 & VIA_CR42_MIDI_PNP) /* Address selected by iobase 2 - not tested */
+ card->midi_info.io_base = pci_resource_start (pdev, 2);
+ else /* Address selected by byte 0x43 */
+ {
+ u8 r43;
+ pci_read_config_byte (pdev, 0x43, &r43);
+ card->midi_info.io_base = 0x300 + ((r43 & 0x0c) << 2);
+ }
+
+ card->midi_info.irq = -pdev->irq;
+ if (probe_uart401(& card->midi_info, THIS_MODULE))
+ {
+ card->midi_devc=midi_devs[card->midi_info.slots[4]]->devc;
+ pci_write_config_byte(pdev, 0x42, r42 & ~VIA_CR42_MIDI_IRQMASK);
+ printk("Enabled Via MIDI\n");
+ }
+ }
+#endif
+
DPRINTK ("EXIT, returning 0\n");
return 0;
@@ -3143,8 +3167,12 @@
#endif
kfree (card);
-err_out_none:
- release_region (pci_resource_start (pdev, 0), pci_resource_len (pdev, 0));
+err_out_res:
+ pci_release_regions (pdev);
+
+err_out_disable:
+ pci_disable_device (pdev);
+
err_out:
pci_set_drvdata (pdev, NULL);
DPRINTK ("EXIT - returning %d\n", rc);
@@ -3162,13 +3190,16 @@
card = pci_get_drvdata (pdev);
assert (card != NULL);
+#ifdef CONFIG_MIDI_VIA82CXXX
+ if (card->midi_info.io_base)
+ unload_uart401(&card->midi_info);
+#endif
+
via_interrupt_cleanup (card);
via_card_cleanup_proc (card);
via_dsp_cleanup (card);
via_ac97_cleanup (card);
- release_region (pci_resource_start (pdev, 0), pci_resource_len (pdev, 0));
-
#ifndef VIA_NDEBUG
memset (card, 0xAB, sizeof (*card)); /* poison memory */
#endif
@@ -3176,7 +3207,9 @@
pci_set_drvdata (pdev, NULL);
+ pci_release_regions (pdev);
pci_set_power_state (pdev, 3); /* ...zzzzzz */
+ pci_disable_device (pdev);
DPRINTK ("EXIT\n");
return;
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)