* i810 audio patch
@ 2001-12-04 0:20 Nathan Bryant
2001-12-04 4:26 ` Doug Ledford
0 siblings, 1 reply; 56+ messages in thread
From: Nathan Bryant @ 2001-12-04 0:20 UTC (permalink / raw)
To: linux-kernel, dledford
[-- Attachment #1: Type: text/plain, Size: 765 bytes --]
this patch is slightly differerent from the last one i posted.
it's still diffed against 2.4.17pre1. one obvious thinko is fixed, and a
couple lines that looked bad to me have been changed (goto end in
i810_read seems to be necessary to clean up the wait queue unless I'm
mistaken), and I'm no longer reproducing any OOPSes.
however, i am seeing artsd segfault occasionally. this also seems to
happen with the 4Front driver, however, at least if I load 4Front's
module after unloading this patched driver. I'm not sure if this is a
bug in artsd or specific to my setup or something nasty i've done to my
kernel's data structures ;) so maybe somebody else who's still having
problems with 2.4.17pre1 and KDE can take a look and see how it works
for them.
[-- Attachment #2: i810.diff2 --]
[-- Type: text/plain, Size: 13951 bytes --]
--- i810_audio.c.17p1 Mon Dec 3 14:14:40 2001
+++ linux/drivers/sound/i810_audio.c Mon Dec 3 19:06:33 2001
@@ -197,7 +197,7 @@
#define INT_MASK (INT_SEC|INT_PRI|INT_MC|INT_PO|INT_PI|INT_MO|INT_NI|INT_GPI)
-#define DRIVER_VERSION "0.04"
+#define DRIVER_VERSION "0.05b"
/* magic numbers to protect our data structures */
#define I810_CARD_MAGIC 0x5072696E /* "Prin" */
@@ -357,6 +357,10 @@
struct i810_channel *(*alloc_rec_pcm_channel)(struct i810_card *);
struct i810_channel *(*alloc_rec_mic_channel)(struct i810_card *);
void (*free_pcm_channel)(struct i810_card *, int chan);
+
+ /* We have a *very* long init time possibly, so use this to block */
+ /* attempts to open our devices before we are ready (stops oops'es) */
+ int initializing;
};
static struct i810_card *devs = NULL;
@@ -364,32 +368,6 @@
static int i810_open_mixdev(struct inode *inode, struct file *file);
static int i810_ioctl_mixdev(struct inode *inode, struct file *file, unsigned int cmd,
unsigned long arg);
-
-static inline unsigned ld2(unsigned int x)
-{
- unsigned r = 0;
-
- if (x >= 0x10000) {
- x >>= 16;
- r += 16;
- }
- if (x >= 0x100) {
- x >>= 8;
- r += 8;
- }
- if (x >= 0x10) {
- x >>= 4;
- r += 4;
- }
- if (x >= 4) {
- x >>= 2;
- r += 2;
- }
- if (x >= 2)
- r++;
- return r;
-}
-
static u16 i810_ac97_get(struct ac97_codec *dev, u8 reg);
static void i810_ac97_set(struct ac97_codec *dev, u8 reg, u16 data);
@@ -969,14 +947,6 @@
else
port += dmabuf->write_channel->port;
- if(dmabuf->mapped) {
- if(rec)
- dmabuf->swptr = (dmabuf->hwptr + dmabuf->dmasize
- - dmabuf->count) % dmabuf->dmasize;
- else
- dmabuf->swptr = (dmabuf->hwptr + dmabuf->count)
- % dmabuf->dmasize;
- }
/*
* two special cases, count == 0 on write
* means no data, and count == dmasize
@@ -993,7 +963,7 @@
/* swptr - 1 is the tail of our transfer */
x = (dmabuf->dmasize + dmabuf->swptr - 1) % dmabuf->dmasize;
x /= dmabuf->fragsize;
- outb(x&31, port+OFF_LVI);
+ outb(x, port+OFF_LVI);
}
static void i810_update_lvi(struct i810_state *state, int rec)
@@ -1020,7 +990,9 @@
/* update hardware pointer */
hwptr = i810_get_dma_addr(state, 1);
diff = (dmabuf->dmasize + hwptr - dmabuf->hwptr) % dmabuf->dmasize;
-// printk("HWP %d,%d,%d\n", hwptr, dmabuf->hwptr, diff);
+#ifdef DEBUG_INTERRUPTS
+ printk("ADC HWP %d,%d,%d\n", hwptr, dmabuf->hwptr, diff);
+#endif
dmabuf->hwptr = hwptr;
dmabuf->total_bytes += diff;
dmabuf->count += diff;
@@ -1043,7 +1015,9 @@
/* update hardware pointer */
hwptr = i810_get_dma_addr(state, 0);
diff = (dmabuf->dmasize + hwptr - dmabuf->hwptr) % dmabuf->dmasize;
-// printk("HWP %d,%d,%d\n", hwptr, dmabuf->hwptr, diff);
+#ifdef DEBUG_INTERRUPTS
+ printk("DAC HWP %d,%d,%d\n", hwptr, dmabuf->hwptr, diff);
+#endif
dmabuf->hwptr = hwptr;
dmabuf->total_bytes += diff;
dmabuf->count -= diff;
@@ -1068,6 +1042,40 @@
}
}
+static inline int i810_get_free_write_space(struct i810_state *state)
+{
+ struct dmabuf *dmabuf = &state->dmabuf;
+ int free;
+
+ i810_update_ptr(state);
+ // catch underruns during playback
+ if (dmabuf->count < 0) {
+ dmabuf->count = 0;
+ }
+ free = dmabuf->dmasize - dmabuf->count;
+ free -= (dmabuf->hwptr % dmabuf->fragsize);
+ if(free < 0)
+ return(0);
+ return(free);
+}
+
+static inline int i810_get_available_read_data(struct i810_state *state)
+{
+ struct dmabuf *dmabuf = &state->dmabuf;
+ int avail;
+
+ i810_update_ptr(state);
+ // catch overruns during record
+ if (dmabuf->count > dmabuf->dmasize) {
+ dmabuf->count = dmabuf->dmasize;
+ }
+ avail = dmabuf->count;
+ avail -= (dmabuf->hwptr % dmabuf->fragsize);
+ if(avail < 0)
+ return(0);
+ return(avail);
+}
+
static int drain_dac(struct i810_state *state, int nonblock)
{
DECLARE_WAITQUEUE(wait, current);
@@ -1271,10 +1279,7 @@
continue;
}
swptr = dmabuf->swptr;
- if (dmabuf->count > dmabuf->dmasize) {
- dmabuf->count = dmabuf->dmasize;
- }
- cnt = dmabuf->count - dmabuf->fragsize;
+ cnt = i810_get_available_read_data(state);
// this is to make the copy_to_user simpler below
if(cnt > (dmabuf->dmasize - swptr))
cnt = dmabuf->dmasize - swptr;
@@ -1291,7 +1296,7 @@
i810_update_lvi(state,1);
if (file->f_flags & O_NONBLOCK) {
if (!ret) ret = -EAGAIN;
- return ret;
+ goto done;
}
/* This isnt strictly right for the 810 but it'll do */
tmo = (dmabuf->dmasize * HZ) / (dmabuf->rate * 2);
@@ -1315,7 +1320,7 @@
}
if (signal_pending(current)) {
ret = ret ? ret : -ERESTARTSYS;
- return ret;
+ goto done;
}
continue;
}
@@ -1402,10 +1407,7 @@
}
swptr = dmabuf->swptr;
- if (dmabuf->count < 0) {
- dmabuf->count = 0;
- }
- cnt = dmabuf->dmasize - swptr;
+ cnt = i810_get_free_write_space(state);
if(cnt > (dmabuf->dmasize - dmabuf->count))
cnt = dmabuf->dmasize - dmabuf->count;
spin_unlock_irqrestore(&state->card->lock, flags);
@@ -1508,13 +1510,8 @@
mask |= POLLIN | POLLRDNORM;
}
if (file->f_mode & FMODE_WRITE && dmabuf->enable & DAC_RUNNING) {
- if (dmabuf->mapped) {
- if (dmabuf->count >= (signed)dmabuf->fragsize)
- mask |= POLLOUT | POLLWRNORM;
- } else {
- if ((signed)dmabuf->dmasize >= dmabuf->count + (signed)dmabuf->fragsize)
- mask |= POLLOUT | POLLWRNORM;
- }
+ if ((signed)dmabuf->dmasize >= dmabuf->count + (signed)dmabuf->fragsize)
+ mask |= POLLOUT | POLLWRNORM;
}
spin_unlock_irqrestore(&state->card->lock, flags);
@@ -1559,10 +1556,7 @@
size, vma->vm_page_prot))
goto out;
dmabuf->mapped = 1;
- if(vma->vm_flags & VM_WRITE)
- dmabuf->count = dmabuf->dmasize;
- else
- dmabuf->count = 0;
+ dmabuf->count = 0;
ret = 0;
#ifdef DEBUG
printk("i810_audio: mmap'ed %ld bytes of data space\n", size);
@@ -1580,11 +1574,9 @@
audio_buf_info abinfo;
count_info cinfo;
unsigned int i_glob_cnt;
- int val = 0, mapped, ret;
+ int val = 0, ret;
struct ac97_codec *codec = state->card->ac97_codec[0];
- mapped = ((file->f_mode & FMODE_WRITE) && dmabuf->mapped) ||
- ((file->f_mode & FMODE_READ) && dmabuf->mapped);
#ifdef DEBUG
printk("i810_audio: i810_ioctl, arg=0x%x, cmd=", arg ? *(int *)arg : 0);
#endif
@@ -1674,9 +1666,6 @@
#ifdef DEBUG
printk("SNDCTL_DSP_STEREO\n");
#endif
- if (get_user(val, (int *)arg))
- return -EFAULT;
-
if (dmabuf->enable & DAC_RUNNING) {
stop_dac(state);
}
@@ -1820,22 +1809,47 @@
dmabuf->ossfragsize = 1<<(val & 0xffff);
dmabuf->ossmaxfrags = (val >> 16) & 0xffff;
- if (dmabuf->ossmaxfrags <= 4)
- dmabuf->ossmaxfrags = 4;
- else if (dmabuf->ossmaxfrags <= 8)
- dmabuf->ossmaxfrags = 8;
- else if (dmabuf->ossmaxfrags <= 16)
- dmabuf->ossmaxfrags = 16;
- else
- dmabuf->ossmaxfrags = 32;
+ if (!dmabuf->ossfragsize || !dmabuf->ossmaxfrags)
+ return -EINVAL;
+ /*
+ * Bound the frag size into our allowed range of 256 - 4096
+ */
+ if (dmabuf->ossfragsize < 256)
+ dmabuf->ossfragsize = 256;
+ else if (dmabuf->ossfragsize > 4096)
+ dmabuf->ossfragsize = 4096;
+ /*
+ * The numfrags could be something reasonable, or it could
+ * be 0xffff meaning "Give me as much as possible". So,
+ * we check the numfrags * fragsize doesn't exceed our
+ * 64k buffer limit, nor is it less than our 8k minimum.
+ * If it fails either one of these checks, then adjust the
+ * number of fragments, not the size of them. It's OK if
+ * our number of fragments doesn't equal 32 or anything
+ * like our hardware based number now since we are using
+ * a different frag count for the hardware. Before we get
+ * into this though, bound the maxfrags to avoid overflow
+ * issues. A reasonable bound would be 64k / 256 since our
+ * maximum buffer size is 64k and our minimum frag size is
+ * 256. On the other end, our minimum buffer size is 8k and
+ * our maximum frag size is 4k, so the lower bound should
+ * be 2.
+ */
+
+ if(dmabuf->ossmaxfrags > 256)
+ dmabuf->ossmaxfrags = 256;
+ else if (dmabuf->ossmaxfrags < 2)
+ dmabuf->ossmaxfrags = 2;
+
val = dmabuf->ossfragsize * dmabuf->ossmaxfrags;
- if (val < 16384)
- val = 16384;
- if (val > 65536)
- val = 65536;
- dmabuf->ossmaxfrags = val/dmabuf->ossfragsize;
- if(dmabuf->ossmaxfrags<4)
- dmabuf->ossfragsize = val/4;
+ while (val < 8192) {
+ val <<= 1;
+ dmabuf->ossmaxfrags <<= 1;
+ }
+ while (val > 65536) {
+ val >>= 1;
+ dmabuf->ossmaxfrags >>= 1;
+ }
dmabuf->ready = 0;
#ifdef DEBUG
printk("SNDCTL_DSP_SETFRAGMENT 0x%x, %d, %d\n", val,
@@ -1853,10 +1867,10 @@
i810_update_ptr(state);
abinfo.fragsize = dmabuf->userfragsize;
abinfo.fragstotal = dmabuf->userfrags;
- if(dmabuf->mapped)
- abinfo.bytes = dmabuf->count;
- else
- abinfo.bytes = dmabuf->dmasize - dmabuf->fragsize - dmabuf->count;
+ if (dmabuf->mapped)
+ abinfo.bytes = dmabuf->dmasize;
+ else
+ abinfo.bytes = i810_get_free_write_space(state);
abinfo.fragments = abinfo.bytes / dmabuf->userfragsize;
spin_unlock_irqrestore(&state->card->lock, flags);
#ifdef DEBUG
@@ -1871,13 +1885,13 @@
if (!dmabuf->ready && (val = prog_dmabuf(state, 0)) != 0)
return val;
spin_lock_irqsave(&state->card->lock, flags);
- i810_update_ptr(state);
+ val = i810_get_free_write_space(state);
cinfo.bytes = dmabuf->total_bytes;
cinfo.ptr = dmabuf->hwptr;
- cinfo.blocks = (dmabuf->dmasize - dmabuf->count)/dmabuf->userfragsize;
- if (dmabuf->mapped) {
- dmabuf->count = (dmabuf->dmasize -
- (dmabuf->count & (dmabuf->userfragsize-1)));
+ cinfo.blocks = val/dmabuf->userfragsize;
+ if (dmabuf->mapped && dmabuf->enable && DAC_RUNNING) {
+ dmabuf->count += val;
+ dmabuf->swptr = (dmabuf->swptr + val) % dmabuf->dmasize;
__i810_update_lvi(state, 0);
}
spin_unlock_irqrestore(&state->card->lock, flags);
@@ -1893,10 +1907,9 @@
if (!dmabuf->ready && (val = prog_dmabuf(state, 1)) != 0)
return val;
spin_lock_irqsave(&state->card->lock, flags);
- i810_update_ptr(state);
+ abinfo.bytes = i810_get_available_read_data(state);
abinfo.fragsize = dmabuf->userfragsize;
abinfo.fragstotal = dmabuf->userfrags;
- abinfo.bytes = dmabuf->dmasize - dmabuf->count;
abinfo.fragments = abinfo.bytes / dmabuf->userfragsize;
spin_unlock_irqrestore(&state->card->lock, flags);
#ifdef DEBUG
@@ -1911,12 +1924,13 @@
if (!dmabuf->ready && (val = prog_dmabuf(state, 0)) != 0)
return val;
spin_lock_irqsave(&state->card->lock, flags);
- i810_update_ptr(state);
+ val = i810_get_available_read_data(state);
cinfo.bytes = dmabuf->total_bytes;
- cinfo.blocks = dmabuf->count/dmabuf->userfragsize;
+ cinfo.blocks = val/dmabuf->userfragsize;
cinfo.ptr = dmabuf->hwptr;
- if (dmabuf->mapped) {
- dmabuf->count &= (dmabuf->userfragsize-1);
+ if (dmabuf->mapped && dmabuf->enable && ADC_RUNNING) {
+ dmabuf->count -= val;
+ dmabuf->swptr = (dmabuf->swptr + val) % dmabuf->dmasize;
__i810_update_lvi(state, 1);
}
spin_unlock_irqrestore(&state->card->lock, flags);
@@ -1970,8 +1984,12 @@
if (!dmabuf->ready && (ret = prog_dmabuf(state, 0)))
return ret;
if (dmabuf->mapped) {
- dmabuf->count = dmabuf->dmasize;
- i810_update_lvi(state,0);
+ spin_lock_irqsave(&state->card->lock, flags);
+ i810_update_ptr(state);
+ dmabuf->count = 0;
+ dmabuf->count = i810_get_free_write_space(state);
+ __i810_update_lvi(state, 0);
+ spin_unlock_irqrestore(&state->card->lock, flags);
}
if (!dmabuf->enable && dmabuf->count > dmabuf->userfragsize)
start_dac(state);
@@ -1985,10 +2003,6 @@
}
if (!dmabuf->ready && (ret = prog_dmabuf(state, 1)))
return ret;
- if (dmabuf->mapped) {
- dmabuf->count = 0;
- i810_update_lvi(state,1);
- }
if (!dmabuf->enable && dmabuf->count <
(dmabuf->dmasize - dmabuf->userfragsize))
start_adc(state);
@@ -2195,7 +2209,11 @@
/* find an avaiable virtual channel (instance of /dev/dsp) */
while (card != NULL) {
- for (i = 0; i < NR_HW_CH; i++) {
+ for (i = 0; i < 50 && card->initializing; i++) {
+ current->state = TASK_UNINTERRUPTIBLE;
+ schedule_timeout(HZ/20);
+ }
+ for (i = 0; i < NR_HW_CH && !card->initializing; i++) {
if (card->states[i] == NULL) {
state = card->states[i] = (struct i810_state *)
kmalloc(sizeof(struct i810_state), GFP_KERNEL);
@@ -2344,13 +2362,18 @@
int minor = MINOR(inode->i_rdev);
struct i810_card *card = devs;
- for (card = devs; card != NULL; card = card->next)
- for (i = 0; i < NR_AC97; i++)
+ for (card = devs; card != NULL; card = card->next) {
+ for (i = 0; i < 50 && card->initializing; i++) {
+ current->state = TASK_UNINTERRUPTIBLE;
+ schedule_timeout(HZ/20);
+ }
+ for (i = 0; i < NR_AC97 && !card->initializing; i++)
if (card->ac97_codec[i] != NULL &&
card->ac97_codec[i]->dev_mixer == minor) {
file->private_data = card->ac97_codec[i];
return 0;
}
+ }
return -ENODEV;
}
@@ -2696,6 +2719,7 @@
}
memset(card, 0, sizeof(*card));
+ card->initializing = 1;
card->iobase = pci_resource_start (pci_dev, 1);
card->ac97base = pci_resource_start (pci_dev, 0);
card->pci_dev = pci_dev;
@@ -2771,7 +2795,7 @@
kfree(card);
return -ENODEV;
}
-
+ card->initializing = 0;
return 0;
}
@@ -2789,6 +2813,7 @@
if (card->ac97_codec[i] != NULL) {
unregister_sound_mixer(card->ac97_codec[i]->dev_mixer);
kfree (card->ac97_codec[i]);
+ card->ac97_codec[i] = NULL;
}
unregister_sound_dsp(card->dev_audio);
kfree(card);
@@ -2957,9 +2982,6 @@
if(ftsodell != 0) {
printk("i810_audio: ftsodell is now a deprecated option.\n");
}
- if(clocking == 48000) {
- i810_configure_clocking();
- }
if(spdif_locked > 0 ) {
if(spdif_locked == 32000 || spdif_locked == 44100 || spdif_locked == 48000) {
printk("i810_audio: Enabling S/PDIF at sample rate %dHz.\n", spdif_locked);
^ permalink raw reply [flat|nested] 56+ messages in thread* Re: i810 audio patch 2001-12-04 0:20 i810 audio patch Nathan Bryant @ 2001-12-04 4:26 ` Doug Ledford [not found] ` <3C0C58DE.9020703@optonline.net> 0 siblings, 1 reply; 56+ messages in thread From: Doug Ledford @ 2001-12-04 4:26 UTC (permalink / raw) To: Nathan Bryant; +Cc: Linux Kernel Mailing List Nathan Bryant wrote: > this patch is slightly differerent from the last one i posted. > > it's still diffed against 2.4.17pre1. one obvious thinko is fixed, and a > couple lines that looked bad to me have been changed (goto end in > i810_read seems to be necessary to clean up the wait queue unless I'm > mistaken), and I'm no longer reproducing any OOPSes. > > however, i am seeing artsd segfault occasionally. this also seems to > happen with the 4Front driver, however, at least if I load 4Front's > module after unloading this patched driver. I'm not sure if this is a > bug in artsd or specific to my setup or something nasty i've done to my > kernel's data structures ;) so maybe somebody else who's still having > problems with 2.4.17pre1 and KDE can take a look and see how it works > for them. Nathan, thanks for taking the time to merge these. I've got some more stuff here that I've done just recently for ANK, and a few moments of spare time. If you'll send me the last version of the .c file you had, I can probably do a pretty quick merge of everthing together (I need the .c file instead of the patch because I'm not starting from the same source you are). Hopefully, between your efforts and the feedback I've gotten in the last few days, we can send a final version to Marcello for the 2.4 kernel series that actually works well. -- Doug Ledford <dledford@redhat.com> http://people.redhat.com/dledford Please check my web site for aic7xxx updates/answers before e-mailing me about problems ^ permalink raw reply [flat|nested] 56+ messages in thread
[parent not found: <3C0C58DE.9020703@optonline.net>]
* Re: i810 audio patch [not found] ` <3C0C58DE.9020703@optonline.net> @ 2001-12-04 5:18 ` Nathan Bryant 2001-12-04 5:40 ` Doug Ledford 2001-12-04 9:03 ` Alan Cox 0 siblings, 2 replies; 56+ messages in thread From: Nathan Bryant @ 2001-12-04 5:18 UTC (permalink / raw) To: Doug Ledford, Linux Kernel Mailing List Nathan Bryant wrote > - I haven't seen those oopses again either; they may have been caused > by i810_configure_clocking being called twice during the > initialization due to a merging goof on my part... Ok, I spoke too soon. That piece of code couldn't cause the problem, because of the surrounding if (clocking==... So there may be some VM/buffer related problem lurking under the covers still. Originally the oops popped up in kswapd, for me, but I can't trigger it again. ^ permalink raw reply [flat|nested] 56+ messages in thread
* Re: i810 audio patch 2001-12-04 5:18 ` Nathan Bryant @ 2001-12-04 5:40 ` Doug Ledford 2001-12-04 6:07 ` Nathan Bryant ` (2 more replies) 2001-12-04 9:03 ` Alan Cox 1 sibling, 3 replies; 56+ messages in thread From: Doug Ledford @ 2001-12-04 5:40 UTC (permalink / raw) To: Nathan Bryant; +Cc: Linux Kernel Mailing List [-- Attachment #1: Type: text/plain, Size: 1365 bytes --] Nathan Bryant wrote: > Nathan Bryant wrote > >> - I haven't seen those oopses again either; they may have been caused >> by i810_configure_clocking being called twice during the >> initialization due to a merging goof on my part... > > > Ok, I spoke too soon. That piece of code couldn't cause the problem, > because of the surrounding if (clocking==... > > So there may be some VM/buffer related problem lurking under the covers > still. Originally the oops popped up in kswapd, for me, but I can't > trigger it again. > Well, your second version of the file had the merge done right (my code didn't include S/PDIF support or PM support, so those parts were different, but the parts that were the same as my code were done correctly). I'm attaching a patch that bumps the code from your 0.05b to a unified 0.06 and I'm also placing the 0.06 i810_audio.c.gz file on my web site in the same place that I put the 0.05 version. If people could please test this and report problems back, I would like to get this one off my plate (aka, I don't want to hear any more about artsd not working ever again so I want testers to tell me that it's fixed ;-) -- Doug Ledford <dledford@redhat.com> http://people.redhat.com/dledford Please check my web site for aic7xxx updates/answers before e-mailing me about problems [-- Attachment #2: i810_audio-0.06.patch --] [-- Type: text/plain, Size: 6597 bytes --] --- i810_audio.c.05b.orig Tue Dec 4 00:29:18 2001 +++ i810_audio.c.06 Tue Dec 4 00:37:35 2001 @@ -105,7 +105,7 @@ static int ftsodell=0; static int strict_clocking=0; -static unsigned int clocking=48000; +static unsigned int clocking=0; static int spdif_locked=0; //#define DEBUG @@ -197,7 +197,7 @@ #define INT_MASK (INT_SEC|INT_PRI|INT_MC|INT_PO|INT_PI|INT_MO|INT_NI|INT_GPI) -#define DRIVER_VERSION "0.05b" +#define DRIVER_VERSION "0.06" /* magic numbers to protect our data structures */ #define I810_CARD_MAGIC 0x5072696E /* "Prin" */ @@ -358,16 +358,16 @@ struct i810_channel *(*alloc_rec_mic_channel)(struct i810_card *); void (*free_pcm_channel)(struct i810_card *, int chan); - /* We have a *very* long init time possibly, so use this to block */ - /* attempts to open our devices before we are ready (stops oops'es) */ + /* We have a *very* long init time possibly, so use this to block */ + /* attempts to open our devices before we are ready (stops oops'es) */ int initializing; }; static struct i810_card *devs = NULL; static int i810_open_mixdev(struct inode *inode, struct file *file); -static int i810_ioctl_mixdev(struct inode *inode, struct file *file, unsigned int cmd, - unsigned long arg); +static int i810_ioctl_mixdev(struct inode *inode, struct file *file, + unsigned int cmd, unsigned long arg); static u16 i810_ac97_get(struct ac97_codec *dev, u8 reg); static void i810_ac97_set(struct ac97_codec *dev, u8 reg, u16 data); @@ -710,21 +710,27 @@ spin_unlock_irqrestore(&card->lock, flags); } -static void start_adc(struct i810_state *state) +static inline void __start_adc(struct i810_state *state) { struct dmabuf *dmabuf = &state->dmabuf; - struct i810_card *card = state->card; - unsigned long flags; if (dmabuf->count < dmabuf->dmasize && dmabuf->ready && !dmabuf->enable && (dmabuf->trigger & PCM_ENABLE_INPUT)) { - spin_lock_irqsave(&card->lock, flags); dmabuf->enable |= ADC_RUNNING; - outb((1<<4) | (1<<2) | 1, card->iobase + PI_CR); - spin_unlock_irqrestore(&card->lock, flags); + outb((1<<4) | (1<<2) | 1, state->card->iobase + PI_CR); } } +static void start_adc(struct i810_state *state) +{ + struct i810_card *card = state->card; + unsigned long flags; + + spin_lock_irqsave(&card->lock, flags); + __start_adc(state); + spin_unlock_irqrestore(&card->lock, flags); +} + /* stop playback (lock held) */ static inline void __stop_dac(struct i810_state *state) { @@ -750,20 +756,25 @@ spin_unlock_irqrestore(&card->lock, flags); } -static void start_dac(struct i810_state *state) +static inline void __start_dac(struct i810_state *state) { struct dmabuf *dmabuf = &state->dmabuf; - struct i810_card *card = state->card; - unsigned long flags; if (dmabuf->count > 0 && dmabuf->ready && !dmabuf->enable && (dmabuf->trigger & PCM_ENABLE_OUTPUT)) { - spin_lock_irqsave(&card->lock, flags); dmabuf->enable |= DAC_RUNNING; - outb((1<<4) | (1<<2) | 1, card->iobase + PO_CR); - spin_unlock_irqrestore(&card->lock, flags); + outb((1<<4) | (1<<2) | 1, state->card->iobase + PO_CR); } } +static void start_dac(struct i810_state *state) +{ + struct i810_card *card = state->card; + unsigned long flags; + + spin_lock_irqsave(&card->lock, flags); + __start_dac(state); + spin_unlock_irqrestore(&card->lock, flags); +} #define DMABUF_DEFAULTORDER (16-PAGE_SHIFT) #define DMABUF_MINORDER 1 @@ -783,6 +794,8 @@ dmabuf->ossfragsize = (PAGE_SIZE<<DMABUF_DEFAULTORDER)/dmabuf->ossmaxfrags; size = dmabuf->ossfragsize * dmabuf->ossmaxfrags; + if(dmabuf->rawbuf && (PAGE_SIZE << dmabuf->buforder) == size) + return 0; /* alloc enough to satisfy the oss params */ for (order = DMABUF_DEFAULTORDER; order >= DMABUF_MINORDER; order--) { if ( (PAGE_SIZE<<order) > size ) @@ -851,14 +864,19 @@ dmabuf->swptr = dmabuf->hwptr = 0; spin_unlock_irqrestore(&state->card->lock, flags); - /* allocate DMA buffer if not allocated yet */ - if (dmabuf->rawbuf) - dealloc_dmabuf(state); + /* allocate DMA buffer, let alloc_dmabuf determine if we are already + * allocated well enough or if we should replace the current buffer + * (assuming one is already allocated, if it isn't, then allocate it). + */ if ((ret = alloc_dmabuf(state))) return ret; /* FIXME: figure out all this OSS fragment stuff */ /* I did, it now does what it should according to the OSS API. DL */ + /* We may not have realloced our dmabuf, but the fragment size to + * fragment number ratio may have changed, so go ahead and reprogram + * things + */ dmabuf->dmasize = PAGE_SIZE << dmabuf->buforder; dmabuf->numfrag = SG_LEN; dmabuf->fragsize = dmabuf->dmasize/dmabuf->numfrag; @@ -1190,6 +1208,11 @@ if(count > 0) { outb(inb(port+OFF_CR) | 1, port+OFF_CR); } else { + if (dmabuf->enable & DAC_RUNNING) + __stop_dac(state); + if (dmabuf->enable & ADC_RUNNING) + __stop_adc(state); + dmabuf->enable = 0; wake_up(&dmabuf->wait); #ifdef DEBUG_INTERRUPTS printk("DCH - STOP "); @@ -1698,18 +1721,7 @@ #ifdef DEBUG printk("SNDCTL_DSP_SETFMT\n"); #endif - if (get_user(val, (int *)arg)) - return -EFAULT; - - switch ( val ) { - case AFMT_S16_LE: - break; - case AFMT_QUERY: - default: - val = AFMT_S16_LE; - break; - } - return put_user(val, (int *)arg); + return put_user(AFMT_S16_LE, (int *)arg); case SNDCTL_DSP_CHANNELS: #ifdef DEBUG @@ -1889,10 +1901,12 @@ cinfo.bytes = dmabuf->total_bytes; cinfo.ptr = dmabuf->hwptr; cinfo.blocks = val/dmabuf->userfragsize; - if (dmabuf->mapped && dmabuf->enable && DAC_RUNNING) { + if (dmabuf->mapped && dmabuf->trigger && PCM_ENABLE_OUTPUT) { dmabuf->count += val; dmabuf->swptr = (dmabuf->swptr + val) % dmabuf->dmasize; __i810_update_lvi(state, 0); + if (!dmabuf->enable) + __start_dac(state); } spin_unlock_irqrestore(&state->card->lock, flags); #ifdef DEBUG @@ -1928,10 +1942,12 @@ cinfo.bytes = dmabuf->total_bytes; cinfo.blocks = val/dmabuf->userfragsize; cinfo.ptr = dmabuf->hwptr; - if (dmabuf->mapped && dmabuf->enable && ADC_RUNNING) { + if (dmabuf->mapped && dmabuf->trigger && PCM_ENABLE_INPUT) { dmabuf->count -= val; dmabuf->swptr = (dmabuf->swptr + val) % dmabuf->dmasize; __i810_update_lvi(state, 1); + if (!dmabuf->enable) + __start_adc(state); } spin_unlock_irqrestore(&state->card->lock, flags); #ifdef DEBUG @@ -2776,7 +2792,7 @@ } pci_set_drvdata(pci_dev, card); - if(clocking == 48000) { + if(clocking == 0) { i810_configure_clocking(); } ^ permalink raw reply [flat|nested] 56+ messages in thread
* Re: i810 audio patch 2001-12-04 5:40 ` Doug Ledford @ 2001-12-04 6:07 ` Nathan Bryant 2001-12-04 7:08 ` Nathan Bryant 2001-12-04 14:35 ` Mario Mikocevic 2 siblings, 0 replies; 56+ messages in thread From: Nathan Bryant @ 2001-12-04 6:07 UTC (permalink / raw) To: Doug Ledford; +Cc: Linux Kernel Mailing List Doug Ledford wrote: > > Well, your second version of the file had the merge done right (my > code didn't include S/PDIF support or PM support, so those parts were > different, but the parts that were the same as my code were done > correctly). I'm attaching a patch that bumps the code from your 0.05b > to a unified 0.06 and I'm also placing the 0.06 i810_audio.c.gz file > on my web site in the same place that I put the 0.05 version. If > people could please test this and report problems back, I would like > to get this one off my plate (aka, I don't want to hear any more about > artsd not working ever again so I want testers to tell me that it's > fixed ;-) You'll need to do something like add "clocking = 48000;" right before the call to i810_set_dac_rate in i810_configure_clocking() to avoid a divide by zero. ^ permalink raw reply [flat|nested] 56+ messages in thread
* Re: i810 audio patch 2001-12-04 5:40 ` Doug Ledford 2001-12-04 6:07 ` Nathan Bryant @ 2001-12-04 7:08 ` Nathan Bryant 2001-12-04 16:46 ` Doug Ledford 2001-12-04 14:35 ` Mario Mikocevic 2 siblings, 1 reply; 56+ messages in thread From: Nathan Bryant @ 2001-12-04 7:08 UTC (permalink / raw) To: Doug Ledford; +Cc: Linux Kernel Mailing List Doug Ledford wrote: > Well, your second version of the file had the merge done right (my > code didn't include S/PDIF support or PM support, so those parts were > different, but the parts that were the same as my code were done > correctly). I'm attaching a patch that bumps the code from your 0.05b > to a unified 0.06 and I'm also placing the 0.06 i810_audio.c.gz file > on my web site in the same place that I put the 0.05 version. If > people could please test this and report problems back, I would like > to get this one off my plate (aka, I don't want to hear any more about > artsd not working ever again so I want testers to tell me that it's > fixed ;-) Ok, fixed the divide by zero but artsd doesn't quite work with 0.06. almost but not quite.. sound works normally with non-artsd stuff but artsd decides to stop writing because select() never signals that the fd is writeable. it just times out. ^ permalink raw reply [flat|nested] 56+ messages in thread
* Re: i810 audio patch 2001-12-04 7:08 ` Nathan Bryant @ 2001-12-04 16:46 ` Doug Ledford 2001-12-04 20:14 ` Nathan Bryant 0 siblings, 1 reply; 56+ messages in thread From: Doug Ledford @ 2001-12-04 16:46 UTC (permalink / raw) To: Nathan Bryant; +Cc: Linux Kernel Mailing List Nathan Bryant wrote: > Doug Ledford wrote: > >> Well, your second version of the file had the merge done right (my >> code didn't include S/PDIF support or PM support, so those parts were >> different, but the parts that were the same as my code were done >> correctly). I'm attaching a patch that bumps the code from your 0.05b >> to a unified 0.06 and I'm also placing the 0.06 i810_audio.c.gz file >> on my web site in the same place that I put the 0.05 version. If >> people could please test this and report problems back, I would like >> to get this one off my plate (aka, I don't want to hear any more about >> artsd not working ever again so I want testers to tell me that it's >> fixed ;-) > > > Ok, fixed the divide by zero but artsd doesn't quite work with 0.06. > almost but not quite.. sound works normally with non-artsd stuff but > artsd decides to stop writing because select() never signals that the fd > is writeable. it just times out. I fixed the clocking issue in my source. I need more details on the artsd problem though. Does artsd start to work and then stop, or does it never get around to outputting any sound? Also, do you have any of the debugging output turned on (it *drastically* changes the timings in the driver and can make things that normally work fail and vice versa)? -- Doug Ledford <dledford@redhat.com> http://people.redhat.com/dledford Please check my web site for aic7xxx updates/answers before e-mailing me about problems ^ permalink raw reply [flat|nested] 56+ messages in thread
* Re: i810 audio patch 2001-12-04 16:46 ` Doug Ledford @ 2001-12-04 20:14 ` Nathan Bryant 2001-12-04 20:16 ` Doug Ledford 0 siblings, 1 reply; 56+ messages in thread From: Nathan Bryant @ 2001-12-04 20:14 UTC (permalink / raw) To: Doug Ledford; +Cc: Linux Kernel Mailing List Doug Ledford wrote: > I fixed the clocking issue in my source. I need more details on the > artsd problem though. Does artsd start to work and then stop, or does > it never get around to outputting any sound? Also, do you have any of > the debugging output turned on (it *drastically* changes the timings > in the driver and can make things that normally work fail and vice versa)? It works for a while then stops. select() works properly for a while, and then starts returning timeouts. I've tried this with DEBUG both on and off, and also with DEBUG_INTERRUPTS on/off... no difference. I don't see anything too interesting in DEBUG+DEBUG2 output. Select() stops working after the buffer fills up (after 4 seconds with artsd set to 256byte fragments*32) and doesn't start working again after the buffer begins to drain. ^ permalink raw reply [flat|nested] 56+ messages in thread
* Re: i810 audio patch 2001-12-04 20:14 ` Nathan Bryant @ 2001-12-04 20:16 ` Doug Ledford 0 siblings, 0 replies; 56+ messages in thread From: Doug Ledford @ 2001-12-04 20:16 UTC (permalink / raw) To: Nathan Bryant; +Cc: Linux Kernel Mailing List Nathan Bryant wrote: > Doug Ledford wrote: > >> I fixed the clocking issue in my source. I need more details on the >> artsd problem though. Does artsd start to work and then stop, or does >> it never get around to outputting any sound? Also, do you have any of >> the debugging output turned on (it *drastically* changes the timings >> in the driver and can make things that normally work fail and vice >> versa)? > > > It works for a while then stops. select() works properly for a while, > and then starts returning timeouts. > > I've tried this with DEBUG both on and off, and also with > DEBUG_INTERRUPTS on/off... no difference. > > I don't see anything too interesting in DEBUG+DEBUG2 output. Select() > stops working after the buffer fills up (after 4 seconds with artsd set > to 256byte fragments*32) and doesn't start working again after the > buffer begins to drain. > Can you try this again with the 0.07 version I put on my web site about 30 minutes ago? I put code in there to (hopefully) solve this problem. -- Doug Ledford <dledford@redhat.com> http://people.redhat.com/dledford Please check my web site for aic7xxx updates/answers before e-mailing me about problems ^ permalink raw reply [flat|nested] 56+ messages in thread
* Re: i810 audio patch 2001-12-04 5:40 ` Doug Ledford 2001-12-04 6:07 ` Nathan Bryant 2001-12-04 7:08 ` Nathan Bryant @ 2001-12-04 14:35 ` Mario Mikocevic 2001-12-04 19:02 ` Nathan Bryant 2 siblings, 1 reply; 56+ messages in thread From: Mario Mikocevic @ 2001-12-04 14:35 UTC (permalink / raw) To: Doug Ledford; +Cc: Nathan Bryant, Linux Kernel Mailing List Hi, > Well, your second version of the file had the merge done right (my code > didn't include S/PDIF support or PM support, so those parts were > different, but the parts that were the same as my code were done > correctly). I'm attaching a patch that bumps the code from your 0.05b > to a unified 0.06 and I'm also placing the 0.06 i810_audio.c.gz file on > my web site in the same place that I put the 0.05 version. If people > could please test this and report problems back, I would like to get > this one off my plate (aka, I don't want to hear any more about artsd > not working ever again so I want testers to tell me that it's fixed ;-) Umh, problems -> modprobe produced an oops (17-pre2), module is left in init state : # lsmod Module Size Used by i810_audio 19472 1 (initializing) ac97_codec 9632 0 [i810_audio] Intel 810 + AC97 Audio, version 0.06, 15:21:16 Dec 4 2001 PCI: Found IRQ 9 for device 00:1f.5 PCI: Sharing IRQ 9 with 00:1f.3 PCI: Setting latency timer of device 00:1f.5 to 64 i810: Intel ICH2 found at IO 0xef00 and 0xe800, IRQ 9 i810_audio: Audio Controller supports 6 channels. ac97_codec: AC97 Audio codec, id: 0x4144:0x5360 (Analog Devices AD1885) i810_audio: AC'97 codec 0 Unable to map surround DAC's (or DAC's not present), total channels = 2 # ksymoops < oops0 ksymoops 2.4.1 on i686 2.4.17-pre2-mzg2. Options used -V (default) -k /proc/ksyms (default) -l /proc/modules (default) -o /lib/modules/2.4.17-pre2-mzg2/ (default) -m /boot/System.map-2.4.17-pre2-mzg2 (default) Warning: You did not tell me where to find symbol information. I will assume that the log matches the kernel and modules that are running right now and I'll use the default options above for symbol resolution. If the current kernel and/or modules do not match the log, you can get more accurate output by telling me the kernel version and where to find map, modules, ksyms etc. ksymoops -h explains the options. cpu: 0, clocks: 1329057, slice: 664528 ac97_codec: AC97 Audio codec, id: 0x4144:0x5360 (Analog Devices AD1885) CPU: 0 EIP: 0010:[<d08f944e>] Not tainted Using defaults from ksymoops -t elf32-i386 -a i386 EFLAGS: 00010246 eax: 14244000 ebx: 00000000 ecx: 18000004 edx: 00000000 esi: cfe07880 edi: cfe077b0 ebp: 00000000 esp: ce817e90 ds: 0018 es: 0018 ss: 0018 Process modprobe (pid: 727, stackpage=ce817000) Stack: 00000000 cfe07780 0000009c cfe0781c cfea2400 d08fc761 cfe07780 0000bb80 00000180 d08fc60f d08fda60 cfe077b0 cfe07780 cfd96800 d08fd930 cfd96800 d08fd0c7 cfea2400 d08fcc17 d08fd998 d08fdac0 cfea2400 00000000 c01aa55c Call Trace: [<d08fc761>] [<d08fc60f>] [<d08fda60>] [<d08fd930>] [<d08fd0c7>] [<d08fcc17>] [<d08fd998>] [<d08fdac0>] [<c01aa55c>] [<d08fd998>] [<d08fdac0>] [<c01aa5c2>] [<d08fdac0>] [<d08fcd94>] [<d08fdac0>] [<d08fd740>] [<c0117f25>] [<d08fdbd8>] [<d08f9060>] [<c0106f1b>] Code: f7 35 28 d9 8f d0 89 07 8b 07 59 5b 5e 5f 5d c3 89 f6 55 57 >>EIP; d08f944e <[i810_audio]i810_set_dac_rate+9e/b0> <===== Trace; d08fc761 <[i810_audio]i810_configure_clocking+c1/2c0> Trace; d08fc60f <[i810_audio]i810_ac97_init+2bf/350> Trace; d08fda60 <[i810_audio]i810_mixer_fops+0/60> Trace; d08fd930 <[i810_audio]card_names+0/14> Trace; d08fd0c7 <[i810_audio].rodata.end+c/11> Trace; d08fcc17 <[i810_audio]i810_probe+2b7/360> Trace; d08fd998 <[i810_audio]i810_pci_tbl+54/a8> Trace; d08fdac0 <[i810_audio]i810_pci_driver+0/3f> Trace; c01aa55c <pci_announce_device+3c/60> Trace; d08fd998 <[i810_audio]i810_pci_tbl+54/a8> Trace; d08fdac0 <[i810_audio]i810_pci_driver+0/3f> Trace; c01aa5c2 <pci_register_driver+42/60> Trace; d08fdac0 <[i810_audio]i810_pci_driver+0/3f> Trace; d08fcd94 <[i810_audio]i810_init_module+24/a0> Trace; d08fdac0 <[i810_audio]i810_pci_driver+0/3f> Trace; d08fd740 <[i810_audio].LC31+28/40> Trace; c0117f25 <sys_init_module+555/630> Trace; d08fdbd8 <.data.end+d9/????> Trace; d08f9060 <[i810_audio]i810_alloc_pcm_channel+0/4> Trace; c0106f1b <system_call+33/38> Code; d08f944e <[i810_audio]i810_set_dac_rate+9e/b0> 00000000 <_EIP>: Code; d08f944e <[i810_audio]i810_set_dac_rate+9e/b0> <===== 0: f7 35 28 d9 8f d0 div 0xd08fd928,%eax <===== Code; d08f9454 <[i810_audio]i810_set_dac_rate+a4/b0> 6: 89 07 mov %eax,(%edi) Code; d08f9456 <[i810_audio]i810_set_dac_rate+a6/b0> 8: 8b 07 mov (%edi),%eax Code; d08f9458 <[i810_audio]i810_set_dac_rate+a8/b0> a: 59 pop %ecx Code; d08f9459 <[i810_audio]i810_set_dac_rate+a9/b0> b: 5b pop %ebx Code; d08f945a <[i810_audio]i810_set_dac_rate+aa/b0> c: 5e pop %esi Code; d08f945b <[i810_audio]i810_set_dac_rate+ab/b0> d: 5f pop %edi Code; d08f945c <[i810_audio]i810_set_dac_rate+ac/b0> e: 5d pop %ebp Code; d08f945d <[i810_audio]i810_set_dac_rate+ad/b0> f: c3 ret Code; d08f945e <[i810_audio]i810_set_dac_rate+ae/b0> 10: 89 f6 mov %esi,%esi Code; d08f9460 <[i810_audio]i810_set_adc_rate+0/b0> 12: 55 push %ebp Code; d08f9461 <[i810_audio]i810_set_adc_rate+1/b0> 13: 57 push %edi 1 warning issued. Results may not be reliable. -- Mario Mikočević (Mozgy) mozgy at hinet dot hr My favourite FUBAR ... ^ permalink raw reply [flat|nested] 56+ messages in thread
* Re: i810 audio patch 2001-12-04 14:35 ` Mario Mikocevic @ 2001-12-04 19:02 ` Nathan Bryant 2001-12-04 19:21 ` Doug Ledford 0 siblings, 1 reply; 56+ messages in thread From: Nathan Bryant @ 2001-12-04 19:02 UTC (permalink / raw) To: Mario Mikocevic; +Cc: Doug Ledford, Linux Kernel Mailing List Mario Mikocevic wrote: >modprobe produced an oops (17-pre2), module is left in init state : > Yep. In the i810_configure_clocking() function, immediately before the call to i810_set_dac_rate(), add a line "clocking = 48000;" ^ permalink raw reply [flat|nested] 56+ messages in thread
* Re: i810 audio patch 2001-12-04 19:02 ` Nathan Bryant @ 2001-12-04 19:21 ` Doug Ledford 2001-12-04 20:41 ` Nathan Bryant 0 siblings, 1 reply; 56+ messages in thread From: Doug Ledford @ 2001-12-04 19:21 UTC (permalink / raw) To: Nathan Bryant; +Cc: Mario Mikocevic, Linux Kernel Mailing List Nathan Bryant wrote: > Mario Mikocevic wrote: > >> modprobe produced an oops (17-pre2), module is left in init state : >> > Yep. In the i810_configure_clocking() function, immediately before the > call to i810_set_dac_rate(), add a line "clocking = 48000;" > There is a new version of the driver (0.07) on my web site. It has this issue and one other issue fixed (hopefully). The other issue is when using artsd with the 0.06 driver, I had a report that artsd would end up waiting on select forever and never getting woken up. The 0.07 driver changes wait queue and lvi handling in a few strategic places, so it should work. However, it's untested. Reports welcome. Complete c file: http://people.redhat.com/dledford/i810_audio.c.gz -- Doug Ledford <dledford@redhat.com> http://people.redhat.com/dledford Please check my web site for aic7xxx updates/answers before e-mailing me about problems ^ permalink raw reply [flat|nested] 56+ messages in thread
* Re: i810 audio patch 2001-12-04 19:21 ` Doug Ledford @ 2001-12-04 20:41 ` Nathan Bryant 2001-12-04 21:15 ` Doug Ledford 0 siblings, 1 reply; 56+ messages in thread From: Nathan Bryant @ 2001-12-04 20:41 UTC (permalink / raw) To: Doug Ledford; +Cc: Mario Mikocevic, Linux Kernel Mailing List Doug Ledford wrote: > There is a new version of the driver (0.07) on my web site. It has > this issue and one other issue fixed (hopefully). The other issue is > when using artsd with the 0.06 driver, I had a report that artsd would > end up waiting on select forever and never getting woken up. The 0.07 > driver changes wait queue and lvi handling in a few strategic places, > so it should work. However, it's untested. Reports welcome. With 0.07, the kernel goes into an endless sleep as soon as artsd calls select(). I don't think the looping changes to i810_poll are correct... or even necessary? though the userfragsize change is probably appropriate. ^ permalink raw reply [flat|nested] 56+ messages in thread
* Re: i810 audio patch 2001-12-04 20:41 ` Nathan Bryant @ 2001-12-04 21:15 ` Doug Ledford 2001-12-04 21:39 ` Nathan Bryant 2001-12-04 22:29 ` Nathan Bryant 0 siblings, 2 replies; 56+ messages in thread From: Doug Ledford @ 2001-12-04 21:15 UTC (permalink / raw) To: Nathan Bryant; +Cc: Mario Mikocevic, Linux Kernel Mailing List [-- Attachment #1: Type: text/plain, Size: 1113 bytes --] Nathan Bryant wrote: > Doug Ledford wrote: > >> There is a new version of the driver (0.07) on my web site. It has >> this issue and one other issue fixed (hopefully). The other issue is >> when using artsd with the 0.06 driver, I had a report that artsd would >> end up waiting on select forever and never getting woken up. The 0.07 >> driver changes wait queue and lvi handling in a few strategic places, >> so it should work. However, it's untested. Reports welcome. > > > With 0.07, the kernel goes into an endless sleep as soon as artsd calls > select(). I don't think the looping changes to i810_poll are correct... > or even necessary? Probably not. Although I did change it back but then change it in another way. Use the attached patch to back out those changes and let me know if it works (for some reason, I doubt it). > though the userfragsize change is probably appropriate. > -- Doug Ledford <dledford@redhat.com> http://people.redhat.com/dledford Please check my web site for aic7xxx updates/answers before e-mailing me about problems [-- Attachment #2: foo --] [-- Type: text/plain, Size: 1193 bytes --] --- i810_audio.c.07 Tue Dec 4 16:13:39 2001 +++ i810_audio.c.07b Tue Dec 4 16:13:00 2001 @@ -1530,30 +1530,24 @@ struct dmabuf *dmabuf = &state->dmabuf; unsigned long flags; unsigned int mask = 0; - DECLARE_WAITQUEUE(waita, current); + int count; if(!dmabuf->ready) return 0; - add_wait_queue(&dmabuf->wait, &waita); -again: + poll_wait(file, &dmabuf->wait, wait); spin_lock_irqsave(&state->card->lock, flags); i810_update_ptr(state); + count = dmabuf->count; + spin_unlock_irqrestore(&state->card->lock, flags); if (file->f_mode & FMODE_READ && dmabuf->enable & ADC_RUNNING) { - if (dmabuf->count >= (signed)dmabuf->userfragsize) + if (count >= (signed)dmabuf->userfragsize) mask |= POLLIN | POLLRDNORM; } if (file->f_mode & FMODE_WRITE && dmabuf->enable & DAC_RUNNING) { if ((signed)dmabuf->dmasize >= - dmabuf->count + (signed)dmabuf->userfragsize) + count + (signed)dmabuf->userfragsize) mask |= POLLOUT | POLLWRNORM; } - spin_unlock_irqrestore(&state->card->lock, flags); - if (mask == 0) { - poll_wait(file, &dmabuf->wait, wait); - goto again; - } - remove_wait_queue(&dmabuf->wait, &waita); - return mask; } ^ permalink raw reply [flat|nested] 56+ messages in thread
* Re: i810 audio patch 2001-12-04 21:15 ` Doug Ledford @ 2001-12-04 21:39 ` Nathan Bryant 2001-12-04 21:53 ` Nathan Bryant 2001-12-04 22:29 ` Nathan Bryant 1 sibling, 1 reply; 56+ messages in thread From: Nathan Bryant @ 2001-12-04 21:39 UTC (permalink / raw) To: Doug Ledford; +Cc: Mario Mikocevic, Linux Kernel Mailing List Doug Ledford wrote: > Probably not. Although I did change it back but then change it in > another way. Use the attached patch to back out those changes and let > me know if it works (for some reason, I doubt it). Let's see if I'm understanding things here. You made the looping change because of the userfragsize change, correct? The idea being if userfragsize is larger than the hardware's fragsize, we have to wait longer to wake up. Except poll_wait doesn't seem designed to be called this way, at a glance. (Maybe it's possible to muck around with the poll table and call again, as a hack? but this seems ugly, have to be very careful that calling poll_wait twice doesn't corrupt memory, though, as implied in some of the notes on http://linux24.sourceforge.net/) fs/select.c:do_poll() calls schedule_timeout() after all do_pollfd's have returned empty sets and there is still time remaining. so if you just eliminate the loop in i810_poll, it will loop back and if there's data available, poll(2) would return properly, but with extra latency. i assume sys_select behaves the same way... so, 2 choices to eliminate latency, either hack i810_poll further, or be a lot more intelligent about calling wake_up. am i wrong? ^ permalink raw reply [flat|nested] 56+ messages in thread
* Re: i810 audio patch 2001-12-04 21:39 ` Nathan Bryant @ 2001-12-04 21:53 ` Nathan Bryant 0 siblings, 0 replies; 56+ messages in thread From: Nathan Bryant @ 2001-12-04 21:53 UTC (permalink / raw) To: Linux Kernel Mailing List; +Cc: Doug Ledford, Mario Mikocevic ok, i'm learning here ;) it seems i guessed wrong, and schedule() wakes up on a wait queue which has been added by poll_wait; poll_wait doesn't actually do any sleeping so no loop is necessary in i810_poll; it will be called again by do_poll or do_select after the call to schedule. so no latency and no problem. right? Nathan Bryant wrote: > fs/select.c:do_poll() calls schedule_timeout() after all do_pollfd's > have returned empty sets and there is still time remaining. so if you > just eliminate the loop in i810_poll, it will loop back and if there's > data available, poll(2) would return properly, but with extra latency. > i assume sys_select behaves the same way... > > so, 2 choices to eliminate latency, either hack i810_poll further, or > be a lot more intelligent about calling wake_up. am i wrong? > ^ permalink raw reply [flat|nested] 56+ messages in thread
* Re: i810 audio patch 2001-12-04 21:15 ` Doug Ledford 2001-12-04 21:39 ` Nathan Bryant @ 2001-12-04 22:29 ` Nathan Bryant 2001-12-04 22:49 ` Nathan Bryant 2001-12-04 23:05 ` Doug Ledford 1 sibling, 2 replies; 56+ messages in thread From: Nathan Bryant @ 2001-12-04 22:29 UTC (permalink / raw) To: Doug Ledford; +Cc: Mario Mikocevic, Linux Kernel Mailing List Doug Ledford wrote: > Probably not. Although I did change it back but then change it in > another way. Use the attached patch to back out those changes and let > me know if it works (for some reason, I doubt it). Fascinating... Your patch to i810_poll fixes the sleep of death. and with the rest of the patches in 0.07, select() works a lot better but still not perfectly. xmms+artsd is likely to play sound for quite a while, *until* I do something that causes another process to be scheduled, like click on the Mozilla window that's sitting in the background. At that point, it reverts to the behavior where select() doesn't return properly. And stays that way. this may be due to an output underrun... or i suppose lost interrupt is also possible. i think it might be wise to use get_available_read_data/get_free_write_space from i810_poll instead of dmabuf->count directly. i'll try this and see if it works... ^ permalink raw reply [flat|nested] 56+ messages in thread
* Re: i810 audio patch 2001-12-04 22:29 ` Nathan Bryant @ 2001-12-04 22:49 ` Nathan Bryant 2001-12-04 23:09 ` Doug Ledford 2001-12-04 23:05 ` Doug Ledford 1 sibling, 1 reply; 56+ messages in thread From: Nathan Bryant @ 2001-12-04 22:49 UTC (permalink / raw) To: Nathan Bryant; +Cc: Doug Ledford, Mario Mikocevic, Linux Kernel Mailing List Nathan Bryant wrote: > this may be due to an output underrun... or i suppose lost interrupt > is also possible. > > i think it might be wise to use > get_available_read_data/get_free_write_space from i810_poll instead of > dmabuf->count directly. i'll try this and see if it works... No good. I tried the following, thinking that the underrun handling in get_free_write_space would help, but it does the same thing. What interrupt do we get upon underrun, are we dropping the dmabuf->enable or DAC_RUNNING state when that happens? -- static unsigned int i810_poll(struct file *file, struct poll_table_struct *wait){ struct i810_state *state = (struct i810_state *)file->private_data; struct dmabuf *dmabuf = &state->dmabuf; unsigned long flags; unsigned int mask = 0; int count; if(!dmabuf->ready) return 0; poll_wait(file, &dmabuf->wait, wait); spin_lock_irqsave(&state->card->lock, flags); if (file->f_mode & FMODE_READ && dmabuf->enable & ADC_RUNNING) { count = i810_get_available_read_data(state); if (count >= (signed)dmabuf->userfragsize) mask |= POLLIN | POLLRDNORM; } if (file->f_mode & FMODE_WRITE && dmabuf->enable & DAC_RUNNING) { count = i810_get_free_write_space(state); if (count >= (signed)dmabuf->userfragsize) mask |= POLLOUT | POLLWRNORM; } spin_unlock_irqrestore(&state->card->lock, flags); return mask; } ^ permalink raw reply [flat|nested] 56+ messages in thread
* Re: i810 audio patch 2001-12-04 22:49 ` Nathan Bryant @ 2001-12-04 23:09 ` Doug Ledford 2001-12-04 23:31 ` Nathan Bryant 0 siblings, 1 reply; 56+ messages in thread From: Doug Ledford @ 2001-12-04 23:09 UTC (permalink / raw) To: Nathan Bryant; +Cc: Mario Mikocevic, Linux Kernel Mailing List Nathan Bryant wrote: > Nathan Bryant wrote: > >> this may be due to an output underrun... or i suppose lost interrupt >> is also possible. >> >> i think it might be wise to use >> get_available_read_data/get_free_write_space from i810_poll instead of >> dmabuf->count directly. i'll try this and see if it works... > > > No good. I tried the following, thinking that the underrun handling in > get_free_write_space would help, but it does the same thing. > > What interrupt do we get upon underrun, are we dropping the > dmabuf->enable or DAC_RUNNING state when that happens? Yes, on underrun the DAC is stopped and dmabuf->enable is cleared. That's clearly a bug in this case. However, it should only cause your problem if you are in fact getting an underrun. Anyway, here's a proposed fix you can try to see if that's what's causing the problem: > -- > > static unsigned int i810_poll(struct file *file, struct > poll_table_struct *wait){ > struct i810_state *state = (struct i810_state *)file->private_data; > struct dmabuf *dmabuf = &state->dmabuf; > unsigned long flags; > unsigned int mask = 0; > int count; > > if(!dmabuf->ready) > return 0; > poll_wait(file, &dmabuf->wait, wait); > spin_lock_irqsave(&state->card->lock, flags); > if (file->f_mode & FMODE_READ && dmabuf->enable & ADC_RUNNING) { if (file->f_mode & FMODE_READ && ((dmabuf->enable & ADC_RUNNING) || (dmabuf->trigger & PCM_ENABLE_INPUT))) { > count = i810_get_available_read_data(state); > if (count >= (signed)dmabuf->userfragsize) > mask |= POLLIN | POLLRDNORM; > } > if (file->f_mode & FMODE_WRITE && dmabuf->enable & DAC_RUNNING) { if (file->f_mode & FMODE_WRITE &&((dmabuf->enable & DAC_RUNNING) || (dmabuf->trigger & PCM_ENABLE_OUTPUT))) { > count = i810_get_free_write_space(state); > if (count >= (signed)dmabuf->userfragsize) > mask |= POLLOUT | POLLWRNORM; > } > spin_unlock_irqrestore(&state->card->lock, flags); > return mask; > } > -- Doug Ledford <dledford@redhat.com> http://people.redhat.com/dledford Please check my web site for aic7xxx updates/answers before e-mailing me about problems ^ permalink raw reply [flat|nested] 56+ messages in thread
* Re: i810 audio patch 2001-12-04 23:09 ` Doug Ledford @ 2001-12-04 23:31 ` Nathan Bryant 2001-12-04 23:44 ` Doug Ledford 0 siblings, 1 reply; 56+ messages in thread From: Nathan Bryant @ 2001-12-04 23:31 UTC (permalink / raw) To: Doug Ledford; +Cc: Mario Mikocevic, Linux Kernel Mailing List Doug Ledford wrote: > Yes, on underrun the DAC is stopped and dmabuf->enable is cleared. > That's clearly a bug in this case. However, it should only cause your > problem if you are in fact getting an underrun. Anyway, here's a > proposed fix you can try to see if that's what's causing the problem: [snip] That works. ^ permalink raw reply [flat|nested] 56+ messages in thread
* Re: i810 audio patch 2001-12-04 23:31 ` Nathan Bryant @ 2001-12-04 23:44 ` Doug Ledford 2001-12-05 1:26 ` Nathan Bryant 0 siblings, 1 reply; 56+ messages in thread From: Doug Ledford @ 2001-12-04 23:44 UTC (permalink / raw) To: Nathan Bryant; +Cc: Mario Mikocevic, Linux Kernel Mailing List Nathan Bryant wrote: > Doug Ledford wrote: > >> Yes, on underrun the DAC is stopped and dmabuf->enable is cleared. >> That's clearly a bug in this case. However, it should only cause your >> problem if you are in fact getting an underrun. Anyway, here's a >> proposed fix you can try to see if that's what's causing the problem: > > > [snip] > > That works. OK, good. I've fixed another bug related to MMAPed stuff (for the people that like to play Quake on these sound cards). I've put up a 0.08 version of the file on my web page. If people could please verify that this version works for them I would appreciate it. Once I've gotten a few "It works here" reports and no "It blew my computer up" reports, I'll submit it to Marcello and Linus so we can finally get these things working a bit more reliably. Highlights of this release: Fix GETOPTR and GETIPTR (thinko/typo in an if statement) Fix i810_poll() (side effect of fixing overrun/underrun handling in 0.06) Make handling of dmabuf->trigger more consistent throughout the source code http://people.redhat.com/dledford/i810_audio.c.gz -- Doug Ledford <dledford@redhat.com> http://people.redhat.com/dledford Please check my web site for aic7xxx updates/answers before e-mailing me about problems ^ permalink raw reply [flat|nested] 56+ messages in thread
* Re: i810 audio patch 2001-12-04 23:44 ` Doug Ledford @ 2001-12-05 1:26 ` Nathan Bryant 2001-12-05 2:48 ` Nathan Bryant 0 siblings, 1 reply; 56+ messages in thread From: Nathan Bryant @ 2001-12-05 1:26 UTC (permalink / raw) To: Doug Ledford; +Cc: Mario Mikocevic, Linux Kernel Mailing List Doug Ledford wrote: > OK, good. I've fixed another bug related to MMAPed stuff (for the > people that like to play Quake on these sound cards). I've put up a > 0.08 version of the file on my web page. If people could please > verify that this version works for them I would appreciate it. Once > I've gotten a few "It works here" reports and no "It blew my computer > up" reports, I'll submit it to Marcello and Linus so we can finally > get these things working a bit more reliably. artsd works in 0.08 glquake.glx doesn't: "i810_audio: drain_dac, dma timeout?" ^ permalink raw reply [flat|nested] 56+ messages in thread
* Re: i810 audio patch 2001-12-05 1:26 ` Nathan Bryant @ 2001-12-05 2:48 ` Nathan Bryant 2001-12-05 3:05 ` Doug Ledford 0 siblings, 1 reply; 56+ messages in thread From: Nathan Bryant @ 2001-12-05 2:48 UTC (permalink / raw) To: Nathan Bryant; +Cc: Doug Ledford, Mario Mikocevic, Linux Kernel Mailing List Nathan Bryant wrote: > glquake.glx doesn't: "i810_audio: drain_dac, dma timeout?" Turns out this has been broken for a while; stock 2.4.17pre1 has a broken mmap too... ^ permalink raw reply [flat|nested] 56+ messages in thread
* Re: i810 audio patch 2001-12-05 2:48 ` Nathan Bryant @ 2001-12-05 3:05 ` Doug Ledford 2001-12-05 3:28 ` Nathan Bryant 0 siblings, 1 reply; 56+ messages in thread From: Doug Ledford @ 2001-12-05 3:05 UTC (permalink / raw) To: Nathan Bryant; +Cc: Mario Mikocevic, Linux Kernel Mailing List [-- Attachment #1: Type: text/plain, Size: 544 bytes --] Nathan Bryant wrote: > Nathan Bryant wrote: > >> glquake.glx doesn't: "i810_audio: drain_dac, dma timeout?" > > > Turns out this has been broken for a while; stock 2.4.17pre1 has a > broken mmap too... > Two questions: 1) This is a timeout on close. Does it work up until then? 2) Does the attached patch (against the 0.08 driver) help? -- Doug Ledford <dledford@redhat.com> http://people.redhat.com/dledford Please check my web site for aic7xxx updates/answers before e-mailing me about problems [-- Attachment #2: foo --] [-- Type: text/plain, Size: 3129 bytes --] --- i810_audio.c.08 Tue Dec 4 18:43:22 2001 +++ i810_audio.c.08b Tue Dec 4 22:04:05 2001 @@ -664,26 +664,26 @@ return offset; } -//static void resync_dma_ptrs(struct i810_state *state, int rec) -//{ -// struct dmabuf *dmabuf = &state->dmabuf; -// struct i810_channel *c; -// int offset; -// -// if(rec) { -// c = dmabuf->read_channel; -// } else { -// c = dmabuf->write_channel; -// } -// if(c==NULL) -// return; -// offset = inb(state->card->iobase+c->port+OFF_CIV); -// if(offset == inb(state->card->iobase+c->port+OFF_LVI)) -// offset++; -// offset *= dmabuf->fragsize; -// -// dmabuf->hwptr=dmabuf->swptr = offset; -//} +static void resync_dma_ptrs(struct i810_state *state, int rec) +{ + struct dmabuf *dmabuf = &state->dmabuf; + struct i810_channel *c; + int offset; + + if(rec) { + c = dmabuf->read_channel; + } else { + c = dmabuf->write_channel; + } + if(c==NULL) + return; + offset = inb(state->card->iobase+c->port+OFF_CIV); + if(offset == inb(state->card->iobase+c->port+OFF_LVI)) + offset++; + offset *= dmabuf->fragsize; + + dmabuf->hwptr=dmabuf->swptr = offset; +} /* Stop recording (lock held) */ static inline void __stop_adc(struct i810_state *state) @@ -1094,13 +1094,13 @@ return(avail); } -static int drain_dac(struct i810_state *state, int nonblock) +static int drain_dac(struct i810_state *state) { DECLARE_WAITQUEUE(wait, current); struct dmabuf *dmabuf = &state->dmabuf; unsigned long flags; unsigned long tmo; - int count; + int count, timeout=0; if (!dmabuf->ready) return 0; @@ -1119,30 +1119,29 @@ if (count <= 0) break; - if (signal_pending(current)) - break; - - i810_update_lvi(state,0); if (dmabuf->enable != DAC_RUNNING) start_dac(state); - if (nonblock) { - remove_wait_queue(&dmabuf->wait, &wait); - set_current_state(TASK_RUNNING); - return -EBUSY; - } + if (signal_pending(current)) + break; - tmo = (dmabuf->dmasize * HZ) / dmabuf->rate; - tmo >>= 1; + /* set the timeout to exactly twice as long as it *should* + * take for the DAC to drain the DMA buffer + */ + tmo = (count * HZ * 2) / dmabuf->rate; if (!schedule_timeout(tmo ? tmo : 1) && tmo){ printk(KERN_ERR "i810_audio: drain_dac, dma timeout?\n"); + timeout = 1; break; } } - stop_dac(state); - synchronize_irq(); remove_wait_queue(&dmabuf->wait, &wait); set_current_state(TASK_RUNNING); + if(count <= 0 || timeout) { + stop_dac(state); + synchronize_irq(); + resync_dma_ptrs(state, 0 /* record channel */); + } if (signal_pending(current)) return -ERESTARTSYS; @@ -1651,7 +1650,7 @@ #endif if (dmabuf->enable != DAC_RUNNING || file->f_flags & O_NONBLOCK) return 0; - drain_dac(state, 0); + drain_dac(state); dmabuf->ready = 0; dmabuf->swptr = dmabuf->hwptr = 0; dmabuf->count = dmabuf->total_bytes = 0; @@ -2324,7 +2323,7 @@ /* stop DMA state machine and free DMA buffers/channels */ if(dmabuf->enable & DAC_RUNNING || (dmabuf->count && (dmabuf->trigger & PCM_ENABLE_OUTPUT))) { - drain_dac(state,0); + drain_dac(state); } if(dmabuf->enable & ADC_RUNNING) { stop_adc(state); ^ permalink raw reply [flat|nested] 56+ messages in thread
* Re: i810 audio patch 2001-12-05 3:05 ` Doug Ledford @ 2001-12-05 3:28 ` Nathan Bryant 2001-12-05 4:25 ` Doug Ledford 2001-12-05 4:41 ` Nathan Bryant 0 siblings, 2 replies; 56+ messages in thread From: Nathan Bryant @ 2001-12-05 3:28 UTC (permalink / raw) To: Doug Ledford; +Cc: Mario Mikocevic, Linux Kernel Mailing List Doug Ledford wrote: > Two questions: > > 1) This is a timeout on close. Does it work up until then? no - no audible output. (quake doesn't use SNDCTL_DSP_SYNC anywhere either so it would have to be on close) > > > 2) Does the attached patch (against the 0.08 driver) help? No - timeout printk still occurs ^ permalink raw reply [flat|nested] 56+ messages in thread
* Re: i810 audio patch 2001-12-05 3:28 ` Nathan Bryant @ 2001-12-05 4:25 ` Doug Ledford 2001-12-05 5:14 ` Nathan Bryant 2001-12-05 4:41 ` Nathan Bryant 1 sibling, 1 reply; 56+ messages in thread From: Doug Ledford @ 2001-12-05 4:25 UTC (permalink / raw) To: Nathan Bryant; +Cc: Mario Mikocevic, Linux Kernel Mailing List [-- Attachment #1: Type: text/plain, Size: 733 bytes --] Nathan Bryant wrote: > Doug Ledford wrote: > >> Two questions: >> >> 1) This is a timeout on close. Does it work up until then? > > > no - no audible output. (quake doesn't use SNDCTL_DSP_SYNC anywhere > either so it would have to be on close) > >> >> >> 2) Does the attached patch (against the 0.08 driver) help? > > > No - timeout printk still occurs > A few more tweaks to the mmap code. This might actually work. It should apply cleanly on top of what you already have. Let me know if it enables Quake sound... -- Doug Ledford <dledford@redhat.com> http://people.redhat.com/dledford Please check my web site for aic7xxx updates/answers before e-mailing me about problems [-- Attachment #2: foo2 --] [-- Type: text/plain, Size: 1720 bytes --] --- i810_audio.c.08b Tue Dec 4 22:04:05 2001 +++ i810_audio.c.08c Tue Dec 4 23:24:16 2001 @@ -2005,7 +2005,7 @@ stop_dac(state); } dmabuf->trigger = val; - if(val & PCM_ENABLE_OUTPUT) { + 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); @@ -2017,15 +2017,18 @@ if (dmabuf->mapped) { spin_lock_irqsave(&state->card->lock, flags); i810_update_ptr(state); + resync_dma_ptrs(state,0); dmabuf->count = 0; 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); } - if (!dmabuf->enable && dmabuf->count > dmabuf->userfragsize) + if (dmabuf->count > dmabuf->userfragsize || + dmabuf->mapped) start_dac(state); } - if(val & PCM_ENABLE_INPUT) { + 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); @@ -2034,9 +2037,15 @@ } if (!dmabuf->ready && (ret = prog_dmabuf(state, 1))) return ret; - if (!dmabuf->enable && dmabuf->count < - (dmabuf->dmasize - dmabuf->userfragsize)) - start_adc(state); + if (dmabuf->mapped) { + spin_lock_irqsave(&state->card->lock, flags); + i810_update_ptr(state); + resync_dma_ptrs(state,0); + dmabuf->count = 0; + spin_unlock_irqrestore(&state->card->lock, flags); + } + i810_update_lvi(state, 1); + start_adc(state); } return 0; ^ permalink raw reply [flat|nested] 56+ messages in thread
* Re: i810 audio patch 2001-12-05 4:25 ` Doug Ledford @ 2001-12-05 5:14 ` Nathan Bryant 2001-12-05 5:23 ` Doug Ledford 0 siblings, 1 reply; 56+ messages in thread From: Nathan Bryant @ 2001-12-05 5:14 UTC (permalink / raw) To: Doug Ledford; +Cc: Mario Mikocevic, Linux Kernel Mailing List Doug Ledford wrote: > A few more tweaks to the mmap code. This might actually work. It > should apply cleanly on top of what you already have. Let me know if > it enables Quake sound... No still silence, and debug output is weirder. (still using only DEBUG_INTERRUPTS) Intel 810 + AC97 Audio, version 0.07, 00:07:49 Dec 5 2001 PCI: Setting latency timer of device 00:1f.5 to 64 i810: Intel ICH 82801AA found at IO 0x2400 and 0x2000, IRQ 17 i810_audio: Audio Controller supports 2 channels. ac97_codec: AC97 Audio codec, id: 0x4144:0x5360 (Analog Devices AD1885) i810_audio: AC'97 codec 0 Unable to map surround DAC's (or DAC's not present), total channels = 2 i810_audio: setting clocking to 41231 NVRM: AGPGART: allocated 257 pages NVRM: AGPGART: allocated 128 pages CHANNEL NUM 1 PORT 10 IRQ ( ST7 DAC HWP 2048,2048,0 LVI DAC HWP 2048,2048,0 ) cdrom: open failed. VFS: Disk change detected on device ide1(22,0) DAC HWP 2048,2048,0 DAC HWP 2048,2048,0 DAC HWP 2048,2048,0 [a few hundred of the above line] DAC HWP 2048,2048,0 NVRM: AGPGART: freed 128 pages NVRM: AGPGART: freed 257 pages DAC HWP 2048,2048,0 i810_audio: drain_dac, dma timeout? ^ permalink raw reply [flat|nested] 56+ messages in thread
* Re: i810 audio patch 2001-12-05 5:14 ` Nathan Bryant @ 2001-12-05 5:23 ` Doug Ledford 2001-12-05 20:04 ` Nathan Bryant 0 siblings, 1 reply; 56+ messages in thread From: Doug Ledford @ 2001-12-05 5:23 UTC (permalink / raw) To: Nathan Bryant; +Cc: Mario Mikocevic, Linux Kernel Mailing List [-- Attachment #1: Type: text/plain, Size: 688 bytes --] Nathan Bryant wrote: > Doug Ledford wrote: > >> A few more tweaks to the mmap code. This might actually work. It >> should apply cleanly on top of what you already have. Let me know if >> it enables Quake sound... > > > No still silence, and debug output is weirder. (still using only > DEBUG_INTERRUPTS) The attached patch should get me the debugging output I need to solve the problem. If you'll get me the output, then I can likely have a working version in short order. -- Doug Ledford <dledford@redhat.com> http://people.redhat.com/dledford Please check my web site for aic7xxx updates/answers before e-mailing me about problems [-- Attachment #2: foo3 --] [-- Type: text/plain, Size: 4500 bytes --] --- i810_audio.c.08c Tue Dec 4 23:24:16 2001 +++ i810_audio.c.09 Wed Dec 5 00:19:23 2001 @@ -1,3 +1,4 @@ + /* * Intel i810 and friends ICH driver for Linux * Alan Cox <alan@redhat.com> @@ -111,6 +112,7 @@ //#define DEBUG //#define DEBUG2 //#define DEBUG_INTERRUPTS +#define DEBUG_MMAP #define ADC_RUNNING 1 #define DAC_RUNNING 2 @@ -197,7 +199,7 @@ #define INT_MASK (INT_SEC|INT_PRI|INT_MC|INT_PO|INT_PI|INT_MO|INT_NI|INT_GPI) -#define DRIVER_VERSION "0.07" +#define DRIVER_VERSION "0.09" /* magic numbers to protect our data structures */ #define I810_CARD_MAGIC 0x5072696E /* "Prin" */ @@ -968,7 +970,7 @@ /* * two special cases, count == 0 on write * means no data, and count == dmasize - * means no data on read, handle appropriately + * means no data on read, handle appropriately. */ if(!rec && dmabuf->count == 0) { outb(inb(port+OFF_CIV),port+OFF_LVI); @@ -1008,7 +1010,7 @@ /* update hardware pointer */ hwptr = i810_get_dma_addr(state, 1); diff = (dmabuf->dmasize + hwptr - dmabuf->hwptr) % dmabuf->dmasize; -#ifdef DEBUG_INTERRUPTS +#if defined(DEBUG_INTERRUPTS) || defined(DEBUG_MMAP) printk("ADC HWP %d,%d,%d\n", hwptr, dmabuf->hwptr, diff); #endif dmabuf->hwptr = hwptr; @@ -1033,7 +1035,7 @@ /* update hardware pointer */ hwptr = i810_get_dma_addr(state, 0); diff = (dmabuf->dmasize + hwptr - dmabuf->hwptr) % dmabuf->dmasize; -#ifdef DEBUG_INTERRUPTS +#if defined(DEBUG_INTERRUPTS) || defined(DEBUG_MMAP) printk("DAC HWP %d,%d,%d\n", hwptr, dmabuf->hwptr, diff); #endif dmabuf->hwptr = hwptr; @@ -1168,11 +1170,11 @@ if(!state->dmabuf.ready) continue; dmabuf = &state->dmabuf; - if(dmabuf->enable & DAC_RUNNING) + if(dmabuf->enable & DAC_RUNNING) { c=dmabuf->write_channel; - else if(dmabuf->enable & ADC_RUNNING) + } else if(dmabuf->enable & ADC_RUNNING) { c=dmabuf->read_channel; - else /* This can occur going from R/W to close */ + } else /* This can occur going from R/W to close */ continue; port+=c->port; @@ -1596,7 +1598,7 @@ dmabuf->count = 0; dmabuf->trigger = 0; ret = 0; -#ifdef DEBUG +#ifdef DEBUG_MMAP printk("i810_audio: mmap'ed %ld bytes of data space\n", size); #endif out: @@ -1650,7 +1652,10 @@ #endif if (dmabuf->enable != DAC_RUNNING || file->f_flags & O_NONBLOCK) return 0; - drain_dac(state); + if(!dmabuf->mapped) + drain_dac(state); + else + stop_dac(state); dmabuf->ready = 0; dmabuf->swptr = dmabuf->hwptr = 0; dmabuf->count = dmabuf->total_bytes = 0; @@ -1900,7 +1905,7 @@ abinfo.bytes = i810_get_free_write_space(state); abinfo.fragments = abinfo.bytes / dmabuf->userfragsize; spin_unlock_irqrestore(&state->card->lock, flags); -#ifdef DEBUG +#if defined(DEBUG) || defined(DEBUG_MMAP) printk("SNDCTL_DSP_GETOSPACE %d, %d, %d, %d\n", abinfo.bytes, abinfo.fragsize, abinfo.fragments, abinfo.fragstotal); #endif @@ -1924,7 +1929,7 @@ __start_dac(state); } spin_unlock_irqrestore(&state->card->lock, flags); -#ifdef DEBUG +#if defined(DEBUG) || defined(DEBUG_MMAP) printk("SNDCTL_DSP_GETOPTR %d, %d, %d, %d\n", cinfo.bytes, cinfo.blocks, cinfo.ptr, dmabuf->count); #endif @@ -1941,7 +1946,7 @@ abinfo.fragstotal = dmabuf->userfrags; abinfo.fragments = abinfo.bytes / dmabuf->userfragsize; spin_unlock_irqrestore(&state->card->lock, flags); -#ifdef DEBUG +#if defined(DEBUG) || defined(DEBUG_MMAP) printk("SNDCTL_DSP_GETISPACE %d, %d, %d, %d\n", abinfo.bytes, abinfo.fragsize, abinfo.fragments, abinfo.fragstotal); #endif @@ -1965,7 +1970,7 @@ __start_adc(state); } spin_unlock_irqrestore(&state->card->lock, flags); -#ifdef DEBUG +#if defined(DEBUG) || defined(DEBUG_MMAP) printk("SNDCTL_DSP_GETIPTR %d, %d, %d, %d\n", cinfo.bytes, cinfo.blocks, cinfo.ptr, dmabuf->count); #endif @@ -1995,7 +2000,7 @@ case SNDCTL_DSP_SETTRIGGER: if (get_user(val, (int *)arg)) return -EFAULT; -#ifdef DEBUG +#if defined(DEBUG) || defined(DEBUG_MMAP) printk("SNDCTL_DSP_SETTRIGGER 0x%x\n", val); #endif if( !(val & PCM_ENABLE_INPUT) && dmabuf->enable == ADC_RUNNING) { @@ -2332,7 +2337,12 @@ /* stop DMA state machine and free DMA buffers/channels */ if(dmabuf->enable & DAC_RUNNING || (dmabuf->count && (dmabuf->trigger & PCM_ENABLE_OUTPUT))) { - drain_dac(state); + if(!dmabuf->mapped) + drain_dac(state); + else { + stop_dac(state); + synchronize_irqs(); + } } if(dmabuf->enable & ADC_RUNNING) { stop_adc(state); ^ permalink raw reply [flat|nested] 56+ messages in thread
* Re: i810 audio patch 2001-12-05 5:23 ` Doug Ledford @ 2001-12-05 20:04 ` Nathan Bryant 2001-12-05 20:05 ` Nathan Bryant 0 siblings, 1 reply; 56+ messages in thread From: Nathan Bryant @ 2001-12-05 20:04 UTC (permalink / raw) To: Doug Ledford; +Cc: Mario Mikocevic, Linux Kernel Mailing List Doug Ledford wrote: > The attached patch should get me the debugging output I need to solve > the problem. If you'll get me the output, then I can likely have a > working version in short order. Here is a fix. It is diffed against your original 0.08 version, Doug. It makes GETOPTR set the LVI to the hardware fragment preceding the one that's currently playing. In the case of Quake, that means Quake must call GETOPTR at least every 3/4ths of a DMA buffer. Hopefully that requirement should be relaxed enough. The alternate fix is to modify the completion handlers. I don't see anything obvious in the databook about how to make the hardware loop infinitely without taking any additional input from us. Comments, please. ^ permalink raw reply [flat|nested] 56+ messages in thread
* Re: i810 audio patch 2001-12-05 20:04 ` Nathan Bryant @ 2001-12-05 20:05 ` Nathan Bryant 2001-12-05 20:10 ` Doug Ledford 0 siblings, 1 reply; 56+ messages in thread From: Nathan Bryant @ 2001-12-05 20:05 UTC (permalink / raw) To: Nathan Bryant; +Cc: Doug Ledford, Mario Mikocevic, Linux Kernel Mailing List [-- Attachment #1: Type: text/plain, Size: 832 bytes --] Umm, duh, here's the actual patch. :-) Nathan Bryant wrote: > Doug Ledford wrote: > >> The attached patch should get me the debugging output I need to solve >> the problem. If you'll get me the output, then I can likely have a >> working version in short order. > > > Here is a fix. It is diffed against your original 0.08 version, Doug. > > It makes GETOPTR set the LVI to the hardware fragment preceding the > one that's currently playing. In the case of Quake, that means Quake > must call GETOPTR at least every 3/4ths of a DMA buffer. Hopefully > that requirement should be relaxed enough. The alternate fix is to > modify the completion handlers. > > I don't see anything obvious in the databook about how to make the > hardware loop infinitely without taking any additional input from us. > > Comments, please. > [-- Attachment #2: 8n.diff --] [-- Type: text/plain, Size: 2455 bytes --] --- i810_audio.c.08 Tue Dec 4 19:43:21 2001 +++ linux/drivers/sound/i810_audio.c Wed Dec 5 14:52:28 2001 @@ -197,7 +197,7 @@ #define INT_MASK (INT_SEC|INT_PRI|INT_MC|INT_PO|INT_PI|INT_MO|INT_NI|INT_GPI) -#define DRIVER_VERSION "0.07" +#define DRIVER_VERSION "0.08n" /* magic numbers to protect our data structures */ #define I810_CARD_MAGIC 0x5072696E /* "Prin" */ @@ -1651,7 +1651,10 @@ #endif if (dmabuf->enable != DAC_RUNNING || file->f_flags & O_NONBLOCK) return 0; - drain_dac(state, 0); + if (!dmabuf->mapped) + drain_dac(state, 0); + else + stop_dac(state); dmabuf->ready = 0; dmabuf->swptr = dmabuf->hwptr = 0; dmabuf->count = dmabuf->total_bytes = 0; @@ -1913,16 +1916,31 @@ if (!dmabuf->ready && (val = prog_dmabuf(state, 0)) != 0) return val; spin_lock_irqsave(&state->card->lock, flags); - val = i810_get_free_write_space(state); + i810_update_ptr(state); cinfo.bytes = dmabuf->total_bytes; cinfo.ptr = dmabuf->hwptr; - cinfo.blocks = val/dmabuf->userfragsize; + /* blocks is only valid in mmap mode, according to API doc */ + cinfo.blocks = 0; if (dmabuf->mapped && (dmabuf->trigger & PCM_ENABLE_OUTPUT)) { - dmabuf->count += val; - dmabuf->swptr = (dmabuf->swptr + val) % dmabuf->dmasize; + /* blocks is supposed to reset to 0 on every call to GETOPTR */ + /* hopefully nobody else destroys count so we can use it for this purpose + in mmap mode */ + cinfo.blocks = (dmabuf->dmasize - dmabuf->count - dmabuf->fragsize) / + dmabuf->userfragsize; + dmabuf->count = dmabuf->dmasize - dmabuf->fragsize; + dmabuf->swptr = (dmabuf->dmasize + dmabuf->hwptr - dmabuf->fragsize) + % dmabuf->dmasize; +#ifdef DEBUG + printk("SNDCTL_DSP_GETOPTR: calling __i810_update_lvi for swptr %d\n", + dmabuf->swptr); +#endif __i810_update_lvi(state, 0); - if (!dmabuf->enable) + if (!dmabuf->enable) { +#ifdef DEBUG + printk("SNDCTL_DSP_GETOPTR: calling __start_dac\n"); +#endif __start_dac(state); + } } spin_unlock_irqrestore(&state->card->lock, flags); #ifdef DEBUG @@ -2324,7 +2342,12 @@ /* stop DMA state machine and free DMA buffers/channels */ if(dmabuf->enable & DAC_RUNNING || (dmabuf->count && (dmabuf->trigger & PCM_ENABLE_OUTPUT))) { - drain_dac(state,0); + if (!dmabuf->mapped) + drain_dac(state,0); + else { + stop_dac(state); + synchronize_irq(); + } } if(dmabuf->enable & ADC_RUNNING) { stop_adc(state); ^ permalink raw reply [flat|nested] 56+ messages in thread
* Re: i810 audio patch 2001-12-05 20:05 ` Nathan Bryant @ 2001-12-05 20:10 ` Doug Ledford 2001-12-05 21:12 ` Nathan Bryant 0 siblings, 1 reply; 56+ messages in thread From: Doug Ledford @ 2001-12-05 20:10 UTC (permalink / raw) To: Nathan Bryant; +Cc: Mario Mikocevic, Linux Kernel Mailing List Nathan Bryant wrote: > Umm, duh, here's the actual patch. :-) > > Nathan Bryant wrote: > >> Doug Ledford wrote: >> >>> The attached patch should get me the debugging output I need to solve >>> the problem. If you'll get me the output, then I can likely have a >>> working version in short order. >> >> >> >> Here is a fix. It is diffed against your original 0.08 version, Doug. >> >> It makes GETOPTR set the LVI to the hardware fragment preceding the >> one that's currently playing. In the case of Quake, that means Quake >> must call GETOPTR at least every 3/4ths of a DMA buffer. Hopefully >> that requirement should be relaxed enough. The alternate fix is to >> modify the completion handlers. >> >> I don't see anything obvious in the databook about how to make the >> hardware loop infinitely without taking any additional input from us. >> >> Comments, please. If that fixes it, then the real fix is to find the bug in i810_get_free_Wwrite_space() and i810_update_lvi(). By using the first function to find the available data in the GETOPTR ioctl, then using update_lvi(), we *should* be setting the lvi fragment to exactly 31 sg segments away from the current index. If that's failing, and we are instead setting lvi == civ, then things will stop and not work. > > > > ------------------------------------------------------------------------ > > --- i810_audio.c.08 Tue Dec 4 19:43:21 2001 > +++ linux/drivers/sound/i810_audio.c Wed Dec 5 14:52:28 2001 > @@ -197,7 +197,7 @@ > #define INT_MASK (INT_SEC|INT_PRI|INT_MC|INT_PO|INT_PI|INT_MO|INT_NI|INT_GPI) > > > -#define DRIVER_VERSION "0.07" > +#define DRIVER_VERSION "0.08n" > > /* magic numbers to protect our data structures */ > #define I810_CARD_MAGIC 0x5072696E /* "Prin" */ > @@ -1651,7 +1651,10 @@ > #endif > if (dmabuf->enable != DAC_RUNNING || file->f_flags & O_NONBLOCK) > return 0; > - drain_dac(state, 0); > + if (!dmabuf->mapped) > + drain_dac(state, 0); > + else > + stop_dac(state); > dmabuf->ready = 0; > dmabuf->swptr = dmabuf->hwptr = 0; > dmabuf->count = dmabuf->total_bytes = 0; > @@ -1913,16 +1916,31 @@ > if (!dmabuf->ready && (val = prog_dmabuf(state, 0)) != 0) > return val; > spin_lock_irqsave(&state->card->lock, flags); > - val = i810_get_free_write_space(state); > + i810_update_ptr(state); > cinfo.bytes = dmabuf->total_bytes; > cinfo.ptr = dmabuf->hwptr; > - cinfo.blocks = val/dmabuf->userfragsize; > + /* blocks is only valid in mmap mode, according to API doc */ > + cinfo.blocks = 0; > if (dmabuf->mapped && (dmabuf->trigger & PCM_ENABLE_OUTPUT)) { > - dmabuf->count += val; > - dmabuf->swptr = (dmabuf->swptr + val) % dmabuf->dmasize; > + /* blocks is supposed to reset to 0 on every call to GETOPTR */ > + /* hopefully nobody else destroys count so we can use it for this purpose > + in mmap mode */ > + cinfo.blocks = (dmabuf->dmasize - dmabuf->count - dmabuf->fragsize) / > + dmabuf->userfragsize; > + dmabuf->count = dmabuf->dmasize - dmabuf->fragsize; > + dmabuf->swptr = (dmabuf->dmasize + dmabuf->hwptr - dmabuf->fragsize) > + % dmabuf->dmasize; > +#ifdef DEBUG > + printk("SNDCTL_DSP_GETOPTR: calling __i810_update_lvi for swptr %d\n", > + dmabuf->swptr); > +#endif > __i810_update_lvi(state, 0); > - if (!dmabuf->enable) > + if (!dmabuf->enable) { > +#ifdef DEBUG > + printk("SNDCTL_DSP_GETOPTR: calling __start_dac\n"); > +#endif > __start_dac(state); > + } > } > spin_unlock_irqrestore(&state->card->lock, flags); > #ifdef DEBUG > @@ -2324,7 +2342,12 @@ > /* stop DMA state machine and free DMA buffers/channels */ > if(dmabuf->enable & DAC_RUNNING || > (dmabuf->count && (dmabuf->trigger & PCM_ENABLE_OUTPUT))) { > - drain_dac(state,0); > + if (!dmabuf->mapped) > + drain_dac(state,0); > + else { > + stop_dac(state); > + synchronize_irq(); > + } > } > if(dmabuf->enable & ADC_RUNNING) { > stop_adc(state); > -- Doug Ledford <dledford@redhat.com> http://people.redhat.com/dledford Please check my web site for aic7xxx updates/answers before e-mailing me about problems ^ permalink raw reply [flat|nested] 56+ messages in thread
* Re: i810 audio patch 2001-12-05 20:10 ` Doug Ledford @ 2001-12-05 21:12 ` Nathan Bryant 2001-12-05 21:25 ` Doug Ledford 0 siblings, 1 reply; 56+ messages in thread From: Nathan Bryant @ 2001-12-05 21:12 UTC (permalink / raw) To: Doug Ledford; +Cc: Mario Mikocevic, Linux Kernel Mailing List Doug Ledford wrote: > If that fixes it, then the real fix is to find the bug in > i810_get_free_Wwrite_space() and i810_update_lvi(). It does fix it. By the way, I'm confused about something. i810_write appears to overrun the end of the DMA buffer instead of wrapping around to the beginning when it does copy_from_user. which makes no sense to me. so ok, the correct number is 31/32nds, not 3/4ths - not so bad. > By using the first function to find the available data in the GETOPTR > ioctl, then using update_lvi(), we *should* be setting the lvi > fragment to exactly 31 sg segments away from the current index. If > that's failing, and we are instead setting lvi == civ, then things > will stop and not work. yeah, i think that's what's happening ^ permalink raw reply [flat|nested] 56+ messages in thread
* Re: i810 audio patch 2001-12-05 21:12 ` Nathan Bryant @ 2001-12-05 21:25 ` Doug Ledford 2001-12-05 21:36 ` Nathan Bryant 2001-12-05 23:46 ` Nathan Bryant 0 siblings, 2 replies; 56+ messages in thread From: Doug Ledford @ 2001-12-05 21:25 UTC (permalink / raw) To: Nathan Bryant; +Cc: Mario Mikocevic, Linux Kernel Mailing List Nathan Bryant wrote: > Doug Ledford wrote: > >> If that fixes it, then the real fix is to find the bug in >> i810_get_free_Wwrite_space() and i810_update_lvi(). > > > It does fix it. > > By the way, I'm confused about something. i810_write appears to overrun > the end of the DMA buffer instead of wrapping around to the beginning > when it does copy_from_user. which makes no sense to me. This didn't used to be a bug, but it is now (all these changes and merges have let some thigns slip in I'm afraid, and I'm not just referring to the work in the last few days, I'm also referring to changes that were lost in the time of the S/PDIF and PM merges). Anyway, in i810_write, the lines that read: if (cnt > (dmabuf->dmasize - dmabuf->count)) cnt = dmabuf->dmasize - dmabuf->count; should read: if (cnt > (dmabuf->dmasize - swptr)) cnt = dmabuf->dmasize - swptr; > so ok, the correct number is 31/32nds, not 3/4ths - not so bad. > >> By using the first function to find the available data in the GETOPTR >> ioctl, then using update_lvi(), we *should* be setting the lvi >> fragment to exactly 31 sg segments away from the current index. If >> that's failing, and we are instead setting lvi == civ, then things >> will stop and not work. > > > yeah, i think that's what's happening Can you add a debug check to update_lvi()? Something like: #ifdef DEBUG_MMAP if (dmabuf->count > dmabuf->fragsize && inb(port+OFF_CIV) == x) printk(KERN_DEBUG,"i810_audio: update_lvi - CIV == LVI\n"); #endif and see if that triggers with the original mmap code? -- Doug Ledford <dledford@redhat.com> http://people.redhat.com/dledford Please check my web site for aic7xxx updates/answers before e-mailing me about problems ^ permalink raw reply [flat|nested] 56+ messages in thread
* Re: i810 audio patch 2001-12-05 21:25 ` Doug Ledford @ 2001-12-05 21:36 ` Nathan Bryant 2001-12-05 21:56 ` Nathan Bryant 2001-12-05 22:43 ` Doug Ledford 2001-12-05 23:46 ` Nathan Bryant 1 sibling, 2 replies; 56+ messages in thread From: Nathan Bryant @ 2001-12-05 21:36 UTC (permalink / raw) To: Doug Ledford; +Cc: Mario Mikocevic, Linux Kernel Mailing List Doug Ledford wrote: > This didn't used to be a bug, but it is now (all these changes and > merges have let some thigns slip in I'm afraid, and I'm not just > referring to the work in the last few days, I'm also referring to > changes that were lost in the time of the S/PDIF and PM merges). Agreed. There are some uglies... > > > Anyway, in i810_write, the lines that read: > > if (cnt > (dmabuf->dmasize - dmabuf->count)) > cnt = dmabuf->dmasize - dmabuf->count; > > should read: > > if (cnt > (dmabuf->dmasize - swptr)) > cnt = dmabuf->dmasize - swptr; Okay. I thought I was being stupid. :-) > Can you add a debug check to update_lvi()? Something like: > > #ifdef DEBUG_MMAP > if (dmabuf->count > dmabuf->fragsize && inb(port+OFF_CIV) == x) > printk(KERN_DEBUG,"i810_audio: update_lvi - CIV == > LVI\n"); > #endif > > and see if that triggers with the original mmap code? Actually, I think I *may* have found the problem, in update ptr, it should look like this: going to test in a moment /* error handling and process wake up for DAC */ if (dmabuf->enable == DAC_RUNNING) { /* update hardware pointer */ hwptr = i810_get_dma_addr(state, 0); diff = hwptr - dmabuf->hwptr; if (hwptr < dmabuf->hwptr) diff += dmabuf->dmasize; #if defined(DEBUG_INTERRUPTS) || defined(DEBUG_MMAP) printk("DAC HWP %d,%d,%d\n", hwptr, dmabuf->hwptr, diff); #endif reason: hwptr hits 65536 which is indistinguishable from 0 in mod arithmetic also, I ran your other DEBUG_MMAP patch and the news is that count just sits at 65536 ad nauseum. ^ permalink raw reply [flat|nested] 56+ messages in thread
* Re: i810 audio patch 2001-12-05 21:36 ` Nathan Bryant @ 2001-12-05 21:56 ` Nathan Bryant 2001-12-05 22:31 ` Doug Ledford 2001-12-05 22:43 ` Doug Ledford 1 sibling, 1 reply; 56+ messages in thread From: Nathan Bryant @ 2001-12-05 21:56 UTC (permalink / raw) To: Nathan Bryant; +Cc: Doug Ledford, Mario Mikocevic, Linux Kernel Mailing List Nathan Bryant wrote: > > also, I ran your other DEBUG_MMAP patch and the news is that count > just sits at 65536 ad nauseum. > this is because settrigger in 0.9 doesn't: it's setting LVI=CVI so it goes nowhere. this was introduced by the second patch against 0.08 that you sent me... ^ permalink raw reply [flat|nested] 56+ messages in thread
* Re: i810 audio patch 2001-12-05 21:56 ` Nathan Bryant @ 2001-12-05 22:31 ` Doug Ledford 0 siblings, 0 replies; 56+ messages in thread From: Doug Ledford @ 2001-12-05 22:31 UTC (permalink / raw) To: Nathan Bryant; +Cc: Mario Mikocevic, Linux Kernel Mailing List Nathan Bryant wrote: > Nathan Bryant wrote: > >> >> also, I ran your other DEBUG_MMAP patch and the news is that count >> just sits at 65536 ad nauseum. >> > > this is because settrigger in 0.9 doesn't: it's setting LVI=CVI so it > goes nowhere. Not true. SETTRIGGER is (generally) only called once to start things (and things are getting started or else it would set at 0 instead of at 65536). After that, SETTRIGGER isn't typically called again unless you are turning the device off. It's calls to GETOPTR that are suppossed to keep the LVI-CIV tail chasing going on. > this was introduced by the second patch against 0.08 that > you sent me... > -- Doug Ledford <dledford@redhat.com> http://people.redhat.com/dledford Please check my web site for aic7xxx updates/answers before e-mailing me about problems ^ permalink raw reply [flat|nested] 56+ messages in thread
* Re: i810 audio patch 2001-12-05 21:36 ` Nathan Bryant 2001-12-05 21:56 ` Nathan Bryant @ 2001-12-05 22:43 ` Doug Ledford 1 sibling, 0 replies; 56+ messages in thread From: Doug Ledford @ 2001-12-05 22:43 UTC (permalink / raw) To: Nathan Bryant; +Cc: Mario Mikocevic, Linux Kernel Mailing List Nathan Bryant wrote: > > Actually, I think I *may* have found the problem, in update ptr, it > should look like this: going to test in a moment > > /* error handling and process wake up for DAC */ > if (dmabuf->enable == DAC_RUNNING) { > /* update hardware pointer */ > hwptr = i810_get_dma_addr(state, 0); > diff = hwptr - dmabuf->hwptr; > if (hwptr < dmabuf->hwptr) > diff += dmabuf->dmasize; This is mathematically equivelant to what was already there. > #if defined(DEBUG_INTERRUPTS) || defined(DEBUG_MMAP) > printk("DAC HWP %d,%d,%d\n", hwptr, dmabuf->hwptr, diff); > #endif > > reason: hwptr hits 65536 which is indistinguishable from 0 in mod > arithmetic The mod doesn't happen until all the rest is already done, and then it's just cancelling out the dmabuf->dmasize portion (instead of using an if statement to do the same thing). > also, I ran your other DEBUG_MMAP patch and the news is that count just > sits at 65536 ad nauseum. Yes, but if I have the stuff leading up to it sitting at 65536 forever I might be able to diagnose the problem (without installing quake myself and taking the time to set it up anyway) ;-) -- Doug Ledford <dledford@redhat.com> http://people.redhat.com/dledford Please check my web site for aic7xxx updates/answers before e-mailing me about problems ^ permalink raw reply [flat|nested] 56+ messages in thread
* Re: i810 audio patch 2001-12-05 21:25 ` Doug Ledford 2001-12-05 21:36 ` Nathan Bryant @ 2001-12-05 23:46 ` Nathan Bryant 2001-12-05 23:51 ` Doug Ledford 2001-12-05 23:57 ` Nathan Bryant 1 sibling, 2 replies; 56+ messages in thread From: Nathan Bryant @ 2001-12-05 23:46 UTC (permalink / raw) To: Doug Ledford; +Cc: Mario Mikocevic, Linux Kernel Mailing List Doug Ledford wrote: > Can you add a debug check to update_lvi()? Something like: > > #ifdef DEBUG_MMAP > if (dmabuf->count > dmabuf->fragsize && inb(port+OFF_CIV) == x) > printk(KERN_DEBUG,"i810_audio: update_lvi - CIV == > LVI\n"); > #endif > > and see if that triggers with the original mmap code? I've narrowed it down a little more.. the above does not trigger. but i've added some other printk's and the sequence of events goes like this: open, mmap SETTRIGGER : works properly with the resync_dma removed; count initialized to 65536 we take 6 interrupts; 4 comp + lvi + dch; count drains to 0 properly [quake finishes initializing] GETOPTR: at the beginning of the call, count is 0; by the end of the call, count has been set to 64K but, we take no interrupts after this point. ^ permalink raw reply [flat|nested] 56+ messages in thread
* Re: i810 audio patch 2001-12-05 23:46 ` Nathan Bryant @ 2001-12-05 23:51 ` Doug Ledford 2001-12-05 23:57 ` Nathan Bryant 1 sibling, 0 replies; 56+ messages in thread From: Doug Ledford @ 2001-12-05 23:51 UTC (permalink / raw) To: Nathan Bryant; +Cc: Mario Mikocevic, Linux Kernel Mailing List Nathan Bryant wrote: > Doug Ledford wrote: > >> Can you add a debug check to update_lvi()? Something like: >> >> #ifdef DEBUG_MMAP >> if (dmabuf->count > dmabuf->fragsize && inb(port+OFF_CIV) == x) >> printk(KERN_DEBUG,"i810_audio: update_lvi - CIV == >> LVI\n"); >> #endif >> >> and see if that triggers with the original mmap code? > > > I've narrowed it down a little more.. the above does not trigger. but > i've added some other printk's and the sequence of events goes like this: > > open, mmap > SETTRIGGER : works properly with the resync_dma removed; count > initialized to 65536 > we take 6 interrupts; 4 comp + lvi + dch; count drains to 0 properly > [quake finishes initializing] > GETOPTR: > at the beginning of the call, count is 0; by the end of the call, count > has been set to 64K > > but, we take no interrupts after this point. > In __i810_update_lvi(), try changing the line that reads: x = (dmabuf->dmasize + dmabuf->swptr - 1) % dmabuf->dmasize; to use - 2 instead of -1 and see if that solves the problem (I've been suspecting an off-by-one error, I just haven't found it for sure. The whole 65536 vs. 0 could be providing the off-by-one though.) -- Doug Ledford <dledford@redhat.com> http://people.redhat.com/dledford Please check my web site for aic7xxx updates/answers before e-mailing me about problems ^ permalink raw reply [flat|nested] 56+ messages in thread
* Re: i810 audio patch 2001-12-05 23:46 ` Nathan Bryant 2001-12-05 23:51 ` Doug Ledford @ 2001-12-05 23:57 ` Nathan Bryant 2001-12-06 0:25 ` Doug Ledford 1 sibling, 1 reply; 56+ messages in thread From: Nathan Bryant @ 2001-12-05 23:57 UTC (permalink / raw) To: Nathan Bryant; +Cc: Doug Ledford, Mario Mikocevic, Linux Kernel Mailing List Nathan Bryant wrote: > Doug Ledford wrote: > >> Can you add a debug check to update_lvi()? Something like: >> >> #ifdef DEBUG_MMAP >> if (dmabuf->count > dmabuf->fragsize && inb(port+OFF_CIV) == x) >> printk(KERN_DEBUG,"i810_audio: update_lvi - CIV == >> LVI\n"); >> #endif >> >> and see if that triggers with the original mmap code? > > > I've narrowed it down a little more.. the above does not trigger. but > i've added some other printk's and the sequence of events goes like this: sorry... syslog.conf was not configured for DEBUG level... it actually looks like this Dec 5 18:55:17 lasn-001 kernel: SNDCTL_DSP_GETOPTR: count = 0 Dec 5 18:55:17 lasn-001 kernel: GETOPTR: setting swptr 0, hwptr=65536 Dec 5 18:55:17 lasn-001 kernel: i810_audio: update_lvi - CIV == LVI Dec 5 18:55:17 lasn-001 kernel: SNDCTL_DSP_GETOPTR 65536, 4, 65536, 65536 Dec 5 18:55:17 lasn-001 kernel: SNDCTL_DSP_GETOPTR: count = 65536 Dec 5 18:55:17 lasn-001 kernel: DAC HWP 65536,65536,0 Dec 5 18:55:17 lasn-001 kernel: GETOPTR: setting swptr 0, hwptr=65536 Dec 5 18:55:17 lasn-001 kernel: i810_audio: update_lvi - CIV == LVI Dec 5 18:55:17 lasn-001 kernel: SNDCTL_DSP_GETOPTR 65536, 0, 65536, 65536 Dec 5 18:55:17 lasn-001 kernel: SNDCTL_DSP_GETOPTR: count = 65536 Dec 5 18:55:17 lasn-001 kernel: DAC HWP 65536,65536,0 Dec 5 18:55:17 lasn-001 kernel: GETOPTR: setting swptr 0, hwptr=65536 Dec 5 18:55:17 lasn-001 kernel: i810_audio: update_lvi - CIV == LVI Dec 5 18:55:17 lasn-001 kernel: SNDCTL_DSP_GETOPTR 65536, 0, 65536, 65536 Dec 5 18:55:17 lasn-001 kernel: SNDCTL_DSP_GETOPTR: count = 65536 Dec 5 18:55:17 lasn-001 kernel: DAC HWP 65536,65536,0 ^ permalink raw reply [flat|nested] 56+ messages in thread
* Re: i810 audio patch 2001-12-05 23:57 ` Nathan Bryant @ 2001-12-06 0:25 ` Doug Ledford 2001-12-06 0:50 ` Nathan Bryant ` (3 more replies) 0 siblings, 4 replies; 56+ messages in thread From: Doug Ledford @ 2001-12-06 0:25 UTC (permalink / raw) To: Nathan Bryant; +Cc: Mario Mikocevic, Linux Kernel Mailing List Nathan Bryant wrote: OK, on my site there is now a 0.10 version of the driver. This one stands a reasonable chance of working in mmap mode. Please give it a try and let me know what happens (see my comments in __i810_update_lvi() to see what I think the actual problem is). http://people.redhat.com/dledford/i810_audio.c.gz -- Doug Ledford <dledford@redhat.com> http://people.redhat.com/dledford Please check my web site for aic7xxx updates/answers before e-mailing me about problems ^ permalink raw reply [flat|nested] 56+ messages in thread
* Re: i810 audio patch 2001-12-06 0:25 ` Doug Ledford @ 2001-12-06 0:50 ` Nathan Bryant [not found] ` <3C0EC0ED.3000603@optonl! ine.net> ` (2 subsequent siblings) 3 siblings, 0 replies; 56+ messages in thread From: Nathan Bryant @ 2001-12-06 0:50 UTC (permalink / raw) To: Doug Ledford; +Cc: Mario Mikocevic, Linux Kernel Mailing List [-- Attachment #1: Type: text/plain, Size: 403 bytes --] Doug Ledford wrote: > Nathan Bryant wrote: > > OK, on my site there is now a 0.10 version of the driver. This one > stands a reasonable chance of working in mmap mode. Please give it a > try and let me know what happens (see my comments in > __i810_update_lvi() to see what I think the actual problem is). > > http://people.redhat.com/dledford/i810_audio.c.gz > > > > some fixes needed, attached [-- Attachment #2: foo --] [-- Type: text/plain, Size: 1926 bytes --] --- /home/nbryant/i810_audio.c Wed Dec 5 19:49:38 2001 +++ drivers/sound/i810_audio.c Wed Dec 5 19:49:00 2001 @@ -953,7 +953,7 @@ * 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->enabled) + if (!dmabuf->enable) outb((inb(port+OFF_CIV)+1)&31, port+OFF_CIV); /* swptr - 1 is the tail of our transfer */ @@ -961,7 +961,7 @@ x /= dmabuf->fragsize; #ifdef DEBUG_MMAP if (dmabuf->count > dmabuf->fragsize && inb(port+OFF_CIV) == x) - printk(KERN_DEBUG,"i810_audio: update_lvi - CIV == LVI\n"); + printk(KERN_DEBUG "i810_audio: update_lvi - CIV == LVI\n"); #endif outb(x, port+OFF_LVI); } @@ -1124,7 +1124,6 @@ if(count <= 0 || timeout) { stop_dac(state); synchronize_irq(); - resync_dma_ptrs(state, 0 /* record channel */); } if (signal_pending(current)) return -ERESTARTSYS; @@ -1595,7 +1594,7 @@ static int i810_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) { struct i810_state *state = (struct i810_state *)file->private_data; - struct i810_channel *c; + struct i810_channel *c = NULL; struct dmabuf *dmabuf = &state->dmabuf; unsigned long flags; audio_buf_info abinfo; @@ -1629,10 +1628,12 @@ c = dmabuf->read_channel; __stop_adc(state); } - outb(2, state->card->iobase+c->port+OFF_CR); /* reset DMA machine */ - outl(virt_to_bus(&c->sg[0]), state->card->iobase+c->port+OFF_BDBAR); - outb(0, state->card->iobase+c->port+OFF_CIV); - outb(0, state->card->iobase+c->port+OFF_LVI); + if (c != NULL) { + outb(2, state->card->iobase+c->port+OFF_CR); /* reset DMA machine */ + outl(virt_to_bus(&c->sg[0]), state->card->iobase+c->port+OFF_BDBAR); + outb(0, state->card->iobase+c->port+OFF_CIV); + outb(0, state->card->iobase+c->port+OFF_LVI); + } spin_unlock_irqrestore(&state->card->lock, flags); synchronize_irq(); ^ permalink raw reply [flat|nested] 56+ messages in thread
[parent not found: <3C0EC0ED.3000603@optonl! ine.net>]
* Re: i810 audio patch [not found] ` <3C0EC0ED.3000603@optonl! ine.net> @ 2001-12-06 0:55 ` Doug Ledford 0 siblings, 0 replies; 56+ messages in thread From: Doug Ledford @ 2001-12-06 0:55 UTC (permalink / raw) To: Nathan Bryant; +Cc: Mario Mikocevic, Linux Kernel Mailing List Nathan Bryant wrote: > Doug Ledford wrote: > >> Nathan Bryant wrote: >> >> OK, on my site there is now a 0.10 version of the driver. This one >> stands a reasonable chance of working in mmap mode. Please give it a >> try and let me know what happens (see my comments in >> __i810_update_lvi() to see what I think the actual problem is). >> >> http://people.redhat.com/dledford/i810_audio.c.gz >> >> >> >> > some fixes needed, attached Thanks, applied. (I haven't been compile testing these patches because I would have to set up another compile environment just to get it to work, my current ones won't work for it) -- Doug Ledford <dledford@redhat.com> http://people.redhat.com/dledford Please check my web site for aic7xxx updates/answers before e-mailing me about problems ^ permalink raw reply [flat|nested] 56+ messages in thread
[parent not found: <3C0EC219.8010107@redhat! .com>]
* Re: i810 audio patch [not found] ` <3C0EC219.8010107@redhat! .com> @ 2001-12-06 2:53 ` Nathan Bryant [not found] ` <3C0EDDC2.608@optonl! ine.net> 1 sibling, 0 replies; 56+ messages in thread From: Nathan Bryant @ 2001-12-06 2:53 UTC (permalink / raw) To: Doug Ledford; +Cc: Mario Mikocevic, Linux Kernel Mailing List as evidenced by, /* 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) { #ifdef DEBUG_MMAP printk("fnord? %d\n", inb(port+OFF_CIV)); #endif /* maybe we have to increment LVI to make room before incrementing CIV, (databook says CELV isn't cleared until new val written to LVI.) we'll set LVI where we really want it down below. */ //outb((inb(port+OFF_LVI)+1)&31, port+OFF_LVI); newciv = (inb(port+OFF_CIV)+1)&31; outb(newciv, port+OFF_CIV); for (x = 0; inb(port+OFF_CIV) != newciv && x< 5000000; x++); if (x==5000000) printk("foo! civ != %d\n", newciv); } and Dec 5 21:34:32 lasn-001 kernel: foo! civ != 1 CIV doesn't seem to respond to writes on my chipset, at least not in this situation. you'll note that nowhere in the driver are we initializing CIV to anything other than 0 anyway. two alternatives I can think of: first fix: set LVI to desired value minus one SG start_dac (which should have side effect of incrementing CIV by one) increment LVI to desired value 2nd fix: back off and perform DMA reset. 3rd fix (really fix 1a ;) just don't allow use of the last SG when restarting ^ permalink raw reply [flat|nested] 56+ messages in thread
[parent not found: <3C0EDDC2.608@optonl! ine.net>]
* Re: i810 audio patch [not found] ` <3C0EDDC2.608@optonl! ine.net> @ 2001-12-06 3:39 ` Doug Ledford 0 siblings, 0 replies; 56+ messages in thread From: Doug Ledford @ 2001-12-06 3:39 UTC (permalink / raw) To: Nathan Bryant; +Cc: Mario Mikocevic, Linux Kernel Mailing List Nathan Bryant wrote: > as evidenced by, > > > /* 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) { > #ifdef DEBUG_MMAP > printk("fnord? %d\n", inb(port+OFF_CIV)); > #endif > /* maybe we have to increment LVI to make room before > incrementing CIV, > (databook says CELV isn't cleared until new val written > to LVI.) > we'll set LVI where we really want it down below. */ > //outb((inb(port+OFF_LVI)+1)&31, port+OFF_LVI); > newciv = (inb(port+OFF_CIV)+1)&31; > outb(newciv, port+OFF_CIV); > for (x = 0; inb(port+OFF_CIV) != newciv && x< 5000000; x++); > if (x==5000000) printk("foo! civ != %d\n", newciv); > } > > and > > Dec 5 21:34:32 lasn-001 kernel: foo! civ != 1 > > CIV doesn't seem to respond to writes on my chipset, at least not in > this situation. you'll note that nowhere in the driver are we > initializing CIV to anything other than 0 anyway. > > two alternatives I can think of: > > first fix: > set LVI to desired value minus one SG > start_dac (which should have side effect of incrementing CIV by one) > increment LVI to desired value > > 2nd fix: > back off and perform DMA reset. > > 3rd fix (really fix 1a ;) > just don't allow use of the last SG when restarting > Try this out: /* 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) { outb((inb(port+OFF_CIV)+1)&31, port+OFF_LVI); if(rec) { __start_adc(state); while( !(inb(port + OFF_CR) & ((1<<4) | (1<<2))) ) barrier(); } else { __start_dac(state); while( !(inb(port + OFF_CR) & ((1<<4) | (1<<2))) ) barrier(); } } -- Doug Ledford <dledford@redhat.com> http://people.redhat.com/dledford Please check my web site for aic7xxx updates/answers before e-mailing me about problems ^ permalink raw reply [flat|nested] 56+ messages in thread
[parent not found: <3C0EC219.8010107@redhat!.com>]
[parent not found: <3C0EE865.1090607@red! hat.com>]
* Re: i810 audio patch [not found] ` <3C0EE865.1090607@red! hat.com> @ 2001-12-06 4:02 ` Nathan Bryant 2001-12-06 4:09 ` Doug Ledford 0 siblings, 1 reply; 56+ messages in thread From: Nathan Bryant @ 2001-12-06 4:02 UTC (permalink / raw) To: Doug Ledford; +Cc: Mario Mikocevic, Linux Kernel Mailing List ok that works ^ permalink raw reply [flat|nested] 56+ messages in thread
* Re: i810 audio patch 2001-12-06 4:02 ` Nathan Bryant @ 2001-12-06 4:09 ` Doug Ledford 2001-12-06 15:45 ` i810 audio patch (it _works_ for me :) Mario Mikocevic 0 siblings, 1 reply; 56+ messages in thread From: Doug Ledford @ 2001-12-06 4:09 UTC (permalink / raw) To: Nathan Bryant; +Cc: Mario Mikocevic, Linux Kernel Mailing List Nathan Bryant wrote: > ok that works > OK, I've reloaded a new 0.10 version of the driver to my web site. At this point, I'm calling this driver done until I hear otherwise. If you have problems, or suspect you might have problems with this driver, or just want to make sure you *won't* have problems with this driver, test and speak now or possibly end up having to hack it yourself later ;-) http://people.redhat.com/dledford/i810_audio.c.gz -- Doug Ledford <dledford@redhat.com> http://people.redhat.com/dledford Please check my web site for aic7xxx updates/answers before e-mailing me about problems ^ permalink raw reply [flat|nested] 56+ messages in thread
* Re: i810 audio patch (it _works_ for me :) 2001-12-06 4:09 ` Doug Ledford @ 2001-12-06 15:45 ` Mario Mikocevic 2001-12-06 17:00 ` i810 audio patch Pascal Junod 0 siblings, 1 reply; 56+ messages in thread From: Mario Mikocevic @ 2001-12-06 15:45 UTC (permalink / raw) To: Doug Ledford; +Cc: Nathan Bryant, Linux Kernel Mailing List Hi, > OK, I've reloaded a new 0.10 version of the driver to my web site. At > this point, I'm calling this driver done until I hear otherwise. If you > have problems, or suspect you might have problems with this driver, or > just want to make sure you *won't* have problems with this driver, test > and speak now or possibly end up having to hack it yourself later ;-) > > http://people.redhat.com/dledford/i810_audio.c.gz Well, 0.10 works for me -> Dec 6 16:04:27 videotest kernel: Intel 810 + AC97 Audio, version 0.10, 16:01:33 Dec 6 2001 Dec 6 16:04:27 videotest kernel: PCI: Found IRQ 9 for device 00:1f.5 Dec 6 16:04:27 videotest kernel: PCI: Sharing IRQ 9 with 00:1f.3 Dec 6 16:04:27 videotest kernel: PCI: Setting latency timer of device 00:1f.5 to 64 Dec 6 16:04:27 videotest kernel: i810: Intel ICH2 found at IO 0xef00 and 0xe800, IRQ 9 Dec 6 16:04:27 videotest kernel: i810_audio: Audio Controller supports 6 channels. Dec 6 16:04:27 videotest kernel: ac97_codec: AC97 Audio codec, id: 0x4144:0x5360 (Analog Devices AD1885) Dec 6 16:04:27 videotest kernel: i810_audio: AC'97 codec 0 Unable to map surround DAC's (or DAC's not present), total channels = 2 Dec 6 16:04:27 videotest kernel: i810_audio: setting clocking to 41319 RealProducer finally works on _all_ codecs and _all_ bitrates, no more oops, xmms works and artsd also works. thanks, -- Mario Mikočević (Mozgy) mozgy at hinet dot hr My favourite FUBAR ... ^ permalink raw reply [flat|nested] 56+ messages in thread
* Re: i810 audio patch 2001-12-06 15:45 ` i810 audio patch (it _works_ for me :) Mario Mikocevic @ 2001-12-06 17:00 ` Pascal Junod 0 siblings, 0 replies; 56+ messages in thread From: Pascal Junod @ 2001-12-06 17:00 UTC (permalink / raw) To: linux-kernel; +Cc: dledford Hi ! I'm trying to get sound working on my Sony Vaio PCG-GR114SK laptop with 0.10 patch: kernel: Intel 810 + AC97 Audio, version 0.10, 17:31:53 Dec 6 2001 kernel: PCI: Setting latency timer of device 00:1f.5 to 64 kernel: i810: Intel ICH3 found at IO 0x18c0 and 0x1c00, IRQ 9 kernel: i810_audio: Audio Controller supports 6 channels. kernel: ac97_codec: AC97 Audio codec, id: 0x4144:0x5348 (Analog Devices AD1881A) kernel: i810_audio: AC'97 codec 0 Unable to map surround DAC's (or DAC's not present), total channels = 2 kernel: ac97_codec: AC97 Modem codec, id: 0x4358:0x5421 (Unknown) kernel: i810_audio: timed out waiting for codec 1 analog ready I have tried alsa drivers 0.9.0beta10 with a little bit more success: I get some sound, but it's looping forever. A+ Pascal -- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * Pascal Junod, pascal.junod@epfl.ch * * Security and Cryptography Laboratory (LASEC) * * INF 240, EPFL, CH-1015 Lausanne, Switzerland ++41 (0)21 693 76 17 * * Montétan 13, CH-1004 Lausanne ++41 (0)79 617 28 57 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ^ permalink raw reply [flat|nested] 56+ messages in thread
* Re: i810 audio patch 2001-12-05 3:28 ` Nathan Bryant 2001-12-05 4:25 ` Doug Ledford @ 2001-12-05 4:41 ` Nathan Bryant 2001-12-05 5:10 ` Doug Ledford 1 sibling, 1 reply; 56+ messages in thread From: Nathan Bryant @ 2001-12-05 4:41 UTC (permalink / raw) To: Doug Ledford, Linux Kernel Mailing List, Mario Mikocevic got this during a quake run with only DEBUG_INTERRUPTS enabled it seems that we aren't making it properly chase its tail during mmap mode. so it runs through once and then stops. the final timeout is waiting for a completion that's never going to come. Dec 4 23:33:50 lasn-001 kernel: Intel 810 + AC97 Audio, version 0.07, 23:28:08 Dec 4 2001 Dec 4 23:33:50 lasn-001 kernel: PCI: Setting latency timer of device 00:1f.5 to 64 Dec 4 23:33:50 lasn-001 kernel: i810: Intel ICH 82801AA found at IO 0x2400 and 0x2000, IRQ 17 Dec 4 23:33:51 lasn-001 kernel: i810_audio: Audio Controller supports 2 channels. Dec 4 23:33:51 lasn-001 kernel: ac97_codec: AC97 Audio codec, id: 0x4144:0x5360 (Analog Devices AD1885) Dec 4 23:33:51 lasn-001 kernel: i810_audio: AC'97 codec 0 Unable to map surround DAC's (or DAC's not present), total channels = 2 Dec 4 23:33:51 lasn-001 kernel: i810_audio: setting clocking to 41231 Dec 4 23:34:00 lasn-001 kernel: NVRM: AGPGART: allocated 257 pages Dec 4 23:34:00 lasn-001 kernel: NVRM: AGPGART: allocated 128 pages Dec 4 23:34:00 lasn-001 kernel: CHANNEL NUM 1 PORT 10 IRQ ( ST8 DAC HWP 16384,0,16384 Dec 4 23:34:00 lasn-001 kernel: COMP 8 ) Dec 4 23:34:01 lasn-001 kernel: CHANNEL NUM 1 PORT 10 IRQ ( ST8 DAC HWP 32768,16384,16384 Dec 4 23:34:01 lasn-001 kernel: COMP 16 ) Dec 4 23:34:01 lasn-001 kernel: CHANNEL NUM 1 PORT 10 IRQ ( ST8 DAC HWP 49152,32768,16384 Dec 4 23:34:01 lasn-001 kernel: COMP 24 ) Dec 4 23:34:01 lasn-001 kernel: CHANNEL NUM 1 PORT 10 IRQ ( ST15 DAC HWP 65536,49152,16384 Dec 4 23:34:01 lasn-001 kernel: COMP 32 DAC HWP 65536,65536,0 Dec 4 23:34:01 lasn-001 kernel: LVI DAC HWP 65536,65536,0 Dec 4 23:34:01 lasn-001 kernel: DCH - STOP ) Dec 4 23:34:02 lasn-001 kernel: cdrom: open failed. Dec 4 23:34:03 lasn-001 kernel: DAC HWP 65536,65536,0 Dec 4 23:34:07 lasn-001 kernel: NVRM: AGPGART: freed 128 pages Dec 4 23:34:07 lasn-001 kernel: NVRM: AGPGART: freed 257 pages Dec 4 23:34:07 lasn-001 kernel: DAC HWP 65536,65536,0 Dec 4 23:34:10 lasn-001 kernel: i810_audio: drain_dac, dma timeout? ^ permalink raw reply [flat|nested] 56+ messages in thread
* Re: i810 audio patch 2001-12-05 4:41 ` Nathan Bryant @ 2001-12-05 5:10 ` Doug Ledford 2001-12-05 5:35 ` Nathan Bryant 2001-12-05 7:24 ` Nathan Bryant 0 siblings, 2 replies; 56+ messages in thread From: Doug Ledford @ 2001-12-05 5:10 UTC (permalink / raw) To: Nathan Bryant; +Cc: Linux Kernel Mailing List, Mario Mikocevic Nathan Bryant wrote: > > > got this during a quake run with only DEBUG_INTERRUPTS enabled > > it seems that we aren't making it properly chase its tail during mmap > mode. Yes and no. We aren't chasing our tail, but that's because the application is suppossed to call the GETOPTR ioctl in order to trigger a pointer update. In short, the GETOPTR ioctl is our cue that the application knows about the empty space and will fill it. We can always make the thing chase it's tail unconditionally, but then you risk playing total garbage when the application falls behind :-/ > so it runs through once and then stops. the final timeout is > waiting for a completion that's never going to come. > > Dec 4 23:33:50 lasn-001 kernel: Intel 810 + AC97 Audio, version 0.07, > 23:28:08 Dec 4 2001 > Dec 4 23:33:50 lasn-001 kernel: PCI: Setting latency timer of device > 00:1f.5 to 64 > Dec 4 23:33:50 lasn-001 kernel: i810: Intel ICH 82801AA found at IO > 0x2400 and 0x2000, IRQ 17 > Dec 4 23:33:51 lasn-001 kernel: i810_audio: Audio Controller supports 2 > channels. > Dec 4 23:33:51 lasn-001 kernel: ac97_codec: AC97 Audio codec, id: > 0x4144:0x5360 (Analog Devices AD1885) > Dec 4 23:33:51 lasn-001 kernel: i810_audio: AC'97 codec 0 Unable to map > surround DAC's (or DAC's not present), total channels = 2 > Dec 4 23:33:51 lasn-001 kernel: i810_audio: setting clocking to 41231 > Dec 4 23:34:00 lasn-001 kernel: NVRM: AGPGART: allocated 257 pages > Dec 4 23:34:00 lasn-001 kernel: NVRM: AGPGART: allocated 128 pages > Dec 4 23:34:00 lasn-001 kernel: CHANNEL NUM 1 PORT 10 IRQ ( ST8 DAC HWP > 16384,0,16384 > Dec 4 23:34:00 lasn-001 kernel: COMP 8 ) > Dec 4 23:34:01 lasn-001 kernel: CHANNEL NUM 1 PORT 10 IRQ ( ST8 DAC HWP > 32768,16384,16384 > Dec 4 23:34:01 lasn-001 kernel: COMP 16 ) > Dec 4 23:34:01 lasn-001 kernel: CHANNEL NUM 1 PORT 10 IRQ ( ST8 DAC HWP > 49152,32768,16384 > Dec 4 23:34:01 lasn-001 kernel: COMP 24 ) > Dec 4 23:34:01 lasn-001 kernel: CHANNEL NUM 1 PORT 10 IRQ ( ST15 DAC > HWP 65536,49152,16384 > Dec 4 23:34:01 lasn-001 kernel: COMP 32 DAC HWP 65536,65536,0 > Dec 4 23:34:01 lasn-001 kernel: LVI DAC HWP 65536,65536,0 > Dec 4 23:34:01 lasn-001 kernel: DCH - STOP ) > Dec 4 23:34:02 lasn-001 kernel: cdrom: open failed. > Dec 4 23:34:03 lasn-001 kernel: DAC HWP 65536,65536,0 Interesting...two seconds after the buffer ran out of data, quake *finally* calls one of the ioctls that then calls i810_update_ptrs()... > Dec 4 23:34:07 lasn-001 kernel: NVRM: AGPGART: freed 128 pages > Dec 4 23:34:07 lasn-001 kernel: NVRM: AGPGART: freed 257 pages > Dec 4 23:34:07 lasn-001 kernel: DAC HWP 65536,65536,0 > Dec 4 23:34:10 lasn-001 kernel: i810_audio: drain_dac, dma timeout? I see no reason to drain the dac on close for mmaped stuff. The application can check GETOPTR to see if the last stuff has played if it really cares that much. I'm going to skip the drain_dac() calls on mmap from now on. That will solve that problem (and it's also the right thing to do if we are chasing our tail and have set the software pointer to God only knows where as far as the final sounds are concerned). > -- Doug Ledford <dledford@redhat.com> http://people.redhat.com/dledford Please check my web site for aic7xxx updates/answers before e-mailing me about problems ^ permalink raw reply [flat|nested] 56+ messages in thread
* Re: i810 audio patch 2001-12-05 5:10 ` Doug Ledford @ 2001-12-05 5:35 ` Nathan Bryant 2001-12-05 7:24 ` Nathan Bryant 1 sibling, 0 replies; 56+ messages in thread From: Nathan Bryant @ 2001-12-05 5:35 UTC (permalink / raw) To: Doug Ledford; +Cc: Linux Kernel Mailing List, Mario Mikocevic Doug Ledford wrote: > Interesting...two seconds after the buffer ran out of data, quake > *finally* calls one of the ioctls that then calls i810_update_ptrs()... mmap followed by SETTRIGGER is part of the sound init routine, in WinQuake/snd_linux.c. they probably call that on startup and don't get around to playing any sound until the rest of the game has booted up. ^ permalink raw reply [flat|nested] 56+ messages in thread
* Re: i810 audio patch 2001-12-05 5:10 ` Doug Ledford 2001-12-05 5:35 ` Nathan Bryant @ 2001-12-05 7:24 ` Nathan Bryant 1 sibling, 0 replies; 56+ messages in thread From: Nathan Bryant @ 2001-12-05 7:24 UTC (permalink / raw) To: Doug Ledford; +Cc: Linux Kernel Mailing List, Mario Mikocevic Doug Ledford wrote: > Yes and no. We aren't chasing our tail, but that's because the > application is suppossed to call the GETOPTR ioctl in order to trigger > a pointer update. In short, the GETOPTR ioctl is our cue that the > application knows about the empty space and will fill it. We can > always make the thing chase it's tail unconditionally, but then you > risk playing total garbage when the application falls behind :-/ This is what happens under most of the drivers i've played quake with (under DOS too, I think). OSS and OSS/Free, and most of the other PCI drivers I've looked at, I believe they don't actually program the DMA engine during GETOPTR calls. Actually one could argue that in the case of quake it's better to let it chase its tail indefinitely (that's what they seem to have assumed when they wrote the game anyway according to comments in the source code) because that allows ambient sounds to continue uninterrupted during some slowdown, eg possible network congestion. (The side effect is that sometimes you end up with endlessly repeating weapon sound effects if you fire during congestion but of course that coincidence happens less often than congestion itself) > I see no reason to drain the dac on close for mmaped stuff. The > application can check GETOPTR to see if the last stuff has played if > it really cares that much. I'm going to skip the drain_dac() calls on > mmap from now on. That will solve that problem (and it's also the > right thing to do if we are chasing our tail and have set the software > pointer to God only knows where as far as the final sounds are > concerned). yep... ^ permalink raw reply [flat|nested] 56+ messages in thread
* Re: i810 audio patch 2001-12-04 22:29 ` Nathan Bryant 2001-12-04 22:49 ` Nathan Bryant @ 2001-12-04 23:05 ` Doug Ledford 1 sibling, 0 replies; 56+ messages in thread From: Doug Ledford @ 2001-12-04 23:05 UTC (permalink / raw) To: Nathan Bryant; +Cc: Mario Mikocevic, Linux Kernel Mailing List Nathan Bryant wrote: > Doug Ledford wrote: > >> Probably not. Although I did change it back but then change it in >> another way. Use the attached patch to back out those changes and let >> me know if it works (for some reason, I doubt it). > > > Fascinating... > > Your patch to i810_poll fixes the sleep of death. and with the rest of > the patches in 0.07, select() works a lot better but still not perfectly. That's because my previous patch would set the poll mask and return on the first call in because there was space already available. However, the initial call into poll() at the vfs layer evidently sets the state of the process to interruptible sleep, and then poll_wait() sets it back to running. So, when I skipped the call to poll_wait(), I wasn't manually setting the task state back to running, and as a result the code would return, but the calling program (artsd) would be set to a sleeping state in the scheduler and would never get woken back up. An alternative fix would have been to set the task state to running before leaving the poll function manually instead of relying upon poll_wait() to do it for us. > xmms+artsd is likely to play sound for quite a while, *until* I do > something that causes another process to be scheduled, like click on the > Mozilla window that's sitting in the background. At that point, it > reverts to the behavior where select() doesn't return properly. And > stays that way. > > this may be due to an output underrun... or i suppose lost interrupt is > also possible. > > i think it might be wise to use > get_available_read_data/get_free_write_space from i810_poll instead of > dmabuf->count directly. i'll try this and see if it works... > -- Doug Ledford <dledford@redhat.com> http://people.redhat.com/dledford Please check my web site for aic7xxx updates/answers before e-mailing me about problems ^ permalink raw reply [flat|nested] 56+ messages in thread
* Re: i810 audio patch 2001-12-04 5:18 ` Nathan Bryant 2001-12-04 5:40 ` Doug Ledford @ 2001-12-04 9:03 ` Alan Cox 1 sibling, 0 replies; 56+ messages in thread From: Alan Cox @ 2001-12-04 9:03 UTC (permalink / raw) To: Nathan Bryant; +Cc: Doug Ledford, Linux Kernel Mailing List > So there may be some VM/buffer related problem lurking under the covers > still. Originally the oops popped up in kswapd, for me, but I can't > trigger it again. I've seen multiple reports of random kswapd oopses in 2.4.16 so while it could be that the i810 code introduced a bug its also quite possible you hit an underlying flaw Alan ^ permalink raw reply [flat|nested] 56+ messages in thread
* Re: i810 audio patch
@ 2001-12-06 19:49 Nathan Bryant
0 siblings, 0 replies; 56+ messages in thread
From: Nathan Bryant @ 2001-12-06 19:49 UTC (permalink / raw)
To: pascal.junod; +Cc: Linux Kernel Mailing List
That timeout is for the modem codec. The primary, audio codec seems to have initialized properly.
> kernel: Intel 810 + AC97 Audio, version 0.10, 17:31:53 Dec 6 2001
> kernel: PCI: Setting latency timer of device 00:1f.5 to 64
> kernel: i810: Intel ICH3 found at IO 0x18c0 and 0x1c00, IRQ 9
> kernel: i810_audio: Audio Controller supports 6 channels.
> kernel: ac97_codec: AC97 Audio codec, id: 0x4144:0x5348 (Analog Devices AD1881A)
> kernel: i810_audio: AC'97 codec 0 Unable to map surround DAC's (or DAC's not present), total channels = 2
> kernel: ac97_codec: AC97 Modem codec, id: 0x4358:0x5421 (Unknown)
> kernel: i810_audio: timed out waiting for codec 1 analog ready
^ permalink raw reply [flat|nested] 56+ messages in threadend of thread, other threads:[~2001-12-06 19:49 UTC | newest]
Thread overview: 56+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2001-12-04 0:20 i810 audio patch Nathan Bryant
2001-12-04 4:26 ` Doug Ledford
[not found] ` <3C0C58DE.9020703@optonline.net>
2001-12-04 5:18 ` Nathan Bryant
2001-12-04 5:40 ` Doug Ledford
2001-12-04 6:07 ` Nathan Bryant
2001-12-04 7:08 ` Nathan Bryant
2001-12-04 16:46 ` Doug Ledford
2001-12-04 20:14 ` Nathan Bryant
2001-12-04 20:16 ` Doug Ledford
2001-12-04 14:35 ` Mario Mikocevic
2001-12-04 19:02 ` Nathan Bryant
2001-12-04 19:21 ` Doug Ledford
2001-12-04 20:41 ` Nathan Bryant
2001-12-04 21:15 ` Doug Ledford
2001-12-04 21:39 ` Nathan Bryant
2001-12-04 21:53 ` Nathan Bryant
2001-12-04 22:29 ` Nathan Bryant
2001-12-04 22:49 ` Nathan Bryant
2001-12-04 23:09 ` Doug Ledford
2001-12-04 23:31 ` Nathan Bryant
2001-12-04 23:44 ` Doug Ledford
2001-12-05 1:26 ` Nathan Bryant
2001-12-05 2:48 ` Nathan Bryant
2001-12-05 3:05 ` Doug Ledford
2001-12-05 3:28 ` Nathan Bryant
2001-12-05 4:25 ` Doug Ledford
2001-12-05 5:14 ` Nathan Bryant
2001-12-05 5:23 ` Doug Ledford
2001-12-05 20:04 ` Nathan Bryant
2001-12-05 20:05 ` Nathan Bryant
2001-12-05 20:10 ` Doug Ledford
2001-12-05 21:12 ` Nathan Bryant
2001-12-05 21:25 ` Doug Ledford
2001-12-05 21:36 ` Nathan Bryant
2001-12-05 21:56 ` Nathan Bryant
2001-12-05 22:31 ` Doug Ledford
2001-12-05 22:43 ` Doug Ledford
2001-12-05 23:46 ` Nathan Bryant
2001-12-05 23:51 ` Doug Ledford
2001-12-05 23:57 ` Nathan Bryant
2001-12-06 0:25 ` Doug Ledford
2001-12-06 0:50 ` Nathan Bryant
[not found] ` <3C0EC0ED.3000603@optonl! ine.net>
2001-12-06 0:55 ` Doug Ledford
[not found] ` <3C0EC219.8010107@redhat! .com>
2001-12-06 2:53 ` Nathan Bryant
[not found] ` <3C0EDDC2.608@optonl! ine.net>
2001-12-06 3:39 ` Doug Ledford
[not found] ` <3C0EC219.8010107@redhat!.com>
[not found] ` <3C0EE865.1090607@red! hat.com>
2001-12-06 4:02 ` Nathan Bryant
2001-12-06 4:09 ` Doug Ledford
2001-12-06 15:45 ` i810 audio patch (it _works_ for me :) Mario Mikocevic
2001-12-06 17:00 ` i810 audio patch Pascal Junod
2001-12-05 4:41 ` Nathan Bryant
2001-12-05 5:10 ` Doug Ledford
2001-12-05 5:35 ` Nathan Bryant
2001-12-05 7:24 ` Nathan Bryant
2001-12-04 23:05 ` Doug Ledford
2001-12-04 9:03 ` Alan Cox
-- strict thread matches above, loose matches on Subject: below --
2001-12-06 19:49 Nathan Bryant
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox