Merge branch 'fix/misc' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound-2.6
* 'fix/misc' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound-2.6: ALSA: lx6464es - remove unused struct member ALSA: lx6464es - cleanup of rmh message bus function ALSA: pcm - Simplify snd_pcm_drain() implementation
This commit is contained in:
commit
0c9af28074
@ -1387,11 +1387,6 @@ static struct action_ops snd_pcm_action_drain_init = {
|
|||||||
.post_action = snd_pcm_post_drain_init
|
.post_action = snd_pcm_post_drain_init
|
||||||
};
|
};
|
||||||
|
|
||||||
struct drain_rec {
|
|
||||||
struct snd_pcm_substream *substream;
|
|
||||||
wait_queue_t wait;
|
|
||||||
};
|
|
||||||
|
|
||||||
static int snd_pcm_drop(struct snd_pcm_substream *substream);
|
static int snd_pcm_drop(struct snd_pcm_substream *substream);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -1407,10 +1402,9 @@ static int snd_pcm_drain(struct snd_pcm_substream *substream,
|
|||||||
struct snd_card *card;
|
struct snd_card *card;
|
||||||
struct snd_pcm_runtime *runtime;
|
struct snd_pcm_runtime *runtime;
|
||||||
struct snd_pcm_substream *s;
|
struct snd_pcm_substream *s;
|
||||||
|
wait_queue_t wait;
|
||||||
int result = 0;
|
int result = 0;
|
||||||
int i, num_drecs;
|
|
||||||
int nonblock = 0;
|
int nonblock = 0;
|
||||||
struct drain_rec *drec, drec_tmp, *d;
|
|
||||||
|
|
||||||
card = substream->pcm->card;
|
card = substream->pcm->card;
|
||||||
runtime = substream->runtime;
|
runtime = substream->runtime;
|
||||||
@ -1433,38 +1427,10 @@ static int snd_pcm_drain(struct snd_pcm_substream *substream,
|
|||||||
} else if (substream->f_flags & O_NONBLOCK)
|
} else if (substream->f_flags & O_NONBLOCK)
|
||||||
nonblock = 1;
|
nonblock = 1;
|
||||||
|
|
||||||
if (nonblock)
|
|
||||||
goto lock; /* no need to allocate waitqueues */
|
|
||||||
|
|
||||||
/* allocate temporary record for drain sync */
|
|
||||||
down_read(&snd_pcm_link_rwsem);
|
down_read(&snd_pcm_link_rwsem);
|
||||||
if (snd_pcm_stream_linked(substream)) {
|
|
||||||
drec = kmalloc(substream->group->count * sizeof(*drec), GFP_KERNEL);
|
|
||||||
if (! drec) {
|
|
||||||
up_read(&snd_pcm_link_rwsem);
|
|
||||||
snd_power_unlock(card);
|
|
||||||
return -ENOMEM;
|
|
||||||
}
|
|
||||||
} else
|
|
||||||
drec = &drec_tmp;
|
|
||||||
|
|
||||||
/* count only playback streams */
|
|
||||||
num_drecs = 0;
|
|
||||||
snd_pcm_group_for_each_entry(s, substream) {
|
|
||||||
runtime = s->runtime;
|
|
||||||
if (s->stream == SNDRV_PCM_STREAM_PLAYBACK) {
|
|
||||||
d = &drec[num_drecs++];
|
|
||||||
d->substream = s;
|
|
||||||
init_waitqueue_entry(&d->wait, current);
|
|
||||||
add_wait_queue(&runtime->sleep, &d->wait);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
up_read(&snd_pcm_link_rwsem);
|
|
||||||
|
|
||||||
lock:
|
|
||||||
snd_pcm_stream_lock_irq(substream);
|
snd_pcm_stream_lock_irq(substream);
|
||||||
/* resume pause */
|
/* resume pause */
|
||||||
if (substream->runtime->status->state == SNDRV_PCM_STATE_PAUSED)
|
if (runtime->status->state == SNDRV_PCM_STATE_PAUSED)
|
||||||
snd_pcm_pause(substream, 0);
|
snd_pcm_pause(substream, 0);
|
||||||
|
|
||||||
/* pre-start/stop - all running streams are changed to DRAINING state */
|
/* pre-start/stop - all running streams are changed to DRAINING state */
|
||||||
@ -1479,25 +1445,35 @@ static int snd_pcm_drain(struct snd_pcm_substream *substream,
|
|||||||
|
|
||||||
for (;;) {
|
for (;;) {
|
||||||
long tout;
|
long tout;
|
||||||
|
struct snd_pcm_runtime *to_check;
|
||||||
if (signal_pending(current)) {
|
if (signal_pending(current)) {
|
||||||
result = -ERESTARTSYS;
|
result = -ERESTARTSYS;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
/* all finished? */
|
/* find a substream to drain */
|
||||||
for (i = 0; i < num_drecs; i++) {
|
to_check = NULL;
|
||||||
runtime = drec[i].substream->runtime;
|
snd_pcm_group_for_each_entry(s, substream) {
|
||||||
if (runtime->status->state == SNDRV_PCM_STATE_DRAINING)
|
if (s->stream != SNDRV_PCM_STREAM_PLAYBACK)
|
||||||
|
continue;
|
||||||
|
runtime = s->runtime;
|
||||||
|
if (runtime->status->state == SNDRV_PCM_STATE_DRAINING) {
|
||||||
|
to_check = runtime;
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (i == num_drecs)
|
if (!to_check)
|
||||||
break; /* yes, all drained */
|
break; /* all drained */
|
||||||
|
init_waitqueue_entry(&wait, current);
|
||||||
|
add_wait_queue(&to_check->sleep, &wait);
|
||||||
set_current_state(TASK_INTERRUPTIBLE);
|
set_current_state(TASK_INTERRUPTIBLE);
|
||||||
snd_pcm_stream_unlock_irq(substream);
|
snd_pcm_stream_unlock_irq(substream);
|
||||||
|
up_read(&snd_pcm_link_rwsem);
|
||||||
snd_power_unlock(card);
|
snd_power_unlock(card);
|
||||||
tout = schedule_timeout(10 * HZ);
|
tout = schedule_timeout(10 * HZ);
|
||||||
snd_power_lock(card);
|
snd_power_lock(card);
|
||||||
|
down_read(&snd_pcm_link_rwsem);
|
||||||
snd_pcm_stream_lock_irq(substream);
|
snd_pcm_stream_lock_irq(substream);
|
||||||
|
remove_wait_queue(&to_check->sleep, &wait);
|
||||||
if (tout == 0) {
|
if (tout == 0) {
|
||||||
if (substream->runtime->status->state == SNDRV_PCM_STATE_SUSPENDED)
|
if (substream->runtime->status->state == SNDRV_PCM_STATE_SUSPENDED)
|
||||||
result = -ESTRPIPE;
|
result = -ESTRPIPE;
|
||||||
@ -1512,16 +1488,7 @@ static int snd_pcm_drain(struct snd_pcm_substream *substream,
|
|||||||
|
|
||||||
unlock:
|
unlock:
|
||||||
snd_pcm_stream_unlock_irq(substream);
|
snd_pcm_stream_unlock_irq(substream);
|
||||||
|
up_read(&snd_pcm_link_rwsem);
|
||||||
if (!nonblock) {
|
|
||||||
for (i = 0; i < num_drecs; i++) {
|
|
||||||
d = &drec[i];
|
|
||||||
runtime = d->substream->runtime;
|
|
||||||
remove_wait_queue(&runtime->sleep, &d->wait);
|
|
||||||
}
|
|
||||||
if (drec != &drec_tmp)
|
|
||||||
kfree(drec);
|
|
||||||
}
|
|
||||||
snd_power_unlock(card);
|
snd_power_unlock(card);
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
|
@ -86,7 +86,6 @@ struct lx6464es {
|
|||||||
|
|
||||||
/* messaging */
|
/* messaging */
|
||||||
spinlock_t msg_lock; /* message spinlock */
|
spinlock_t msg_lock; /* message spinlock */
|
||||||
atomic_t send_message_locked;
|
|
||||||
struct lx_rmh rmh;
|
struct lx_rmh rmh;
|
||||||
|
|
||||||
/* configuration */
|
/* configuration */
|
||||||
@ -95,7 +94,6 @@ struct lx6464es {
|
|||||||
uint hardware_running[2];
|
uint hardware_running[2];
|
||||||
u32 board_sample_rate; /* sample rate read from
|
u32 board_sample_rate; /* sample rate read from
|
||||||
* board */
|
* board */
|
||||||
u32 sample_rate; /* our sample rate */
|
|
||||||
u16 pcm_granularity; /* board blocksize */
|
u16 pcm_granularity; /* board blocksize */
|
||||||
|
|
||||||
/* dma */
|
/* dma */
|
||||||
|
@ -314,98 +314,6 @@ static inline void lx_message_dump(struct lx_rmh *rmh)
|
|||||||
#define XILINX_POLL_NO_SLEEP 100
|
#define XILINX_POLL_NO_SLEEP 100
|
||||||
#define XILINX_POLL_ITERATIONS 150
|
#define XILINX_POLL_ITERATIONS 150
|
||||||
|
|
||||||
#if 0 /* not used now */
|
|
||||||
static int lx_message_send(struct lx6464es *chip, struct lx_rmh *rmh)
|
|
||||||
{
|
|
||||||
u32 reg = ED_DSP_TIMED_OUT;
|
|
||||||
int dwloop;
|
|
||||||
int answer_received;
|
|
||||||
|
|
||||||
if (lx_dsp_reg_read(chip, eReg_CSM) & (Reg_CSM_MC | Reg_CSM_MR)) {
|
|
||||||
snd_printk(KERN_ERR LXP "PIOSendMessage eReg_CSM %x\n", reg);
|
|
||||||
return -EBUSY;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* write command */
|
|
||||||
lx_dsp_reg_writebuf(chip, eReg_CRM1, rmh->cmd, rmh->cmd_len);
|
|
||||||
|
|
||||||
snd_BUG_ON(atomic_read(&chip->send_message_locked) != 0);
|
|
||||||
atomic_set(&chip->send_message_locked, 1);
|
|
||||||
|
|
||||||
/* MicoBlaze gogogo */
|
|
||||||
lx_dsp_reg_write(chip, eReg_CSM, Reg_CSM_MC);
|
|
||||||
|
|
||||||
/* wait for interrupt to answer */
|
|
||||||
for (dwloop = 0; dwloop != XILINX_TIMEOUT_MS; ++dwloop) {
|
|
||||||
answer_received = atomic_read(&chip->send_message_locked);
|
|
||||||
if (answer_received == 0)
|
|
||||||
break;
|
|
||||||
msleep(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (answer_received == 0) {
|
|
||||||
/* in Debug mode verify Reg_CSM_MR */
|
|
||||||
snd_BUG_ON(!(lx_dsp_reg_read(chip, eReg_CSM) & Reg_CSM_MR));
|
|
||||||
|
|
||||||
/* command finished, read status */
|
|
||||||
if (rmh->dsp_stat == 0)
|
|
||||||
reg = lx_dsp_reg_read(chip, eReg_CRM1);
|
|
||||||
else
|
|
||||||
reg = 0;
|
|
||||||
} else {
|
|
||||||
int i;
|
|
||||||
snd_printk(KERN_WARNING LXP "TIMEOUT lx_message_send! "
|
|
||||||
"Interrupts disabled?\n");
|
|
||||||
|
|
||||||
/* attente bit Reg_CSM_MR */
|
|
||||||
for (i = 0; i != XILINX_POLL_ITERATIONS; i++) {
|
|
||||||
if ((lx_dsp_reg_read(chip, eReg_CSM) & Reg_CSM_MR)) {
|
|
||||||
if (rmh->dsp_stat == 0)
|
|
||||||
reg = lx_dsp_reg_read(chip, eReg_CRM1);
|
|
||||||
else
|
|
||||||
reg = 0;
|
|
||||||
goto polling_successful;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (i > XILINX_POLL_NO_SLEEP)
|
|
||||||
msleep(1);
|
|
||||||
}
|
|
||||||
snd_printk(KERN_WARNING LXP "TIMEOUT lx_message_send! "
|
|
||||||
"polling failed\n");
|
|
||||||
|
|
||||||
polling_successful:
|
|
||||||
atomic_set(&chip->send_message_locked, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((reg & ERROR_VALUE) == 0) {
|
|
||||||
/* read response */
|
|
||||||
if (rmh->stat_len) {
|
|
||||||
snd_BUG_ON(rmh->stat_len >= (REG_CRM_NUMBER-1));
|
|
||||||
|
|
||||||
lx_dsp_reg_readbuf(chip, eReg_CRM2, rmh->stat,
|
|
||||||
rmh->stat_len);
|
|
||||||
}
|
|
||||||
} else
|
|
||||||
snd_printk(KERN_WARNING LXP "lx_message_send: error_value %x\n",
|
|
||||||
reg);
|
|
||||||
|
|
||||||
/* clear Reg_CSM_MR */
|
|
||||||
lx_dsp_reg_write(chip, eReg_CSM, 0);
|
|
||||||
|
|
||||||
switch (reg) {
|
|
||||||
case ED_DSP_TIMED_OUT:
|
|
||||||
snd_printk(KERN_WARNING LXP "lx_message_send: dsp timeout\n");
|
|
||||||
return -ETIMEDOUT;
|
|
||||||
|
|
||||||
case ED_DSP_CRASHED:
|
|
||||||
snd_printk(KERN_WARNING LXP "lx_message_send: dsp crashed\n");
|
|
||||||
return -EAGAIN;
|
|
||||||
}
|
|
||||||
|
|
||||||
lx_message_dump(rmh);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
#endif /* not used now */
|
|
||||||
|
|
||||||
static int lx_message_send_atomic(struct lx6464es *chip, struct lx_rmh *rmh)
|
static int lx_message_send_atomic(struct lx6464es *chip, struct lx_rmh *rmh)
|
||||||
{
|
{
|
||||||
@ -423,7 +331,7 @@ static int lx_message_send_atomic(struct lx6464es *chip, struct lx_rmh *rmh)
|
|||||||
/* MicoBlaze gogogo */
|
/* MicoBlaze gogogo */
|
||||||
lx_dsp_reg_write(chip, eReg_CSM, Reg_CSM_MC);
|
lx_dsp_reg_write(chip, eReg_CSM, Reg_CSM_MC);
|
||||||
|
|
||||||
/* wait for interrupt to answer */
|
/* wait for device to answer */
|
||||||
for (dwloop = 0; dwloop != XILINX_TIMEOUT_MS * 1000; ++dwloop) {
|
for (dwloop = 0; dwloop != XILINX_TIMEOUT_MS * 1000; ++dwloop) {
|
||||||
if (lx_dsp_reg_read(chip, eReg_CSM) & Reg_CSM_MR) {
|
if (lx_dsp_reg_read(chip, eReg_CSM) & Reg_CSM_MR) {
|
||||||
if (rmh->dsp_stat == 0)
|
if (rmh->dsp_stat == 0)
|
||||||
@ -1175,10 +1083,6 @@ static int lx_interrupt_ack(struct lx6464es *chip, u32 *r_irqsrc,
|
|||||||
*r_async_escmd = 1;
|
*r_async_escmd = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (irqsrc & MASK_SYS_STATUS_CMD_DONE)
|
|
||||||
/* xilinx command notification */
|
|
||||||
atomic_set(&chip->send_message_locked, 0);
|
|
||||||
|
|
||||||
if (irq_async) {
|
if (irq_async) {
|
||||||
/* snd_printd("interrupt: async event pending\n"); */
|
/* snd_printd("interrupt: async event pending\n"); */
|
||||||
*r_async_pending = 1;
|
*r_async_pending = 1;
|
||||||
|
Loading…
Reference in New Issue
Block a user