Re: i810 audio patch

Doug Ledford (dledford@redhat.com)
Tue, 04 Dec 2001 00:40:28 -0500


This is a multi-part message in MIME format.
--------------080901050900000908040803
Content-Type: text/plain; charset=us-ascii; format=flowed
Content-Transfer-Encoding: 7bit

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

--------------080901050900000908040803 Content-Type: text/plain; name="i810_audio-0.06.patch" Content-Transfer-Encoding: 7bit Content-Disposition: inline; filename="i810_audio-0.06.patch"

--- 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(); }

--------------080901050900000908040803--

- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/