--- i810_audio.c-0.11 Fri Dec 7 08:29:51 2001 +++ i810_audio.c Fri Dec 7 14:37:30 2001 @@ -690,25 +690,35 @@ spin_unlock_irqrestore(&card->lock, flags); } -static inline void __start_adc(struct i810_state *state) +static inline int __start_adc(struct i810_state *state) { + int ret = 0; struct dmabuf *dmabuf = &state->dmabuf; + if ( ! (dmabuf->trigger & PCM_ENABLE_INPUT) ) { + printk (KERN_ERR "i810_audio: __start_adc called without PCM_ENABLE_INPUT set\n"); + dmabuf->trigger |= PCM_ENABLE_INPUT; + } + if (dmabuf->count < dmabuf->dmasize && dmabuf->ready && !dmabuf->enable && (dmabuf->trigger & PCM_ENABLE_INPUT)) { + ret = 1; dmabuf->enable |= ADC_RUNNING; outb((1<<4) | (1<<2) | 1, state->card->iobase + PI_CR); } + return ret; } -static void start_adc(struct i810_state *state) +static int start_adc(struct i810_state *state) { + int ret; struct i810_card *card = state->card; unsigned long flags; spin_lock_irqsave(&card->lock, flags); - __start_adc(state); + ret = __start_adc(state); spin_unlock_irqrestore(&card->lock, flags); + return ret; } /* stop playback (lock held) */ @@ -736,24 +746,34 @@ spin_unlock_irqrestore(&card->lock, flags); } -static inline void __start_dac(struct i810_state *state) +static inline int __start_dac(struct i810_state *state) { + int ret = 0; struct dmabuf *dmabuf = &state->dmabuf; + if ( ! (dmabuf->trigger & PCM_ENABLE_OUTPUT) ) { + printk (KERN_ERR "i810_audio: __start_adc called without PCM_ENABLE_INPUT set\n"); + dmabuf->trigger |= PCM_ENABLE_OUTPUT; + } + if (dmabuf->count > 0 && dmabuf->ready && !dmabuf->enable && (dmabuf->trigger & PCM_ENABLE_OUTPUT)) { + ret = 1; dmabuf->enable |= DAC_RUNNING; outb((1<<4) | (1<<2) | 1, state->card->iobase + PO_CR); } + return ret; } -static void start_dac(struct i810_state *state) +static int start_dac(struct i810_state *state) { + int ret; struct i810_card *card = state->card; unsigned long flags; spin_lock_irqsave(&card->lock, flags); - __start_dac(state); + ret = __start_dac(state); spin_unlock_irqrestore(&card->lock, flags); + return ret; } #define DMABUF_DEFAULTORDER (16-PAGE_SHIFT) @@ -936,7 +956,7 @@ static void __i810_update_lvi(struct i810_state *state, int rec) { struct dmabuf *dmabuf = &state->dmabuf; - int x, port; + int x, port, ok; port = state->card->iobase; if(rec) @@ -955,11 +975,13 @@ if (!dmabuf->enable) { outb((inb(port+OFF_CIV)+1)&31, port+OFF_LVI); if(rec) { - __start_adc(state); + ok = __start_adc(state); } else { - __start_dac(state); + ok = __start_dac(state); + } + if (ok) { + while( !(inb(port + OFF_CR) & ((1<<4) | (1<<2))) ) ; } - while( !(inb(port + OFF_CR) & ((1<<4) | (1<<2))) ) ; } /* swptr - 1 is the tail of our transfer */ @@ -1509,6 +1531,12 @@ x = dmabuf->fragsize - (swptr % dmabuf->fragsize); memset(dmabuf->rawbuf + swptr, '\0', x); } + // There is data waiting to be played + /* + * Force the trigger setting since we would + * deadlock with it set any other way + */ + dmabuf->trigger = PCM_ENABLE_OUTPUT; i810_update_lvi(state,0); ret: set_current_state(TASK_RUNNING);