Commit 60eaf398 authored by Jean-Paul Saman's avatar Jean-Paul Saman

davinci oss; rewrite to not use local_irq_{save,restore}

Use atomic types where possible and try minimizing the use of local_irq_{save,restore}.
parent 81a25387
......@@ -205,9 +205,10 @@ int audio_setup_buf(audio_stream_t * s)
}
s->usr_head = s->dma_head = s->dma_tail = 0;
AUDIO_QUEUE_INIT(s);
s->started = 0;
s->dma_started = 0;
atomic_set(&s->started, 0);
atomic_set(&s->dma_started, 0);
s->bytecount = 0;
s->fragcount = 0;
s->prevbuf = 0;
......@@ -217,6 +218,7 @@ int audio_setup_buf(audio_stream_t * s)
FN_OUT(0);
return 0;
err:
audio_discard_buf(s);
FN_OUT(1);
......@@ -372,20 +374,16 @@ int davinci_free_sound_dma(int master_ch, int **channels)
int audio_process_dma(audio_stream_t * s)
{
int ret = 0;
unsigned long flags;
FN_IN;
/* Dont let the ISR over ride touching the in_use flag */
local_irq_save(flags);
if (1 == s->in_use) {
local_irq_restore(flags);
if (1 == atomic_read(&s->in_use)) {
DPRINTK("Called again while In Use\n");
return 0;
}
s->in_use = 1;
local_irq_restore(flags);
atomic_set(&s->in_use, 1);
if (s->stopped)
if (atomic_read(&s->stopped) == 1)
goto spin;
if (s->dma_spinref > 0 && s->pending_frags) {
......@@ -418,7 +416,7 @@ int audio_process_dma(audio_stream_t * s)
}
}
spin:
if (s->spin_idle) {
if (atomic_read(&s->spin_idle) == 1) {
int spincnt = 0;
DPRINTK("we are spinning\n");
while (davinci_start_sound_dma(s, SPIN_ADDR, SPIN_SIZE) == 0)
......@@ -437,7 +435,7 @@ int audio_process_dma(audio_stream_t * s)
}
process_out:
s->in_use = 0;
atomic_set(&s->in_use, 0);
FN_OUT(ret);
return ret;
......@@ -452,6 +450,7 @@ int audio_process_dma(audio_stream_t * s)
void audio_prime_rx(audio_state_t * state)
{
audio_stream_t *is = state->input_stream;
audio_stream_t *os = state->output_stream;
FN_IN;
if (state->need_tx_for_rx) {
......@@ -463,15 +462,15 @@ void audio_prime_rx(audio_state_t * state)
* will spin with all zeroes. We use the cache flush special
* area for that.
*/
state->output_stream->spin_idle = 1;
audio_process_dma(state->output_stream);
atomic_set(&os->spin_idle, 1);
audio_process_dma(os);
}
is->pending_frags = is->nbfrags;
init_completion(&is->wfc);
is->wfc.done = 0;
is->active = 1;
atomic_set(&is->active, 1);
audio_process_dma(is);
FN_OUT(0);
......@@ -486,7 +485,7 @@ void audio_prime_rx(audio_state_t * state)
int audio_set_fragments(audio_stream_t * s, int val)
{
FN_IN;
if (s->active)
if (atomic_read(&s->active) == 1)
return -EBUSY;
if (s->buffers)
audio_discard_buf(s);
......@@ -519,7 +518,6 @@ int audio_sync(struct file *file)
audio_stream_t *s = state->output_stream;
audio_buf_t *b;
u_int shiftval = 0;
unsigned long flags;
DECLARE_WAITQUEUE(wait, current);
......@@ -548,7 +546,7 @@ int audio_sync(struct file *file)
* with the start pointer here and don't forget to restore
* it later.
*/
local_irq_save(flags);
mutex_lock(&state->mutex);
shiftval = s->fragsize - b->offset;
if (shiftval > 0) {
b->offset = shiftval;
......@@ -560,8 +558,8 @@ int audio_sync(struct file *file)
s->usr_head = 0;
s->pending_frags++;
mutex_unlock(&state->mutex);
audio_process_dma(s);
local_irq_restore(flags);
}
/* Let's wait for all buffers to complete */
......@@ -578,13 +576,13 @@ int audio_sync(struct file *file)
/* undo the pointer hack above */
if (shiftval > 0) {
local_irq_save(flags);
mutex_lock(&state->mutex);
b->dma_addr += shiftval;
b->data += shiftval;
/* ensure sane DMA code behavior if not yet processed */
if (b->offset != 0)
b->offset = s->fragsize;
local_irq_restore(flags);
mutex_unlock(&state->mutex);
}
FN_OUT(0);
......@@ -598,20 +596,16 @@ int audio_sync(struct file *file)
******************************************************************************/
void audio_stop_dma(audio_stream_t * s)
{
unsigned long flags;
FN_IN;
DPRINTK("audio_stop_dma\n");
if (s->dma_spinref > 0 || !s->buffers)
return;
local_irq_save(flags);
davinci_stop_dma(s->master_ch);
s->dma_started = 0;
atomic_set(&s->dma_started, 0);
if (s->spin_idle) {
if (atomic_read(&s->spin_idle) == 1) {
#if 0
DMA_START(s, SPIN_ADDR, SPIN_SIZE);
DMA_START(s, SPIN_ADDR, SPIN_SIZE);
......@@ -620,8 +614,6 @@ void audio_stop_dma(audio_stream_t * s)
} else
s->dma_spinref = 0;
local_irq_restore(flags);
FN_OUT(0);
return;
}
......@@ -667,9 +659,8 @@ void audio_reset(audio_stream_t * s)
audio_buf_t *b;
FN_IN;
if (s->buffers) {
davinci_mcbsp_stop(0);
s->started = 0;
atomic_set(&s->started, 0);
audio_stop_dma(s);
/* back up pointers to be ready to restart from the same spot */
while (s->dma_head != s->dma_tail) {
......@@ -697,8 +688,10 @@ void audio_reset(audio_stream_t * s)
s->wfc.done = s->nbfrags;
}
AUDIO_QUEUE_INIT(s);
s->active = 0;
s->stopped = 0;
atomic_set(&s->in_use, 0);
atomic_set(&s->active, 0);
atomic_set(&s->stopped, 0);
FN_OUT(0);
return;
......@@ -763,18 +756,18 @@ static int audio_start_dma_chain(audio_stream_t * s)
int channel = s->lch[s->dma_q_head];
FN_IN;
if (!s->dma_started) {
if (atomic_read(&s->dma_started) == 0) {
edmacc_paramentry_regs temp;
davinci_get_dma_params(channel, &temp);
davinci_set_dma_params(s->master_ch, &temp);
davinci_start_dma(s->master_ch);
s->dma_started = 1;
atomic_set(&s->dma_started, 1);
}
if (!s->started) {
if (atomic_read(&s->started) == 0) {
davinci_mcbsp_start(0);
s->started = 1;
atomic_set(&s->started, 1);
}
/* else the dma itself will progress forward with out our help */
......@@ -978,7 +971,6 @@ static void audio_dma_callback(int lch, u16 ch_status, void *data)
if (!s->mapped) {
complete(&s->wfc);
s->done_flag = 1;
} else
s->pending_frags++;
......
......@@ -203,19 +203,19 @@ static int audio_ldm_suspend(void *data)
int stopstate;
if (is && is->buffers) {
DPRINTK("IS Suspend\n");
stopstate = is->stopped;
stopstate = atomic_read(&is->stopped);
audio_stop_dma(is);
DMA_CLEAR(is);
is->dma_spinref = 0;
is->stopped = stopstate;
atomic_set(&is->stopped, stopstate);
}
if (os && os->buffers) {
DPRINTK("OS Suspend\n");
stopstate = os->stopped;
stopstate = atomic_read(&os->stopped);
audio_stop_dma(os);
DMA_CLEAR(os);
os->dma_spinref = 0;
os->stopped = stopstate;
atomic_set(&os->stopped, stopstate);
}
#endif
}
......@@ -438,6 +438,10 @@ int audio_register_codec(audio_state_t * codec_state)
}
memcpy(&audio_state, codec_state, sizeof(audio_state_t));
atomic_set(&audio_state.output_stream->in_use, 0);
atomic_set(&audio_state.input_stream->in_use, 0);
mutex_init(&audio_state.mutex);
ret = platform_device_register(&davinci_audio_device);
......@@ -508,7 +512,6 @@ audio_write(struct file *file, const char *buffer, size_t count, loff_t * ppos)
audio_state_t *state = file->private_data;
audio_stream_t *s = state->output_stream;
int chunksize, ret = 0;
unsigned long flags;
DPRINTK("audio_write: count=%d\n", count);
if (*ppos != file->f_pos) {
......@@ -534,9 +537,9 @@ audio_write(struct file *file, const char *buffer, size_t count, loff_t * ppos)
ret = -EAGAIN;
break;
} else {
local_irq_save(flags);
mutex_lock(&state->mutex);
s->wfc.done--;
local_irq_restore(flags);
mutex_unlock(&state->mutex);
}
} else {
ret = -ERESTARTSYS;
......@@ -565,14 +568,14 @@ audio_write(struct file *file, const char *buffer, size_t count, loff_t * ppos)
}
/* Update pointers and send current fragment to DMA */
local_irq_save(flags);
mutex_lock(&state->mutex);
b->offset = 0;
if (++s->usr_head >= s->nbfrags)
s->usr_head = 0;
/* Add the num of frags pending */
s->pending_frags++;
s->active = 1;
local_irq_restore(flags);
mutex_unlock(&state->mutex);
atomic_set(&s->active, 1);
audio_process_dma(s);
}
......@@ -595,7 +598,6 @@ audio_read(struct file *file, char __user *buffer, size_t count, loff_t * ppos)
audio_state_t *state = file->private_data;
audio_stream_t *s = state->input_stream;
int chunksize, ret = 0;
unsigned long flags;
DPRINTK("audio_read: count=%d\n", count);
......@@ -609,7 +611,7 @@ audio_read(struct file *file, char __user *buffer, size_t count, loff_t * ppos)
return -ENXIO;
}
if (!s->active) {
if (atomic_read(&s->active) == 0) {
if (!s->buffers && audio_setup_buf(s)) {
DPRINTK("AudioRead - No Memory\n");
return -ENOMEM;
......@@ -626,9 +628,9 @@ audio_read(struct file *file, char __user *buffer, size_t count, loff_t * ppos)
ret = -EAGAIN;
break;
} else {
local_irq_save(flags);
mutex_lock(&state->mutex);
s->wfc.done--;
local_irq_restore(flags);
mutex_unlock(&state->mutex);
}
} else {
ret = -ERESTARTSYS;
......@@ -655,17 +657,16 @@ audio_read(struct file *file, char __user *buffer, size_t count, loff_t * ppos)
}
/* Update pointers and return current fragment to DMA */
local_irq_save(flags);
mutex_lock(&state->mutex);
b->offset = 0;
if (++s->usr_head >= s->nbfrags)
s->usr_head = 0;
s->pending_frags++;
local_irq_restore(flags);
mutex_unlock(&state->mutex);
DPRINTK(KERN_INFO
"calling audio_process_dma from audio_read\n");
audio_process_dma(s);
s->done_flag = 0;
}
if ((buffer - buffer0))
......@@ -748,7 +749,7 @@ audio_poll(struct file *file, struct poll_table_struct *wait)
if (file->f_mode & FMODE_READ) {
/* Start audio input if not already active */
if (!is->active) {
if (atomic_read(&is->active) == 0) {
if (!is->buffers && audio_setup_buf(is))
return -ENOMEM;
audio_prime_rx(state);
......@@ -872,9 +873,13 @@ audio_ioctl(struct inode *inode, struct file *file, uint cmd, ulong arg)
case SNDCTL_DSP_GETTRIGGER:
val = 0;
if (file->f_mode & FMODE_READ && is->active && !is->stopped)
if (file->f_mode & FMODE_READ &&
atomic_read(&is->active) &&
!atomic_read(&is->stopped))
val |= PCM_ENABLE_INPUT;
if (file->f_mode & FMODE_WRITE && os->active && !os->stopped)
if (file->f_mode & FMODE_WRITE &&
atomic_read(&os->active) &&
!atomic_read(&os->stopped))
val |= PCM_ENABLE_OUTPUT;
FN_OUT(11);
return put_user(val, (int *)arg);
......@@ -886,43 +891,39 @@ audio_ioctl(struct inode *inode, struct file *file, uint cmd, ulong arg)
}
if (file->f_mode & FMODE_READ) {
if (val & PCM_ENABLE_INPUT) {
unsigned long flags;
if (!is->active) {
if (atomic_read(&is->active) == 0) {
if (!is->buffers && audio_setup_buf(is)) {
FN_OUT(13);
return -ENOMEM;
}
audio_prime_rx(state);
}
local_irq_save(flags);
is->stopped = 0;
local_irq_restore(flags);
atomic_set(&is->stopped, 0);
audio_process_dma(is);
} else {
is->stopped = 1;
atomic_set(&is->stopped, 1);
audio_stop_dma(is);
}
}
if (file->f_mode & FMODE_WRITE) {
if (val & PCM_ENABLE_OUTPUT) {
unsigned long flags;
if (!os->buffers && audio_setup_buf(os)) {
FN_OUT(14);
return -ENOMEM;
}
local_irq_save(flags);
if (os->mapped && !os->pending_frags) {
mutex_lock(&state->mutex);
os->pending_frags = os->nbfrags;
init_completion(&os->wfc);
os->wfc.done = 0;
os->active = 1;
mutex_unlock(&state->mutex);
atomic_set(&os->active, 1);
}
os->stopped = 0;
local_irq_restore(flags);
atomic_set(&os->stopped, 0);
audio_process_dma(os);
} else {
os->stopped = 1;
atomic_set(&os->stopped, 1);
audio_stop_dma(os);
}
}
......@@ -936,25 +937,24 @@ audio_ioctl(struct inode *inode, struct file *file, uint cmd, ulong arg)
audio_stream_t *s =
(cmd == SNDCTL_DSP_GETOPTR) ? os : is;
int bytecount, offset;
unsigned long flags;
if ((s == is && !(file->f_mode & FMODE_READ)) ||
(s == os && !(file->f_mode & FMODE_WRITE))) {
FN_OUT(16);
return -EINVAL;
}
if (s->active) {
local_irq_save(flags);
if (atomic_read(&s->active) == 1) {
mutex_lock(&state->mutex);
offset = audio_get_dma_pos(s);
inf.ptr = s->dma_tail * s->fragsize + offset;
bytecount = s->bytecount + offset;
s->bytecount = -offset;
inf.blocks = s->fragcount;
s->fragcount = 0;
local_irq_restore(flags);
if (bytecount < 0)
bytecount = 0;
inf.bytes = bytecount;
mutex_unlock(&state->mutex);
}
FN_OUT(17);
return copy_to_user((void *)arg, &inf, sizeof(inf));
......@@ -977,6 +977,8 @@ audio_ioctl(struct inode *inode, struct file *file, uint cmd, ulong arg)
FN_OUT(19);
return -ENOMEM;
}
mutex_lock(&state->mutex);
b = &s->buffers[s->usr_head];
inf.bytes = s->wfc.done * s->fragsize;
inf.bytes -= b->offset;
......@@ -986,6 +988,7 @@ audio_ioctl(struct inode *inode, struct file *file, uint cmd, ulong arg)
inf.fragments = inf.bytes / s->fragsize;
inf.fragsize = s->fragsize;
inf.fragstotal = s->nbfrags;
mutex_unlock(&state->mutex);
FN_OUT(20);
return copy_to_user((void *)arg, &inf, sizeof(inf));
}
......@@ -999,10 +1002,7 @@ audio_ioctl(struct inode *inode, struct file *file, uint cmd, ulong arg)
if (file->f_mode & FMODE_READ) {
audio_reset(is);
if (state->need_tx_for_rx) {
unsigned long flags;
local_irq_save(flags);
os->spin_idle = 0;
local_irq_restore(flags);
atomic_set(&os->spin_idle, 0);
}
}
if (file->f_mode & FMODE_WRITE) {
......@@ -1119,7 +1119,6 @@ static int audio_open(struct inode *inode, struct file *file)
is->fragsize = AUDIO_FRAGSIZE_DEFAULT;
is->nbfrags = AUDIO_NBFRAGS_DEFAULT;
is->mapped = 0;
is->done_flag = 0;
init_waitqueue_head(&is->wq);
}
......@@ -1156,7 +1155,7 @@ static int audio_release(struct inode *inode, struct file *file)
DMA_FREE(is);
is->dma_spinref = 0;
if (state->need_tx_for_rx) {
os->spin_idle = 0;
atomic_set(&os->spin_idle, 0);
if (!state->wr_ref) {
DMA_FREE(os);
os->dma_spinref = 0;
......
......@@ -51,11 +51,11 @@ typedef struct {
u_int pending_frags; /* Fragments sent to DMA */
int dma_dev; /* device identifier for DMA */
u_int prevbuf; /* Prev pending frag size sent to DMA */
char started; /* to store if the chain was started or not */
atomic_t started; /* to store if the chain was started or not */
int dma_q_head; /* DMA Channel Q Head */
int dma_q_tail; /* DMA Channel Q Tail */
char dma_q_count; /* DMA Channel Q Count */
char in_use; /* Is this is use? */
atomic_t in_use; /* Is this is use? */
int master_ch;
int *lch; /* Chain of channels this stream is linked to */
int input_or_output; /* Direction of this data stream */
......@@ -65,11 +65,10 @@ typedef struct {
wait_queue_head_t wq; /* for poll */
int dma_spinref; /* DMA is spinning */
int mapped:1; /* mmap()'ed buffers */
int active:1; /* actually in progress */
int stopped:1; /* might be active but stopped */
int spin_idle:1; /* have DMA spin on zeros when idle */
int dma_started; /* to store if DMA was started or not */
int done_flag;
atomic_t active; /* actually in progress */
atomic_t stopped; /* might be active but stopped */
atomic_t spin_idle; /* have DMA spin on zeros when idle */
atomic_t dma_started; /* to store if DMA was started or not */
} audio_stream_t;
/*
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment