patch-2.3.25 linux/drivers/sound/es1371.c
Next file: linux/drivers/sound/esssolo1.c
Previous file: linux/drivers/sound/es1370.c
Back to the patch index
Back to the overall index
- Lines: 861
- Date:
Sat Oct 30 09:45:36 1999
- Orig file:
v2.3.24/linux/drivers/sound/es1371.c
- Orig date:
Fri Sep 10 23:57:35 1999
diff -u --recursive --new-file v2.3.24/linux/drivers/sound/es1371.c linux/drivers/sound/es1371.c
@@ -86,7 +86,14 @@
* replaced current->state = x with set_current_state(x)
* 03.09.99 0.18 change read semantics for MIDI to match
* OSS more closely; remove possible wakeup race
- *
+ * 21.10.99 0.19 Round sampling rates, requested by
+ * Kasamatsu Kenichi <t29w0267@ip.media.kyoto-u.ac.jp>
+ * 27.10.99 0.20 Added SigmaTel 3D enhancement string
+ * Codec ID printing changes
+ * 28.10.99 0.21 More waitqueue races fixed
+ * Joe Cotellese <joec@ensoniq.com>
+ * Changed PCI detection routine so we can more easily
+ * detect ES137x chip and derivatives.
*/
/*****************************************************************************/
@@ -116,16 +123,31 @@
#undef OSS_DOCUMENTED_MIXER_SEMANTICS
#define ES1371_DEBUG
+#define DBG(x) {}
+/*#define DBG(x) {x}*/
/* --------------------------------------------------------------------- */
#ifndef PCI_VENDOR_ID_ENSONIQ
#define PCI_VENDOR_ID_ENSONIQ 0x1274
#endif
+
+#ifndef PCI_VENDOR_ID_ECTIVA
+#define PCI_VENDOR_ID_ECTIVA 0x1102
+#endif
+
#ifndef PCI_DEVICE_ID_ENSONIQ_ES1371
#define PCI_DEVICE_ID_ENSONIQ_ES1371 0x1371
#endif
+#ifndef PCI_DEVICE_ID_ENSONIQ_CT5880
+#define PCI_DEVICE_ID_ENSONIQ_CT5880 0x5880
+#endif
+
+#ifndef PCI_DEVICE_ID_ECTIVA_EV1938
+#define PCI_DEVICE_ID_ECTIVA_EV1938 0x8938
+#endif
+
/* ES1371 chip ID */
/* This is a little confusing because all ES1371 compatible chips have the
same DEVICE_ID, the only thing differentiating them is the REV_ID field.
@@ -135,8 +157,9 @@
#define ES1371REV_ES1373_A 0x04
#define ES1371REV_ES1373_B 0x06
#define ES1371REV_CT5880_A 0x07
+#define CT5880REV_CT5880_C 0x02
#define ES1371REV_ES1371_B 0x09
-
+#define EV1938REV_EV1938_A 0x00
#define ES1371_MAGIC ((PCI_VENDOR_ID_ENSONIQ<<16)|PCI_DEVICE_ID_ENSONIQ_ES1371)
@@ -144,7 +167,7 @@
#define JOY_EXTENT 8
#define ES1371_REG_CONTROL 0x00
-#define ES1371_REG_STATUS 0x04
+#define ES1371_REG_STATUS 0x04 /* on the 5880 it is control/status */
#define ES1371_REG_UART_DATA 0x08
#define ES1371_REG_UART_STATUS 0x09
#define ES1371_REG_UART_CONTROL 0x09
@@ -212,6 +235,7 @@
#define STAT_INTR 0x80000000 /* wired or of all interrupt bits */
+#define CSTAT_5880_AC97_RST 0x20000000 /* CT5880 Reset bit */
#define STAT_EN_SPDIF 0x00040000 /* enable S/PDIF circuitry */
#define STAT_TS_SPDIF 0x00020000 /* test S/PDIF circuitry */
#define STAT_TESTMODE 0x00010000 /* test ASIC */
@@ -370,7 +394,13 @@
"NVidea 3D Stereo Enhancement",
"Philips Incredible Sound",
"Texas Instruments 3D Stereo Enhancement",
- "VLSI Technology 3D Stereo Enhancement"
+ "VLSI Technology 3D Stereo Enhancement",
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ "SigmaTel SS3D"
};
/* --------------------------------------------------------------------- */
@@ -391,8 +421,12 @@
/* hardware resources */
unsigned long io; /* long for SPARC */
unsigned int irq;
+
+ /* PCI ID's */
+ u16 vendor;
+ u16 device;
u8 rev; /* the chip revision */
-
+
#ifdef ES1371_DEBUG
/* debug /proc entry */
struct proc_dir_entry *ps;
@@ -591,8 +625,8 @@
rate = 48000;
if (rate < 4000)
rate = 4000;
- freq = (rate << 15) / 3000;
- s->dac1rate = (freq * 3000) >> 15;
+ freq = ((rate << 15) + 1500) / 3000;
+ s->dac1rate = (freq * 3000 + 16384) >> 15;
spin_lock_irqsave(&s->lock, flags);
r = (wait_src_ready(s) & (SRC_DIS | SRC_DDAC2 | SRC_DADC)) | SRC_DDAC1;
outl(r, s->io + ES1371_REG_SRCONV);
@@ -614,9 +648,8 @@
rate = 48000;
if (rate < 4000)
rate = 4000;
- freq = (rate << 15) / 3000;
- s->dac2rate = (freq * 3000) >> 15;
- printk (KERN_DEBUG "dac2 freq: %d\n", freq);
+ freq = ((rate << 15) + 1500) / 3000;
+ s->dac2rate = (freq * 3000 + 16384) >> 15;
spin_lock_irqsave(&s->lock, flags);
r = (wait_src_ready(s) & (SRC_DIS | SRC_DDAC1 | SRC_DADC)) | SRC_DDAC2;
outl(r, s->io + ES1371_REG_SRCONV);
@@ -1612,10 +1645,9 @@
if (s->dma_dac1.mapped || !s->dma_dac1.ready)
return 0;
-
- __set_current_state(TASK_INTERRUPTIBLE);
add_wait_queue(&s->dma_dac1.wait, &wait);
for (;;) {
+ __set_current_state(TASK_INTERRUPTIBLE);
spin_lock_irqsave(&s->lock, flags);
count = s->dma_dac1.count;
spin_unlock_irqrestore(&s->lock, flags);
@@ -1631,7 +1663,7 @@
tmo = 3 * HZ * (count + s->dma_dac1.fragsize) / 2 / s->dac1rate;
tmo >>= sample_shift[(s->sctrl & SCTRL_P1FMT) >> SCTRL_SH_P1FMT];
if (!schedule_timeout(tmo + 1))
- printk(KERN_DEBUG "es1371: dac1 dma timed out??\n");
+ DBG(printk(KERN_DEBUG "es1371: dac1 dma timed out??\n");)
}
remove_wait_queue(&s->dma_dac1.wait, &wait);
set_current_state(TASK_RUNNING);
@@ -1648,10 +1680,9 @@
if (s->dma_dac2.mapped || !s->dma_dac2.ready)
return 0;
-
- __set_current_state(TASK_UNINTERRUPTIBLE);
add_wait_queue(&s->dma_dac2.wait, &wait);
for (;;) {
+ __set_current_state(TASK_UNINTERRUPTIBLE);
spin_lock_irqsave(&s->lock, flags);
count = s->dma_dac2.count;
spin_unlock_irqrestore(&s->lock, flags);
@@ -1667,7 +1698,7 @@
tmo = 3 * HZ * (count + s->dma_dac2.fragsize) / 2 / s->dac2rate;
tmo >>= sample_shift[(s->sctrl & SCTRL_P2FMT) >> SCTRL_SH_P2FMT];
if (!schedule_timeout(tmo + 1))
- printk(KERN_DEBUG "es1371: dac2 dma timed out??\n");
+ DBG(printk(KERN_DEBUG "es1371: dac2 dma timed out??\n");)
}
remove_wait_queue(&s->dma_dac2.wait, &wait);
set_current_state(TASK_RUNNING);
@@ -1681,6 +1712,7 @@
static ssize_t es1371_read(struct file *file, char *buffer, size_t count, loff_t *ppos)
{
struct es1371_state *s = (struct es1371_state *)file->private_data;
+ DECLARE_WAITQUEUE(wait, current);
ssize_t ret;
unsigned long flags;
unsigned swptr;
@@ -1696,26 +1728,38 @@
if (!access_ok(VERIFY_WRITE, buffer, count))
return -EFAULT;
ret = 0;
+ add_wait_queue(&s->dma_adc.wait, &wait);
while (count > 0) {
spin_lock_irqsave(&s->lock, flags);
swptr = s->dma_adc.swptr;
cnt = s->dma_adc.dmasize-swptr;
if (s->dma_adc.count < cnt)
cnt = s->dma_adc.count;
+ if (cnt <= 0)
+ __set_current_state(TASK_INTERRUPTIBLE);
spin_unlock_irqrestore(&s->lock, flags);
if (cnt > count)
cnt = count;
if (cnt <= 0) {
start_adc(s);
- if (file->f_flags & O_NONBLOCK)
- return ret ? ret : -EAGAIN;
- interruptible_sleep_on(&s->dma_adc.wait);
- if (signal_pending(current))
- return ret ? ret : -ERESTARTSYS;
+ if (file->f_flags & O_NONBLOCK) {
+ if (!ret)
+ ret = -EAGAIN;
+ break;
+ }
+ schedule();
+ if (signal_pending(current)) {
+ if (!ret)
+ ret = -ERESTARTSYS;
+ break;
+ }
continue;
}
- if (copy_to_user(buffer, s->dma_adc.rawbuf + swptr, cnt))
- return ret ? ret : -EFAULT;
+ if (copy_to_user(buffer, s->dma_adc.rawbuf + swptr, cnt)) {
+ if (!ret)
+ ret = -EFAULT;
+ break;
+ }
swptr = (swptr + cnt) % s->dma_adc.dmasize;
spin_lock_irqsave(&s->lock, flags);
s->dma_adc.swptr = swptr;
@@ -1726,12 +1770,15 @@
ret += cnt;
start_adc(s);
}
+ remove_wait_queue(&s->dma_adc.wait, &wait);
+ set_current_state(TASK_RUNNING);
return ret;
}
static ssize_t es1371_write(struct file *file, const char *buffer, size_t count, loff_t *ppos)
{
struct es1371_state *s = (struct es1371_state *)file->private_data;
+ DECLARE_WAITQUEUE(wait, current);
ssize_t ret;
unsigned long flags;
unsigned swptr;
@@ -1747,6 +1794,7 @@
if (!access_ok(VERIFY_READ, buffer, count))
return -EFAULT;
ret = 0;
+ add_wait_queue(&s->dma_dac2.wait, &wait);
while (count > 0) {
spin_lock_irqsave(&s->lock, flags);
if (s->dma_dac2.count < 0) {
@@ -1757,20 +1805,31 @@
cnt = s->dma_dac2.dmasize-swptr;
if (s->dma_dac2.count + cnt > s->dma_dac2.dmasize)
cnt = s->dma_dac2.dmasize - s->dma_dac2.count;
+ if (cnt <= 0)
+ __set_current_state(TASK_INTERRUPTIBLE);
spin_unlock_irqrestore(&s->lock, flags);
if (cnt > count)
cnt = count;
if (cnt <= 0) {
start_dac2(s);
- if (file->f_flags & O_NONBLOCK)
- return ret ? ret : -EAGAIN;
- interruptible_sleep_on(&s->dma_dac2.wait);
- if (signal_pending(current))
- return ret ? ret : -ERESTARTSYS;
+ if (file->f_flags & O_NONBLOCK) {
+ if (!ret)
+ ret = -EAGAIN;
+ break;
+ }
+ schedule();
+ if (signal_pending(current)) {
+ if (!ret)
+ ret = -ERESTARTSYS;
+ break;
+ }
continue;
}
- if (copy_from_user(s->dma_dac2.rawbuf + swptr, buffer, cnt))
- return ret ? ret : -EFAULT;
+ if (copy_from_user(s->dma_dac2.rawbuf + swptr, buffer, cnt)) {
+ if (!ret)
+ ret = -EFAULT;
+ break;
+ }
swptr = (swptr + cnt) % s->dma_dac2.dmasize;
spin_lock_irqsave(&s->lock, flags);
s->dma_dac2.swptr = swptr;
@@ -1782,6 +1841,8 @@
ret += cnt;
start_dac2(s);
}
+ remove_wait_queue(&s->dma_dac2.wait, &wait);
+ set_current_state(TASK_RUNNING);
return ret;
}
@@ -1833,7 +1894,7 @@
db = &s->dma_adc;
} else
return -EINVAL;
- if (vma->vm_offset != 0)
+ if (vma->vm_pgoff != 0)
return -EINVAL;
size = vma->vm_end - vma->vm_start;
if (size > (PAGE_SIZE << db->buforder))
@@ -1894,7 +1955,6 @@
if (file->f_mode & FMODE_WRITE) {
stop_dac2(s);
s->dma_dac2.ready = 0;
- printk (KERN_DEBUG "es137x: setting DAC2 rate: %d\n", val);
set_dac2_rate(s, val);
}
}
@@ -2152,6 +2212,7 @@
static int es1371_open(struct inode *inode, struct file *file)
{
int minor = MINOR(inode->i_rdev);
+ DECLARE_WAITQUEUE(wait, current);
struct es1371_state *s = devs;
unsigned long flags;
@@ -2168,8 +2229,12 @@
up(&s->open_sem);
return -EBUSY;
}
+ add_wait_queue(&s->open_wait, &wait);
+ __set_current_state(TASK_INTERRUPTIBLE);
up(&s->open_sem);
- interruptible_sleep_on(&s->open_wait);
+ schedule();
+ remove_wait_queue(&s->open_wait, &wait);
+ set_current_state(TASK_RUNNING);
if (signal_pending(current))
return -ERESTARTSYS;
down(&s->open_sem);
@@ -2251,6 +2316,7 @@
static ssize_t es1371_write_dac(struct file *file, const char *buffer, size_t count, loff_t *ppos)
{
struct es1371_state *s = (struct es1371_state *)file->private_data;
+ DECLARE_WAITQUEUE(wait, current);
ssize_t ret = 0;
unsigned long flags;
unsigned swptr;
@@ -2265,6 +2331,7 @@
return ret;
if (!access_ok(VERIFY_READ, buffer, count))
return -EFAULT;
+ add_wait_queue(&s->dma_dac1.wait, &wait);
while (count > 0) {
spin_lock_irqsave(&s->lock, flags);
if (s->dma_dac1.count < 0) {
@@ -2275,20 +2342,31 @@
cnt = s->dma_dac1.dmasize-swptr;
if (s->dma_dac1.count + cnt > s->dma_dac1.dmasize)
cnt = s->dma_dac1.dmasize - s->dma_dac1.count;
+ if (cnt <= 0)
+ __set_current_state(TASK_INTERRUPTIBLE);
spin_unlock_irqrestore(&s->lock, flags);
if (cnt > count)
cnt = count;
if (cnt <= 0) {
start_dac1(s);
- if (file->f_flags & O_NONBLOCK)
- return ret ? ret : -EAGAIN;
- interruptible_sleep_on(&s->dma_dac1.wait);
- if (signal_pending(current))
- return ret ? ret : -ERESTARTSYS;
+ if (file->f_flags & O_NONBLOCK) {
+ if (!ret)
+ ret = -EAGAIN;
+ break;
+ }
+ schedule();
+ if (signal_pending(current)) {
+ if (!ret)
+ ret = -ERESTARTSYS;
+ break;
+ }
continue;
}
- if (copy_from_user(s->dma_dac1.rawbuf + swptr, buffer, cnt))
- return ret ? ret : -EFAULT;
+ if (copy_from_user(s->dma_dac1.rawbuf + swptr, buffer, cnt)) {
+ if (!ret)
+ ret = -EFAULT;
+ break;
+ }
swptr = (swptr + cnt) % s->dma_dac1.dmasize;
spin_lock_irqsave(&s->lock, flags);
s->dma_dac1.swptr = swptr;
@@ -2300,6 +2378,8 @@
ret += cnt;
start_dac1(s);
}
+ remove_wait_queue(&s->dma_dac1.wait, &wait);
+ set_current_state(TASK_RUNNING);
return ret;
}
@@ -2335,7 +2415,7 @@
return -EINVAL;
if ((ret = prog_dmabuf_dac1(s)) != 0)
return ret;
- if (vma->vm_offset != 0)
+ if (vma->vm_pgoff != 0)
return -EINVAL;
size = vma->vm_end - vma->vm_start;
if (size > (PAGE_SIZE << s->dma_dac1.buforder))
@@ -2528,6 +2608,7 @@
static int es1371_open_dac(struct inode *inode, struct file *file)
{
int minor = MINOR(inode->i_rdev);
+ DECLARE_WAITQUEUE(wait, current);
struct es1371_state *s = devs;
unsigned long flags;
@@ -2551,8 +2632,12 @@
up(&s->open_sem);
return -EBUSY;
}
+ add_wait_queue(&s->open_wait, &wait);
+ __set_current_state(TASK_INTERRUPTIBLE);
up(&s->open_sem);
- interruptible_sleep_on(&s->open_wait);
+ schedule();
+ remove_wait_queue(&s->open_wait, &wait);
+ set_current_state(TASK_RUNNING);
if (signal_pending(current))
return -ERESTARTSYS;
down(&s->open_sem);
@@ -2633,6 +2718,8 @@
cnt = MIDIINBUF - ptr;
if (s->midi.icnt < cnt)
cnt = s->midi.icnt;
+ if (cnt <= 0)
+ __set_current_state(TASK_INTERRUPTIBLE);
spin_unlock_irqrestore(&s->lock, flags);
if (cnt > count)
cnt = count;
@@ -2642,7 +2729,6 @@
ret = -EAGAIN;
break;
}
- __set_current_state(TASK_INTERRUPTIBLE);
schedule();
if (signal_pending(current)) {
if (!ret)
@@ -2695,8 +2781,10 @@
cnt = MIDIOUTBUF - ptr;
if (s->midi.ocnt + cnt > MIDIOUTBUF)
cnt = MIDIOUTBUF - s->midi.ocnt;
- if (cnt <= 0)
+ if (cnt <= 0) {
+ __set_current_state(TASK_INTERRUPTIBLE);
es1371_handle_midi(s);
+ }
spin_unlock_irqrestore(&s->lock, flags);
if (cnt > count)
cnt = count;
@@ -2706,7 +2794,6 @@
ret = -EAGAIN;
break;
}
- __set_current_state(TASK_INTERRUPTIBLE);
schedule();
if (signal_pending(current)) {
if (!ret)
@@ -2764,6 +2851,7 @@
static int es1371_midi_open(struct inode *inode, struct file *file)
{
int minor = MINOR(inode->i_rdev);
+ DECLARE_WAITQUEUE(wait, current);
struct es1371_state *s = devs;
unsigned long flags;
@@ -2780,8 +2868,12 @@
up(&s->open_sem);
return -EBUSY;
}
+ add_wait_queue(&s->open_wait, &wait);
+ __set_current_state(TASK_INTERRUPTIBLE);
up(&s->open_sem);
- interruptible_sleep_on(&s->open_wait);
+ schedule();
+ remove_wait_queue(&s->open_wait, &wait);
+ set_current_state(TASK_RUNNING);
if (signal_pending(current))
return -ERESTARTSYS;
down(&s->open_sem);
@@ -2819,9 +2911,9 @@
VALIDATE_STATE(s);
if (file->f_mode & FMODE_WRITE) {
- __set_current_state(TASK_INTERRUPTIBLE);
add_wait_queue(&s->midi.owait, &wait);
for (;;) {
+ __set_current_state(TASK_INTERRUPTIBLE);
spin_lock_irqsave(&s->lock, flags);
count = s->midi.ocnt;
spin_unlock_irqrestore(&s->lock, flags);
@@ -2952,162 +3044,212 @@
((dev)->resource[(num)].flags & PCI_BASE_ADDRESS_SPACE) == PCI_BASE_ADDRESS_SPACE_IO)
#define RSRCADDRESS(dev,num) ((dev)->resource[(num)].start)
+static int __init probe_chip(struct pci_dev *pcidev, int index)
+{
+ struct es1371_state *s;
+ mm_segment_t fs;
+ int i, val, val2;
+ unsigned char id[4];
+ unsigned long tmo;
+ signed long tmo2;
+ unsigned int cssr;
+
+ if (!RSRCISIOREGION(pcidev, 0))
+ return -1;
+ if (pcidev->irq == 0)
+ return -1;
+ if (!(s = kmalloc(sizeof(struct es1371_state), GFP_KERNEL))) {
+ printk(KERN_WARNING "es1371: out of memory\n");
+ return -1;
+ }
+ memset(s, 0, sizeof(struct es1371_state));
+ init_waitqueue_head(&s->dma_adc.wait);
+ init_waitqueue_head(&s->dma_dac1.wait);
+ init_waitqueue_head(&s->dma_dac2.wait);
+ init_waitqueue_head(&s->open_wait);
+ init_waitqueue_head(&s->midi.iwait);
+ init_waitqueue_head(&s->midi.owait);
+ init_MUTEX(&s->open_sem);
+ spin_lock_init(&s->lock);
+ s->magic = ES1371_MAGIC;
+ s->io = RSRCADDRESS(pcidev, 0);
+ s->irq = pcidev->irq;
+ s->vendor = pcidev->vendor;
+ s->device = pcidev->device;
+ pci_read_config_byte(pcidev, PCI_REVISION_ID, &s->rev);
+ printk(KERN_INFO "es1371: found chip, vendor id 0x%04x device id 0x%04x revision 0x%02x\n",
+ s->vendor, s->device, s->rev);
+ if (check_region(s->io, ES1371_EXTENT)) {
+ printk(KERN_ERR "es1371: io ports %#lx-%#lx in use\n", s->io, s->io+ES1371_EXTENT-1);
+ goto err_region;
+ }
+ request_region(s->io, ES1371_EXTENT, "es1371");
+ if (request_irq(s->irq, es1371_interrupt, SA_SHIRQ, "es1371", s)) {
+ printk(KERN_ERR "es1371: irq %u in use\n", s->irq);
+ goto err_irq;
+ }
+ printk(KERN_INFO "es1371: found es1371 rev %d at io %#lx irq %u\n"
+ KERN_INFO "es1371: features: joystick 0x%x\n", s->rev, s->io, s->irq, joystick[index]);
+ /* register devices */
+ if ((s->dev_audio = register_sound_dsp(&es1371_audio_fops, -1)) < 0)
+ goto err_dev1;
+ if ((s->dev_mixer = register_sound_mixer(&es1371_mixer_fops, -1)) < 0)
+ goto err_dev2;
+ if ((s->dev_dac = register_sound_dsp(&es1371_dac_fops, -1)) < 0)
+ goto err_dev3;
+ if ((s->dev_midi = register_sound_midi(&es1371_midi_fops, -1)) < 0)
+ goto err_dev4;
+#ifdef ES1371_DEBUG
+ /* intialize the debug proc device */
+ s->ps = create_proc_entry("es1371", S_IFREG | S_IRUGO, NULL);
+ if (s->ps)
+ s->ps->read_proc = proc_es1371_dump;
+#endif /* ES1371_DEBUG */
+
+ /* initialize codec registers */
+ s->ctrl = 0;
+ if ((joystick[index] & ~0x18) == 0x200) {
+ if (check_region(joystick[index], JOY_EXTENT))
+ printk(KERN_ERR "es1371: joystick address 0x%x already in use\n", joystick[index]);
+ else {
+ s->ctrl |= CTRL_JYSTK_EN | (((joystick[index] >> 3) & CTRL_JOY_MASK) << CTRL_JOY_SHIFT);
+ }
+ }
+ s->sctrl = 0;
+ cssr = 0;
+ /* check to see if s/pdif mode is being requested */
+ if (spdif[index]) {
+ if (s->rev >= 4) {
+ printk(KERN_INFO "es1371: enabling S/PDIF output\n");
+ cssr |= STAT_EN_SPDIF;
+ s->ctrl |= CTRL_SPDIFEN_B;
+ } else {
+ printk(KERN_ERR "es1371: revision %d does not support S/PDIF\n", s->rev);
+ }
+ }
+ /* initialize the chips */
+ outl(s->ctrl, s->io+ES1371_REG_CONTROL);
+ outl(s->sctrl, s->io+ES1371_REG_SERIAL_CONTROL);
+ outl(0, s->io+ES1371_REG_LEGACY);
+ pci_set_master(pcidev); /* enable bus mastering */
+ /* if we are a 5880 turn on the AC97 */
+ if (s->vendor == PCI_VENDOR_ID_ENSONIQ &&
+ s->device == PCI_DEVICE_ID_ENSONIQ_CT5880 &&
+ s->rev == CT5880REV_CT5880_C) {
+ cssr |= CSTAT_5880_AC97_RST;
+ outl(cssr, s->io+ES1371_REG_STATUS);
+ /* need to delay around 20ms(bleech) to give
+ some CODECs enough time to wakeup */
+ tmo = jiffies + (HZ / 50) + 1;
+ for (;;) {
+ tmo2 = tmo - jiffies;
+ if (tmo2 <= 0)
+ break;
+ schedule_timeout(tmo2);
+ }
+ }
+ /* AC97 warm reset to start the bitclk */
+ outl(s->ctrl | CTRL_SYNCRES, s->io+ES1371_REG_CONTROL);
+ udelay(2);
+ outl(s->ctrl, s->io+ES1371_REG_CONTROL);
+ /* init the sample rate converter */
+ src_init(s);
+ /* codec init */
+ wrcodec(s, AC97_RESET, 0); /* reset codec */
+ s->mix.codec_id = rdcodec(s, AC97_RESET); /* get codec ID */
+ val = rdcodec(s, AC97_VENDOR_ID1);
+ val2 = rdcodec(s, AC97_VENDOR_ID2);
+ id[0] = val >> 8;
+ id[1] = val;
+ id[2] = val2 >> 8;
+ id[3] = 0;
+ if (id[0] <= ' ' || id[0] > 0x7f)
+ id[0] = ' ';
+ if (id[1] <= ' ' || id[1] > 0x7f)
+ id[1] = ' ';
+ if (id[2] <= ' ' || id[2] > 0x7f)
+ id[2] = ' ';
+ printk(KERN_INFO "es1371: codec vendor %s (0x%04x%02x) revision %d (0x%02x)\n",
+ id, val & 0xffff, (val2 >> 8) & 0xff, val2 & 0xff, val2 & 0xff);
+ printk(KERN_INFO "es1371: codec features");
+ if (s->mix.codec_id & CODEC_ID_DEDICATEDMIC)
+ printk(" dedicated MIC PCM in");
+ if (s->mix.codec_id & CODEC_ID_MODEMCODEC)
+ printk(" Modem Line Codec");
+ if (s->mix.codec_id & CODEC_ID_BASSTREBLE)
+ printk(" Bass & Treble");
+ if (s->mix.codec_id & CODEC_ID_SIMULATEDSTEREO)
+ printk(" Simulated Stereo");
+ if (s->mix.codec_id & CODEC_ID_HEADPHONEOUT)
+ printk(" Headphone out");
+ if (s->mix.codec_id & CODEC_ID_LOUDNESS)
+ printk(" Loudness");
+ if (s->mix.codec_id & CODEC_ID_18BITDAC)
+ printk(" 18bit DAC");
+ if (s->mix.codec_id & CODEC_ID_20BITDAC)
+ printk(" 20bit DAC");
+ if (s->mix.codec_id & CODEC_ID_18BITADC)
+ printk(" 18bit ADC");
+ if (s->mix.codec_id & CODEC_ID_20BITADC)
+ printk(" 20bit ADC");
+ printk("%s\n", (s->mix.codec_id & 0x3ff) ? "" : " none");
+ val = (s->mix.codec_id >> CODEC_ID_SESHIFT) & CODEC_ID_SEMASK;
+ printk(KERN_INFO "es1371: stereo enhancement: %s\n",
+ (val <= 26 && stereo_enhancement[val]) ? stereo_enhancement[val] : "unknown");
+
+ fs = get_fs();
+ set_fs(KERNEL_DS);
+ val = SOUND_MASK_LINE;
+ mixer_ioctl(s, SOUND_MIXER_WRITE_RECSRC, (unsigned long)&val);
+ for (i = 0; i < sizeof(initvol)/sizeof(initvol[0]); i++) {
+ val = initvol[i].vol;
+ mixer_ioctl(s, initvol[i].mixch, (unsigned long)&val);
+ }
+ set_fs(fs);
+ /* turn on S/PDIF output driver if requested */
+ outl(cssr, s->io+ES1371_REG_STATUS);
+ /* queue it for later freeing */
+ s->next = devs;
+ devs = s;
+ return 0;
+
+ err_dev4:
+ unregister_sound_dsp(s->dev_dac);
+ err_dev3:
+ unregister_sound_mixer(s->dev_mixer);
+ err_dev2:
+ unregister_sound_dsp(s->dev_audio);
+ err_dev1:
+ printk(KERN_ERR "es1371: cannot register misc device\n");
+ free_irq(s->irq, s);
+ err_irq:
+ release_region(s->io, ES1371_EXTENT);
+ err_region:
+ kfree_s(s, sizeof(struct es1371_state));
+ return -1;
+}
+
static int __init init_es1371(void)
{
- struct es1371_state *s;
struct pci_dev *pcidev = NULL;
- mm_segment_t fs;
- int i, val, val2, index = 0;
- unsigned cssr;
+ int index = 0;
if (!pci_present()) /* No PCI bus in this machine! */
return -ENODEV;
- printk(KERN_INFO "es1371: version v0.17 time " __TIME__ " " __DATE__ "\n");
- while (index < NR_DEVICE &&
- (pcidev = pci_find_device(PCI_VENDOR_ID_ENSONIQ, PCI_DEVICE_ID_ENSONIQ_ES1371, pcidev))) {
- if (!RSRCISIOREGION(pcidev, 0))
- continue;
- if (pcidev->irq == 0)
- continue;
- if (!(s = kmalloc(sizeof(struct es1371_state), GFP_KERNEL))) {
- printk(KERN_WARNING "es1371: out of memory\n");
+ printk(KERN_INFO "es1371: version v0.22 time " __TIME__ " " __DATE__ "\n");
+ while (index < NR_DEVICE && (pcidev = pci_find_device(PCI_ANY_ID, PCI_ANY_ID, pcidev))) {
+ if (pcidev->vendor == PCI_VENDOR_ID_ENSONIQ) {
+ if (pcidev->device != PCI_DEVICE_ID_ENSONIQ_ES1371 &&
+ pcidev->device != PCI_DEVICE_ID_ENSONIQ_CT5880)
+ continue;
+ } else if (pcidev->vendor == PCI_VENDOR_ID_ECTIVA) {
+ if (pcidev->device != PCI_DEVICE_ID_ECTIVA_EV1938)
+ continue;
+ } else
continue;
- }
- memset(s, 0, sizeof(struct es1371_state));
- init_waitqueue_head(&s->dma_adc.wait);
- init_waitqueue_head(&s->dma_dac1.wait);
- init_waitqueue_head(&s->dma_dac2.wait);
- init_waitqueue_head(&s->open_wait);
- init_waitqueue_head(&s->midi.iwait);
- init_waitqueue_head(&s->midi.owait);
- init_MUTEX(&s->open_sem);
- spin_lock_init(&s->lock);
- s->magic = ES1371_MAGIC;
- s->io = RSRCADDRESS(pcidev, 0);
- s->irq = pcidev->irq;
- pci_read_config_byte(pcidev, PCI_REVISION_ID, &s->rev);
- if (check_region(s->io, ES1371_EXTENT)) {
- printk(KERN_ERR "es1371: io ports %#lx-%#lx in use\n", s->io, s->io+ES1371_EXTENT-1);
- goto err_region;
- }
- request_region(s->io, ES1371_EXTENT, "es1371");
- if (request_irq(s->irq, es1371_interrupt, SA_SHIRQ, "es1371", s)) {
- printk(KERN_ERR "es1371: irq %u in use\n", s->irq);
- goto err_irq;
- }
- printk(KERN_INFO "es1371: found es1371 rev %d at io %#lx irq %u\n"
- KERN_INFO "es1371: features: joystick 0x%x\n", s->rev, s->io, s->irq, joystick[index]);
- /* register devices */
- if ((s->dev_audio = register_sound_dsp(&es1371_audio_fops, -1)) < 0)
- goto err_dev1;
- if ((s->dev_mixer = register_sound_mixer(&es1371_mixer_fops, -1)) < 0)
- goto err_dev2;
- if ((s->dev_dac = register_sound_dsp(&es1371_dac_fops, -1)) < 0)
- goto err_dev3;
- if ((s->dev_midi = register_sound_midi(&es1371_midi_fops, -1)) < 0)
- goto err_dev4;
-#ifdef ES1371_DEBUG
- /* intialize the debug proc device */
- s->ps = create_proc_entry("es1371", S_IFREG | S_IRUGO, NULL);
- if (s->ps)
- s->ps->read_proc = proc_es1371_dump;
-#endif /* ES1371_DEBUG */
-
- /* initialize codec registers */
- s->ctrl = 0;
- if ((joystick[index] & ~0x18) == 0x200) {
- if (check_region(joystick[index], JOY_EXTENT))
- printk(KERN_ERR "es1371: joystick address 0x%x already in use\n", joystick[index]);
- else {
- s->ctrl |= CTRL_JYSTK_EN | (((joystick[index] >> 3) & CTRL_JOY_MASK) << CTRL_JOY_SHIFT);
- }
- }
- s->sctrl = 0;
- cssr = 0;
- /* check to see if s/pdif mode is being requested */
- if (spdif[index]) {
- if (s->rev >= 4) {
- printk(KERN_INFO "es1371: enabling S/PDIF output\n");
- cssr |= STAT_EN_SPDIF;
- s->ctrl |= CTRL_SPDIFEN_B;
- } else {
- printk(KERN_ERR "es1371: revision %d does not support S/PDIF\n", s->rev);
- }
- }
- /* initialize the chips */
- outl(s->ctrl, s->io+ES1371_REG_CONTROL);
- outl(s->sctrl, s->io+ES1371_REG_SERIAL_CONTROL);
- outl(0, s->io+ES1371_REG_LEGACY);
- pci_set_master(pcidev); /* enable bus mastering */
- /* AC97 warm reset to start the bitclk */
- outl(s->ctrl | CTRL_SYNCRES, s->io+ES1371_REG_CONTROL);
- udelay(2);
- outl(s->ctrl, s->io+ES1371_REG_CONTROL);
- /* init the sample rate converter */
- src_init(s);
- /* codec init */
- wrcodec(s, AC97_RESET, 0); /* reset codec */
- s->mix.codec_id = rdcodec(s, AC97_RESET); /* get codec ID */
- val = rdcodec(s, AC97_VENDOR_ID1);
- val2 = rdcodec(s, AC97_VENDOR_ID2);
- printk(KERN_INFO "es1371: codec vendor %c%c%c revision %d\n",
- (val >> 8) & 0xff, val & 0xff, (val2 >> 8) & 0xff, val2 & 0xff);
- printk(KERN_INFO "es1371: codec features");
- if (s->mix.codec_id & CODEC_ID_DEDICATEDMIC)
- printk(" dedicated MIC PCM in");
- if (s->mix.codec_id & CODEC_ID_MODEMCODEC)
- printk(" Modem Line Codec");
- if (s->mix.codec_id & CODEC_ID_BASSTREBLE)
- printk(" Bass & Treble");
- if (s->mix.codec_id & CODEC_ID_SIMULATEDSTEREO)
- printk(" Simulated Stereo");
- if (s->mix.codec_id & CODEC_ID_HEADPHONEOUT)
- printk(" Headphone out");
- if (s->mix.codec_id & CODEC_ID_LOUDNESS)
- printk(" Loudness");
- if (s->mix.codec_id & CODEC_ID_18BITDAC)
- printk(" 18bit DAC");
- if (s->mix.codec_id & CODEC_ID_20BITDAC)
- printk(" 20bit DAC");
- if (s->mix.codec_id & CODEC_ID_18BITADC)
- printk(" 18bit ADC");
- if (s->mix.codec_id & CODEC_ID_20BITADC)
- printk(" 20bit ADC");
- printk("%s\n", (s->mix.codec_id & 0x3ff) ? "" : " none");
- val = (s->mix.codec_id >> CODEC_ID_SESHIFT) & CODEC_ID_SEMASK;
- printk(KERN_INFO "es1371: stereo enhancement: %s\n", (val <= 20) ? stereo_enhancement[val] : "unknown");
-
- fs = get_fs();
- set_fs(KERNEL_DS);
- val = SOUND_MASK_LINE;
- mixer_ioctl(s, SOUND_MIXER_WRITE_RECSRC, (unsigned long)&val);
- for (i = 0; i < sizeof(initvol)/sizeof(initvol[0]); i++) {
- val = initvol[i].vol;
- mixer_ioctl(s, initvol[i].mixch, (unsigned long)&val);
- }
- set_fs(fs);
- /* turn on S/PDIF output driver if requested */
- outl(cssr, s->io+ES1371_REG_STATUS);
- /* queue it for later freeing */
- s->next = devs;
- devs = s;
- index++;
- continue;
-
- err_dev4:
- unregister_sound_dsp(s->dev_dac);
- err_dev3:
- unregister_sound_mixer(s->dev_mixer);
- err_dev2:
- unregister_sound_dsp(s->dev_audio);
- err_dev1:
- printk(KERN_ERR "es1371: cannot register misc device\n");
- free_irq(s->irq, s);
- err_irq:
- release_region(s->io, ES1371_EXTENT);
- err_region:
- kfree_s(s, sizeof(struct es1371_state));
+ if (!probe_chip(pcidev, index))
+ index++;
}
if (!devs)
return -ENODEV;
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)