patch-2.4.27 linux-2.4.27/drivers/sound/i810_audio.c
Next file: linux-2.4.27/drivers/sound/kahlua.c
Previous file: linux-2.4.27/drivers/sound/cmpci.c
Back to the patch index
Back to the overall index
- Lines: 750
- Date:
2004-08-07 16:26:05.556383841 -0700
- Orig file:
linux-2.4.26/drivers/sound/i810_audio.c
- Orig date:
2004-04-14 06:05:32.000000000 -0700
diff -urN linux-2.4.26/drivers/sound/i810_audio.c linux-2.4.27/drivers/sound/i810_audio.c
@@ -99,54 +99,14 @@
#include <linux/spinlock.h>
#include <linux/smp_lock.h>
#include <linux/ac97_codec.h>
+#include <linux/bitops.h>
#include <asm/uaccess.h>
#include <asm/hardirq.h>
-#ifndef PCI_DEVICE_ID_INTEL_82801
-#define PCI_DEVICE_ID_INTEL_82801 0x2415
-#endif
-#ifndef PCI_DEVICE_ID_INTEL_82901
-#define PCI_DEVICE_ID_INTEL_82901 0x2425
-#endif
-#ifndef PCI_DEVICE_ID_INTEL_ICH2
-#define PCI_DEVICE_ID_INTEL_ICH2 0x2445
-#endif
-#ifndef PCI_DEVICE_ID_INTEL_ICH3
-#define PCI_DEVICE_ID_INTEL_ICH3 0x2485
-#endif
-#ifndef PCI_DEVICE_ID_INTEL_ICH4
-#define PCI_DEVICE_ID_INTEL_ICH4 0x24c5
-#endif
-#ifndef PCI_DEVICE_ID_INTEL_ICH5
-#define PCI_DEVICE_ID_INTEL_ICH5 0x24d5
-#endif
-#ifndef PCI_DEVICE_ID_INTEL_ICH6_3
-#define PCI_DEVICE_ID_INTEL_ICH6_3 0x266e
-#endif
-#ifndef PCI_DEVICE_ID_INTEL_440MX
-#define PCI_DEVICE_ID_INTEL_440MX 0x7195
-#endif
-#ifndef PCI_DEVICE_ID_INTEL_ESB_5
-#define PCI_DEVICE_ID_INTEL_ESB_5 0x25a6
-#endif
-#ifndef PCI_DEVICE_ID_SI_7012
-#define PCI_DEVICE_ID_SI_7012 0x7012
-#endif
-#ifndef PCI_DEVICE_ID_NVIDIA_MCP1_AUDIO
-#define PCI_DEVICE_ID_NVIDIA_MCP1_AUDIO 0x01b1
-#endif
-#ifndef PCI_DEVICE_ID_NVIDIA_MCP2_AUDIO
-#define PCI_DEVICE_ID_NVIDIA_MCP2_AUDIO 0x006a
-#endif
-#ifndef PCI_DEVICE_ID_NVIDIA_MCP3_AUDIO
-#define PCI_DEVICE_ID_NVIDIA_MCP3_AUDIO 0x00da
-#endif
-#ifndef PCI_DEVICE_ID_AMD_768_AUDIO
-#define PCI_DEVICE_ID_AMD_768_AUDIO 0x7445
-#endif
-#ifndef PCI_DEVICE_ID_AMD_8111_AC97
-#define PCI_DEVICE_ID_AMD_8111_AC97 0x746d
-#endif
+#define DRIVER_VERSION "1.01"
+
+#define MODULOP2(a, b) ((a) & ((b) - 1))
+#define MASKP2(a, b) ((a) & ~((b) - 1))
static int ftsodell;
static int strict_clocking;
@@ -209,6 +169,7 @@
#define ENUM_ENGINE(PRE,DIG) \
enum { \
+ PRE##_BASE = 0x##DIG##0, /* Base Address */ \
PRE##_BDBAR = 0x##DIG##0, /* Buffer Descriptor list Base Address */ \
PRE##_CIV = 0x##DIG##4, /* Current Index Value */ \
PRE##_LVI = 0x##DIG##5, /* Last Valid Index */ \
@@ -256,8 +217,6 @@
#define INT_GPI (1<<0)
#define INT_MASK (INT_SEC|INT_PRI|INT_MC|INT_PO|INT_PI|INT_MO|INT_NI|INT_GPI)
-#define DRIVER_VERSION "0.24"
-
/* magic numbers to protect our data structures */
#define I810_CARD_MAGIC 0x5072696E /* "Prin" */
#define I810_STATE_MAGIC 0x63657373 /* "cess" */
@@ -323,19 +282,19 @@
};
static struct pci_device_id i810_pci_tbl [] = {
- {PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801,
+ {PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801AA_5,
PCI_ANY_ID, PCI_ANY_ID, 0, 0, ICH82801AA},
- {PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82901,
+ {PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801AB_5,
PCI_ANY_ID, PCI_ANY_ID, 0, 0, ICH82901AB},
{PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_440MX,
PCI_ANY_ID, PCI_ANY_ID, 0, 0, INTEL440MX},
- {PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH2,
+ {PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801BA_4,
PCI_ANY_ID, PCI_ANY_ID, 0, 0, INTELICH2},
- {PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH3,
+ {PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801CA_5,
PCI_ANY_ID, PCI_ANY_ID, 0, 0, INTELICH3},
- {PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH4,
+ {PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801DB_5,
PCI_ANY_ID, PCI_ANY_ID, 0, 0, INTELICH4},
- {PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH5,
+ {PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801EB_5,
PCI_ANY_ID, PCI_ANY_ID, 0, 0, INTELICH5},
{PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_7012,
PCI_ANY_ID, PCI_ANY_ID, 0, 0, SI7012},
@@ -345,13 +304,13 @@
PCI_ANY_ID, PCI_ANY_ID, 0, 0, NVIDIA_NFORCE},
{PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_MCP3_AUDIO,
PCI_ANY_ID, PCI_ANY_ID, 0, 0, NVIDIA_NFORCE},
- {PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_768_AUDIO,
+ {PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_OPUS_7445,
PCI_ANY_ID, PCI_ANY_ID, 0, 0, AMD768},
- {PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_8111_AC97,
+ {PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_8111_AUDIO,
PCI_ANY_ID, PCI_ANY_ID, 0, 0, AMD8111},
{PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ESB_5,
PCI_ANY_ID, PCI_ANY_ID, 0, 0, INTELICH4},
- {PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH6_3,
+ {PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH6_18,
PCI_ANY_ID, PCI_ANY_ID, 0, 0, INTELICH4},
{0,}
@@ -491,8 +450,12 @@
/* extract register offset from codec struct */
#define IO_REG_OFF(codec) (((struct i810_card *) codec->private_data)->ac97_id_map[codec->id])
+#define GET_CIV(port) MODULOP2(inb((port) + OFF_CIV), SG_LEN)
+#define GET_LVI(port) MODULOP2(inb((port) + OFF_LVI), SG_LEN)
+
/* set LVI from CIV */
-#define CIV_TO_LVI(port, off) outb((inb(port+OFF_CIV)+off) & 31, port+OFF_LVI)
+#define CIV_TO_LVI(port, off) \
+ outb(MODULOP2(GET_CIV((port)) + (off), SG_LEN), (port) + OFF_LVI)
static struct i810_card *devs = NULL;
@@ -762,7 +725,7 @@
port_picb = port + OFF_PICB;
do {
- civ = inb(port+OFF_CIV) & 31;
+ civ = GET_CIV(port);
offset = inw(port_picb);
/* Must have a delay here! */
if(offset == 0)
@@ -782,7 +745,7 @@
* that we won't have to worry about the chip still being
* out of sync with reality ;-)
*/
- } while (civ != (inb(port+OFF_CIV) & 31) || offset != inw(port_picb));
+ } while (civ != GET_CIV(port) || offset != inw(port_picb));
return (((civ + 1) * dmabuf->fragsize - (bytes * offset))
% dmabuf->dmasize);
@@ -992,6 +955,7 @@
dmabuf->numfrag = SG_LEN;
dmabuf->fragsize = dmabuf->dmasize/dmabuf->numfrag;
dmabuf->fragsamples = dmabuf->fragsize >> 1;
+ dmabuf->fragshift = ffs(dmabuf->fragsize) - 1;
dmabuf->userfragsize = dmabuf->ossfragsize;
dmabuf->userfrags = dmabuf->dmasize/dmabuf->ossfragsize;
@@ -999,16 +963,12 @@
if(dmabuf->ossmaxfrags == 4) {
fragint = 8;
- dmabuf->fragshift = 2;
} else if (dmabuf->ossmaxfrags == 8) {
fragint = 4;
- dmabuf->fragshift = 3;
} else if (dmabuf->ossmaxfrags == 16) {
fragint = 2;
- dmabuf->fragshift = 4;
} else {
fragint = 1;
- dmabuf->fragshift = 5;
}
/*
* Now set up the ring
@@ -1072,41 +1032,41 @@
{
struct dmabuf *dmabuf = &state->dmabuf;
int x, port;
-
+ int trigger;
+ int count, fragsize;
+ void (*start)(struct i810_state *);
+
+ count = dmabuf->count;
port = state->card->iobase;
- if(rec)
+ if (rec) {
port += dmabuf->read_channel->port;
- else
+ trigger = PCM_ENABLE_INPUT;
+ start = __start_adc;
+ count = dmabuf->dmasize - count;
+ } else {
port += dmabuf->write_channel->port;
+ trigger = PCM_ENABLE_OUTPUT;
+ start = __start_dac;
+ }
+
+ /* Do not process partial fragments. */
+ fragsize = dmabuf->fragsize;
+ if (count < fragsize)
+ return;
- /* if we are currently stopped, then our CIV is actually set to our
- * *last* sg segment and we are ready to wrap to the next. However,
- * if we set our LVI to the last sg segment, then it won't wrap to
- * the next sg segment, it won't even get a start. So, instead, when
- * we are stopped, we set both the LVI value and also we increment
- * the CIV value to the next sg segment to be played so that when
- * we call start_{dac,adc}, things will operate properly
- */
if (!dmabuf->enable && dmabuf->ready) {
- if(rec && dmabuf->count < dmabuf->dmasize &&
- (dmabuf->trigger & PCM_ENABLE_INPUT))
- {
- CIV_TO_LVI(port, 1);
- __start_adc(state);
- while( !(inb(port + OFF_CR) & ((1<<4) | (1<<2))) ) ;
- } else if (!rec && dmabuf->count &&
- (dmabuf->trigger & PCM_ENABLE_OUTPUT))
- {
- CIV_TO_LVI(port, 1);
- __start_dac(state);
- while( !(inb(port + OFF_CR) & ((1<<4) | (1<<2))) ) ;
- }
+ if (!(dmabuf->trigger & trigger))
+ return;
+
+ start(state);
+ while (!(inb(port + OFF_CR) & ((1<<4) | (1<<2))))
+ ;
}
- /* swptr - 1 is the tail of our transfer */
- x = (dmabuf->dmasize + dmabuf->swptr - 1) % dmabuf->dmasize;
- x /= dmabuf->fragsize;
- outb(x, port+OFF_LVI);
+ /* MASKP2(swptr, fragsize) - 1 is the tail of our transfer */
+ x = MODULOP2(MASKP2(dmabuf->swptr, fragsize) - 1, dmabuf->dmasize);
+ x >>= dmabuf->fragshift;
+ outb(x, port + OFF_LVI);
}
static void i810_update_lvi(struct i810_state *state, int rec)
@@ -1126,13 +1086,17 @@
{
struct dmabuf *dmabuf = &state->dmabuf;
unsigned hwptr;
+ unsigned fragmask, dmamask;
int diff;
- /* error handling and process wake up for DAC */
+ fragmask = MASKP2(~0, dmabuf->fragsize);
+ dmamask = MODULOP2(~0, dmabuf->dmasize);
+
+ /* error handling and process wake up for ADC */
if (dmabuf->enable == ADC_RUNNING) {
/* update hardware pointer */
- hwptr = i810_get_dma_addr(state, 1);
- diff = (dmabuf->dmasize + hwptr - dmabuf->hwptr) % dmabuf->dmasize;
+ hwptr = i810_get_dma_addr(state, 1) & fragmask;
+ diff = (hwptr - dmabuf->hwptr) & dmamask;
#if defined(DEBUG_INTERRUPTS) || defined(DEBUG_MMAP)
printk("ADC HWP %d,%d,%d\n", hwptr, dmabuf->hwptr, diff);
#endif
@@ -1144,20 +1108,20 @@
/* this is normal for the end of a read */
/* only give an error if we went past the */
/* last valid sg entry */
- if((inb(state->card->iobase + PI_CIV) & 31) !=
- (inb(state->card->iobase + PI_LVI) & 31)) {
+ if (GET_CIV(state->card->iobase + PI_BASE) !=
+ GET_LVI(state->card->iobase + PI_BASE)) {
printk(KERN_WARNING "i810_audio: DMA overrun on read\n");
dmabuf->error++;
}
}
- if (dmabuf->count > dmabuf->userfragsize)
+ if (diff)
wake_up(&dmabuf->wait);
}
/* error handling and process wake up for DAC */
if (dmabuf->enable == DAC_RUNNING) {
/* update hardware pointer */
- hwptr = i810_get_dma_addr(state, 0);
- diff = (dmabuf->dmasize + hwptr - dmabuf->hwptr) % dmabuf->dmasize;
+ hwptr = i810_get_dma_addr(state, 0) & fragmask;
+ diff = (hwptr - dmabuf->hwptr) & dmamask;
#if defined(DEBUG_INTERRUPTS) || defined(DEBUG_MMAP)
printk("DAC HWP %d,%d,%d\n", hwptr, dmabuf->hwptr, diff);
#endif
@@ -1169,18 +1133,18 @@
/* this is normal for the end of a write */
/* only give an error if we went past the */
/* last valid sg entry */
- if((inb(state->card->iobase + PO_CIV) & 31) !=
- (inb(state->card->iobase + PO_LVI) & 31)) {
+ if (GET_CIV(state->card->iobase + PO_BASE) !=
+ GET_LVI(state->card->iobase + PO_BASE)) {
printk(KERN_WARNING "i810_audio: DMA overrun on write\n");
printk("i810_audio: CIV %d, LVI %d, hwptr %x, "
"count %d\n",
- inb(state->card->iobase + PO_CIV) & 31,
- inb(state->card->iobase + PO_LVI) & 31,
+ GET_CIV(state->card->iobase + PO_BASE),
+ GET_LVI(state->card->iobase + PO_BASE),
dmabuf->hwptr, dmabuf->count);
dmabuf->error++;
}
}
- if (dmabuf->count < (dmabuf->dmasize-dmabuf->userfragsize))
+ if (diff)
wake_up(&dmabuf->wait);
}
}
@@ -1197,7 +1161,6 @@
dmabuf->swptr = dmabuf->hwptr;
}
free = dmabuf->dmasize - dmabuf->count;
- free -= (dmabuf->hwptr % dmabuf->fragsize);
if(free < 0)
return(0);
return(free);
@@ -1215,12 +1178,27 @@
dmabuf->swptr = dmabuf->hwptr;
}
avail = dmabuf->count;
- avail -= (dmabuf->hwptr % dmabuf->fragsize);
if(avail < 0)
return(0);
return(avail);
}
+static inline void fill_partial_frag(struct dmabuf *dmabuf)
+{
+ unsigned fragsize;
+ unsigned swptr, len;
+
+ fragsize = dmabuf->fragsize;
+ swptr = dmabuf->swptr;
+ len = fragsize - MODULOP2(dmabuf->swptr, fragsize);
+ if (len == fragsize)
+ return;
+
+ memset(dmabuf->rawbuf + swptr, '\0', len);
+ dmabuf->swptr = MODULOP2(swptr + len, dmabuf->dmasize);
+ dmabuf->count += len;
+}
+
static int drain_dac(struct i810_state *state, int signals_allowed)
{
DECLARE_WAITQUEUE(wait, current);
@@ -1235,30 +1213,28 @@
stop_dac(state);
return 0;
}
+
+ spin_lock_irqsave(&state->card->lock, flags);
+
+ fill_partial_frag(dmabuf);
+
+ /*
+ * This will make sure that our LVI is correct, that our
+ * pointer is updated, and that the DAC is running. We
+ * have to force the setting of dmabuf->trigger to avoid
+ * any possible deadlocks.
+ */
+ dmabuf->trigger = PCM_ENABLE_OUTPUT;
+ __i810_update_lvi(state, 0);
+
+ spin_unlock_irqrestore(&state->card->lock, flags);
+
add_wait_queue(&dmabuf->wait, &wait);
for (;;) {
spin_lock_irqsave(&state->card->lock, flags);
i810_update_ptr(state);
count = dmabuf->count;
- spin_unlock_irqrestore(&state->card->lock, flags);
-
- if (count <= 0)
- break;
-
- /*
- * This will make sure that our LVI is correct, that our
- * pointer is updated, and that the DAC is running. We
- * have to force the setting of dmabuf->trigger to avoid
- * any possible deadlocks.
- */
- if(!dmabuf->enable) {
- dmabuf->trigger = PCM_ENABLE_OUTPUT;
- i810_update_lvi(state,0);
- }
- if (signal_pending(current) && signals_allowed) {
- break;
- }
/* It seems that we have to set the current state to
* TASK_INTERRUPTIBLE every time to make the process
@@ -1269,7 +1245,17 @@
* instead of actually sleeping and waiting for an
* interrupt to wake us up!
*/
- set_current_state(TASK_INTERRUPTIBLE);
+ __set_current_state(signals_allowed ?
+ TASK_INTERRUPTIBLE : TASK_UNINTERRUPTIBLE);
+ spin_unlock_irqrestore(&state->card->lock, flags);
+
+ if (count <= 0)
+ break;
+
+ if (signal_pending(current) && signals_allowed) {
+ break;
+ }
+
/*
* set the timeout to significantly longer than it *should*
* take for the DAC to drain the DMA buffer
@@ -1350,11 +1336,10 @@
if(status & DMA_INT_DCH)
printk("DCH -");
#endif
- if(dmabuf->enable & DAC_RUNNING)
- count = dmabuf->count;
- else
- count = dmabuf->dmasize - dmabuf->count;
- if(count > 0) {
+ count = dmabuf->count;
+ if(dmabuf->enable & ADC_RUNNING)
+ count = dmabuf->dmasize - count;
+ if (count >= (int)dmabuf->fragsize) {
outb(inb(port+OFF_CR) | 1, port+OFF_CR);
#ifdef DEBUG_INTERRUPTS
printk(" CONTINUE ");
@@ -1417,6 +1402,7 @@
unsigned long flags;
unsigned int swptr;
int cnt;
+ int pending;
DECLARE_WAITQUEUE(waita, current);
#ifdef DEBUG2
@@ -1442,6 +1428,8 @@
return -EFAULT;
ret = 0;
+ pending = 0;
+
add_wait_queue(&dmabuf->wait, &waita);
while (count > 0) {
set_current_state(TASK_INTERRUPTIBLE);
@@ -1455,8 +1443,8 @@
}
continue;
}
- swptr = dmabuf->swptr;
cnt = i810_get_available_read_data(state);
+ swptr = dmabuf->swptr;
// this is to make the copy_to_user simpler below
if(cnt > (dmabuf->dmasize - swptr))
cnt = dmabuf->dmasize - swptr;
@@ -1464,15 +1452,6 @@
if (cnt > count)
cnt = count;
- /* Lop off the last two bits to force the code to always
- * write in full samples. This keeps software that sets
- * O_NONBLOCK but doesn't check the return value of the
- * write call from getting things out of state where they
- * think a full 4 byte sample was written when really only
- * a portion was, resulting in odd sound and stereo
- * hysteresis.
- */
- cnt &= ~0x3;
if (cnt <= 0) {
unsigned long tmo;
/*
@@ -1526,7 +1505,7 @@
goto done;
}
- swptr = (swptr + cnt) % dmabuf->dmasize;
+ swptr = MODULOP2(swptr + cnt, dmabuf->dmasize);
spin_lock_irqsave(&card->lock, flags);
@@ -1535,7 +1514,7 @@
continue;
}
dmabuf->swptr = swptr;
- dmabuf->count -= cnt;
+ pending = dmabuf->count -= cnt;
spin_unlock_irqrestore(&card->lock, flags);
count -= cnt;
@@ -1543,7 +1522,9 @@
ret += cnt;
}
done:
- i810_update_lvi(state,1);
+ pending = dmabuf->dmasize - pending;
+ if (dmabuf->enable || pending >= dmabuf->userfragsize)
+ i810_update_lvi(state, 1);
set_current_state(TASK_RUNNING);
remove_wait_queue(&dmabuf->wait, &waita);
@@ -1560,7 +1541,8 @@
ssize_t ret;
unsigned long flags;
unsigned int swptr = 0;
- int cnt, x;
+ int pending;
+ int cnt;
DECLARE_WAITQUEUE(waita, current);
#ifdef DEBUG2
@@ -1585,6 +1567,8 @@
return -EFAULT;
ret = 0;
+ pending = 0;
+
add_wait_queue(&dmabuf->wait, &waita);
while (count > 0) {
set_current_state(TASK_INTERRUPTIBLE);
@@ -1599,8 +1583,8 @@
continue;
}
- swptr = dmabuf->swptr;
cnt = i810_get_free_write_space(state);
+ swptr = dmabuf->swptr;
/* Bound the maximum size to how much we can copy to the
* dma buffer before we hit the end. If we have more to
* copy then it will get done in a second pass of this
@@ -1615,15 +1599,6 @@
#endif
if (cnt > count)
cnt = count;
- /* Lop off the last two bits to force the code to always
- * write in full samples. This keeps software that sets
- * O_NONBLOCK but doesn't check the return value of the
- * write call from getting things out of state where they
- * think a full 4 byte sample was written when really only
- * a portion was, resulting in odd sound and stereo
- * hysteresis.
- */
- cnt &= ~0x3;
if (cnt <= 0) {
unsigned long tmo;
// There is data waiting to be played
@@ -1668,7 +1643,7 @@
goto ret;
}
- swptr = (swptr + cnt) % dmabuf->dmasize;
+ swptr = MODULOP2(swptr + cnt, dmabuf->dmasize);
spin_lock_irqsave(&state->card->lock, flags);
if (PM_SUSPENDED(card)) {
@@ -1677,19 +1652,16 @@
}
dmabuf->swptr = swptr;
- dmabuf->count += cnt;
+ pending = dmabuf->count += cnt;
count -= cnt;
buffer += cnt;
ret += cnt;
spin_unlock_irqrestore(&state->card->lock, flags);
}
- if (swptr % dmabuf->fragsize) {
- x = dmabuf->fragsize - (swptr % dmabuf->fragsize);
- memset(dmabuf->rawbuf + swptr, '\0', x);
- }
ret:
- i810_update_lvi(state,0);
+ if (dmabuf->enable || pending >= dmabuf->userfragsize)
+ i810_update_lvi(state, 0);
set_current_state(TASK_RUNNING);
remove_wait_queue(&dmabuf->wait, &waita);
@@ -1938,8 +1910,8 @@
}
/* ICH and ICH0 only support 2 channels */
- if ( state->card->pci_id == PCI_DEVICE_ID_INTEL_82801
- || state->card->pci_id == PCI_DEVICE_ID_INTEL_82901)
+ if ( state->card->pci_id == PCI_DEVICE_ID_INTEL_82801AA_5
+ || state->card->pci_id == PCI_DEVICE_ID_INTEL_82801AB_5)
return put_user(2, (int *)arg);
/* Multi-channel support was added with ICH2. Bits in */
@@ -2179,6 +2151,13 @@
#if defined(DEBUG) || defined(DEBUG_MMAP)
printk("SNDCTL_DSP_SETTRIGGER 0x%x\n", val);
#endif
+ /* silently ignore invalid PCM_ENABLE_xxx bits,
+ * like the other drivers do
+ */
+ if (!(file->f_mode & FMODE_READ ))
+ val &= ~PCM_ENABLE_INPUT;
+ if (!(file->f_mode & FMODE_WRITE ))
+ val &= ~PCM_ENABLE_OUTPUT;
if((file->f_mode & FMODE_READ) && !(val & PCM_ENABLE_INPUT) && dmabuf->enable == ADC_RUNNING) {
stop_adc(state);
}
@@ -2186,7 +2165,7 @@
stop_dac(state);
}
dmabuf->trigger = val;
- if((file->f_mode & FMODE_WRITE) && (val & PCM_ENABLE_OUTPUT) && !(dmabuf->enable & DAC_RUNNING)) {
+ if((val & PCM_ENABLE_OUTPUT) && !(dmabuf->enable & DAC_RUNNING)) {
if (!dmabuf->write_channel) {
dmabuf->ready = 0;
dmabuf->write_channel = state->card->alloc_pcm_channel(state->card);
@@ -2202,12 +2181,12 @@
dmabuf->swptr = dmabuf->hwptr;
dmabuf->count = i810_get_free_write_space(state);
dmabuf->swptr = (dmabuf->swptr + dmabuf->count) % dmabuf->dmasize;
- __i810_update_lvi(state, 0);
spin_unlock_irqrestore(&state->card->lock, flags);
- } else
- start_dac(state);
+ }
+ i810_update_lvi(state, 0);
+ start_dac(state);
}
- if((file->f_mode & FMODE_READ) && (val & PCM_ENABLE_INPUT) && !(dmabuf->enable & ADC_RUNNING)) {
+ if((val & PCM_ENABLE_INPUT) && !(dmabuf->enable & ADC_RUNNING)) {
if (!dmabuf->read_channel) {
dmabuf->ready = 0;
dmabuf->read_channel = state->card->alloc_rec_pcm_channel(state->card);
@@ -2471,7 +2450,7 @@
if(file->f_mode & FMODE_READ) {
if((dmabuf->read_channel = card->alloc_rec_pcm_channel(card)) == NULL) {
kfree (card->states[i]);
- card->states[i] = NULL;;
+ card->states[i] = NULL;
return -EBUSY;
}
dmabuf->trigger |= PCM_ENABLE_INPUT;
@@ -2483,7 +2462,7 @@
if(file->f_mode & FMODE_READ)
card->free_pcm_channel(card,dmabuf->read_channel->num);
kfree (card->states[i]);
- card->states[i] = NULL;;
+ card->states[i] = NULL;
return -EBUSY;
}
/* Initialize to 8kHz? What if we don't support 8kHz? */
@@ -2747,6 +2726,26 @@
return i;
}
+static int is_new_ich(u16 pci_id)
+{
+ switch (pci_id) {
+ case PCI_DEVICE_ID_INTEL_82801DB_5:
+ case PCI_DEVICE_ID_INTEL_82801EB_5:
+ case PCI_DEVICE_ID_INTEL_ESB_5:
+ case PCI_DEVICE_ID_INTEL_ICH6_18:
+ return 1;
+ default:
+ break;
+ }
+
+ return 0;
+}
+
+static inline int ich_use_mmio(struct i810_card *card)
+{
+ return is_new_ich(card->pci_id) && card->use_mmio;
+}
+
/**
* i810_ac97_power_up_bus - bring up AC97 link
* @card : ICH audio device to power up
@@ -2796,9 +2795,7 @@
*/
/* see i810_ac97_init for the next 7 lines (jsaw) */
inw(card->ac97base);
- if ((card->pci_id == PCI_DEVICE_ID_INTEL_ICH4 || card->pci_id == PCI_DEVICE_ID_INTEL_ICH5 ||
- card->pci_id == PCI_DEVICE_ID_INTEL_ESB_5 || card->pci_id == PCI_DEVICE_ID_INTEL_ICH6_3)
- && (card->use_mmio)) {
+ if (ich_use_mmio(card)) {
primary_codec_id = (int) readl(card->iobase_mmio + SDM) & 0x3;
printk(KERN_INFO "i810_audio: Primary codec has ID %d\n",
primary_codec_id);
@@ -2819,7 +2816,7 @@
return 1;
}
-static int __init i810_ac97_init(struct i810_card *card)
+static int __devinit i810_ac97_init(struct i810_card *card)
{
int num_ac97 = 0;
int ac97_id;
@@ -2867,9 +2864,7 @@
possible IO channels. Bit 0:1 of SDM then holds the
last codec ID spoken to.
*/
- if ((card->pci_id == PCI_DEVICE_ID_INTEL_ICH4 || card->pci_id == PCI_DEVICE_ID_INTEL_ICH5 ||
- card->pci_id == PCI_DEVICE_ID_INTEL_ESB_5 || card->pci_id == PCI_DEVICE_ID_INTEL_ICH6_3)
- && (card->use_mmio)) {
+ if (ich_use_mmio(card)) {
ac97_id = (int) readl(card->iobase_mmio + SDM) & 0x3;
printk(KERN_INFO "i810_audio: Connection %d with codec id %d\n",
num_ac97, ac97_id);
@@ -3024,7 +3019,7 @@
return num_ac97;
}
-static void __init i810_configure_clocking (void)
+static void __devinit i810_configure_clocking (void)
{
struct i810_card *card;
struct i810_state *state;
@@ -3065,15 +3060,14 @@
goto config_out;
}
dmabuf->count = dmabuf->dmasize;
- CIV_TO_LVI(card->iobase+dmabuf->write_channel->port, 31);
- save_flags(flags);
- cli();
+ CIV_TO_LVI(card->iobase+dmabuf->write_channel->port, -1);
+ local_irq_save(flags);
start_dac(state);
offset = i810_get_dma_addr(state, 0);
mdelay(50);
new_offset = i810_get_dma_addr(state, 0);
stop_dac(state);
- restore_flags(flags);
+ local_irq_restore(flags);
i = new_offset - offset;
#ifdef DEBUG_INTERRUPTS
printk("i810_audio: %d bytes in 50 milliseconds\n", i);
@@ -3097,7 +3091,7 @@
/* install the driver, we do not allocate hardware channel nor DMA buffer now, they are defered
until "ACCESS" time (in prog_dmabuf called by open/read/write/ioctl/mmap) */
-static int __init i810_probe(struct pci_dev *pci_dev, const struct pci_device_id *pci_id)
+static int __devinit i810_probe(struct pci_dev *pci_dev, const struct pci_device_id *pci_id)
{
struct i810_card *card;
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)