ALSA: vx: Use nonatomic PCM ops
Rewrite VXpocket and VX222 drivers to use the new PCM nonatomic ops. The former irq tasklet is replaced with a threaded irq handler, and the tasklet for the PCM delayed start is simply merged into the normal PCM trigger, as well as the replacement of spinlock with mutex. Signed-off-by: Takashi Iwai <tiwai@suse.de>
This commit is contained in:
parent
e7e69265b6
commit
db0a5214b8
@ -80,8 +80,6 @@ struct vx_pipe {
|
|||||||
|
|
||||||
unsigned int references; /* an output pipe may be used for monitoring and/or playback */
|
unsigned int references; /* an output pipe may be used for monitoring and/or playback */
|
||||||
struct vx_pipe *monitoring_pipe; /* pointer to the monitoring pipe (capture pipe only)*/
|
struct vx_pipe *monitoring_pipe; /* pointer to the monitoring pipe (capture pipe only)*/
|
||||||
|
|
||||||
struct tasklet_struct start_tq;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct vx_core;
|
struct vx_core;
|
||||||
@ -165,9 +163,7 @@ struct vx_core {
|
|||||||
struct snd_vx_hardware *hw;
|
struct snd_vx_hardware *hw;
|
||||||
struct snd_vx_ops *ops;
|
struct snd_vx_ops *ops;
|
||||||
|
|
||||||
spinlock_t lock;
|
struct mutex lock;
|
||||||
spinlock_t irq_lock;
|
|
||||||
struct tasklet_struct tq;
|
|
||||||
|
|
||||||
unsigned int chip_status;
|
unsigned int chip_status;
|
||||||
unsigned int pcm_running;
|
unsigned int pcm_running;
|
||||||
@ -223,6 +219,7 @@ void snd_vx_free_firmware(struct vx_core *chip);
|
|||||||
* interrupt handler; exported for pcmcia
|
* interrupt handler; exported for pcmcia
|
||||||
*/
|
*/
|
||||||
irqreturn_t snd_vx_irq_handler(int irq, void *dev);
|
irqreturn_t snd_vx_irq_handler(int irq, void *dev);
|
||||||
|
irqreturn_t snd_vx_threaded_irq_handler(int irq, void *dev);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* lowlevel functions
|
* lowlevel functions
|
||||||
|
@ -117,7 +117,7 @@ static int vx_reset_chk(struct vx_core *chip)
|
|||||||
*
|
*
|
||||||
* returns 0 if successful, or a negative error code.
|
* returns 0 if successful, or a negative error code.
|
||||||
* the error code can be VX-specific, retrieved via vx_get_error().
|
* the error code can be VX-specific, retrieved via vx_get_error().
|
||||||
* NB: call with spinlock held!
|
* NB: call with mutex held!
|
||||||
*/
|
*/
|
||||||
static int vx_transfer_end(struct vx_core *chip, int cmd)
|
static int vx_transfer_end(struct vx_core *chip, int cmd)
|
||||||
{
|
{
|
||||||
@ -155,7 +155,7 @@ static int vx_transfer_end(struct vx_core *chip, int cmd)
|
|||||||
*
|
*
|
||||||
* returns 0 if successful, or a negative error code.
|
* returns 0 if successful, or a negative error code.
|
||||||
* the error code can be VX-specific, retrieved via vx_get_error().
|
* the error code can be VX-specific, retrieved via vx_get_error().
|
||||||
* NB: call with spinlock held!
|
* NB: call with mutex held!
|
||||||
*/
|
*/
|
||||||
static int vx_read_status(struct vx_core *chip, struct vx_rmh *rmh)
|
static int vx_read_status(struct vx_core *chip, struct vx_rmh *rmh)
|
||||||
{
|
{
|
||||||
@ -236,7 +236,7 @@ static int vx_read_status(struct vx_core *chip, struct vx_rmh *rmh)
|
|||||||
* returns 0 if successful, or a negative error code.
|
* returns 0 if successful, or a negative error code.
|
||||||
* the error code can be VX-specific, retrieved via vx_get_error().
|
* the error code can be VX-specific, retrieved via vx_get_error().
|
||||||
*
|
*
|
||||||
* this function doesn't call spinlock at all.
|
* this function doesn't call mutex lock at all.
|
||||||
*/
|
*/
|
||||||
int vx_send_msg_nolock(struct vx_core *chip, struct vx_rmh *rmh)
|
int vx_send_msg_nolock(struct vx_core *chip, struct vx_rmh *rmh)
|
||||||
{
|
{
|
||||||
@ -337,7 +337,7 @@ int vx_send_msg_nolock(struct vx_core *chip, struct vx_rmh *rmh)
|
|||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* vx_send_msg - send a DSP message with spinlock
|
* vx_send_msg - send a DSP message with mutex
|
||||||
* @rmh: the rmh record to send and receive
|
* @rmh: the rmh record to send and receive
|
||||||
*
|
*
|
||||||
* returns 0 if successful, or a negative error code.
|
* returns 0 if successful, or a negative error code.
|
||||||
@ -345,12 +345,11 @@ int vx_send_msg_nolock(struct vx_core *chip, struct vx_rmh *rmh)
|
|||||||
*/
|
*/
|
||||||
int vx_send_msg(struct vx_core *chip, struct vx_rmh *rmh)
|
int vx_send_msg(struct vx_core *chip, struct vx_rmh *rmh)
|
||||||
{
|
{
|
||||||
unsigned long flags;
|
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
spin_lock_irqsave(&chip->lock, flags);
|
mutex_lock(&chip->lock);
|
||||||
err = vx_send_msg_nolock(chip, rmh);
|
err = vx_send_msg_nolock(chip, rmh);
|
||||||
spin_unlock_irqrestore(&chip->lock, flags);
|
mutex_unlock(&chip->lock);
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -362,7 +361,7 @@ int vx_send_msg(struct vx_core *chip, struct vx_rmh *rmh)
|
|||||||
* returns 0 if successful, or a negative error code.
|
* returns 0 if successful, or a negative error code.
|
||||||
* the error code can be VX-specific, retrieved via vx_get_error().
|
* the error code can be VX-specific, retrieved via vx_get_error().
|
||||||
*
|
*
|
||||||
* this function doesn't call spinlock at all.
|
* this function doesn't call mutex at all.
|
||||||
*
|
*
|
||||||
* unlike RMH, no command is sent to DSP.
|
* unlike RMH, no command is sent to DSP.
|
||||||
*/
|
*/
|
||||||
@ -398,19 +397,18 @@ int vx_send_rih_nolock(struct vx_core *chip, int cmd)
|
|||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* vx_send_rih - send an RIH with spinlock
|
* vx_send_rih - send an RIH with mutex
|
||||||
* @cmd: the command to send
|
* @cmd: the command to send
|
||||||
*
|
*
|
||||||
* see vx_send_rih_nolock().
|
* see vx_send_rih_nolock().
|
||||||
*/
|
*/
|
||||||
int vx_send_rih(struct vx_core *chip, int cmd)
|
int vx_send_rih(struct vx_core *chip, int cmd)
|
||||||
{
|
{
|
||||||
unsigned long flags;
|
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
spin_lock_irqsave(&chip->lock, flags);
|
mutex_lock(&chip->lock);
|
||||||
err = vx_send_rih_nolock(chip, cmd);
|
err = vx_send_rih_nolock(chip, cmd);
|
||||||
spin_unlock_irqrestore(&chip->lock, flags);
|
mutex_unlock(&chip->lock);
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -482,30 +480,30 @@ static int vx_test_irq_src(struct vx_core *chip, unsigned int *ret)
|
|||||||
int err;
|
int err;
|
||||||
|
|
||||||
vx_init_rmh(&chip->irq_rmh, CMD_TEST_IT);
|
vx_init_rmh(&chip->irq_rmh, CMD_TEST_IT);
|
||||||
spin_lock(&chip->lock);
|
mutex_lock(&chip->lock);
|
||||||
err = vx_send_msg_nolock(chip, &chip->irq_rmh);
|
err = vx_send_msg_nolock(chip, &chip->irq_rmh);
|
||||||
if (err < 0)
|
if (err < 0)
|
||||||
*ret = 0;
|
*ret = 0;
|
||||||
else
|
else
|
||||||
*ret = chip->irq_rmh.Stat[0];
|
*ret = chip->irq_rmh.Stat[0];
|
||||||
spin_unlock(&chip->lock);
|
mutex_unlock(&chip->lock);
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* vx_interrupt - soft irq handler
|
* snd_vx_threaded_irq_handler - threaded irq handler
|
||||||
*/
|
*/
|
||||||
static void vx_interrupt(unsigned long private_data)
|
irqreturn_t snd_vx_threaded_irq_handler(int irq, void *dev)
|
||||||
{
|
{
|
||||||
struct vx_core *chip = (struct vx_core *) private_data;
|
struct vx_core *chip = dev;
|
||||||
unsigned int events;
|
unsigned int events;
|
||||||
|
|
||||||
if (chip->chip_status & VX_STAT_IS_STALE)
|
if (chip->chip_status & VX_STAT_IS_STALE)
|
||||||
return;
|
return IRQ_HANDLED;
|
||||||
|
|
||||||
if (vx_test_irq_src(chip, &events) < 0)
|
if (vx_test_irq_src(chip, &events) < 0)
|
||||||
return;
|
return IRQ_HANDLED;
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
if (events & 0x000800)
|
if (events & 0x000800)
|
||||||
@ -519,7 +517,7 @@ static void vx_interrupt(unsigned long private_data)
|
|||||||
*/
|
*/
|
||||||
if (events & FATAL_DSP_ERROR) {
|
if (events & FATAL_DSP_ERROR) {
|
||||||
snd_printk(KERN_ERR "vx_core: fatal DSP error!!\n");
|
snd_printk(KERN_ERR "vx_core: fatal DSP error!!\n");
|
||||||
return;
|
return IRQ_HANDLED;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* The start on time code conditions are filled (ie the time code
|
/* The start on time code conditions are filled (ie the time code
|
||||||
@ -534,8 +532,9 @@ static void vx_interrupt(unsigned long private_data)
|
|||||||
|
|
||||||
/* update the pcm streams */
|
/* update the pcm streams */
|
||||||
vx_pcm_update_intr(chip, events);
|
vx_pcm_update_intr(chip, events);
|
||||||
|
return IRQ_HANDLED;
|
||||||
}
|
}
|
||||||
|
EXPORT_SYMBOL(snd_vx_threaded_irq_handler);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* snd_vx_irq_handler - interrupt handler
|
* snd_vx_irq_handler - interrupt handler
|
||||||
@ -548,8 +547,8 @@ irqreturn_t snd_vx_irq_handler(int irq, void *dev)
|
|||||||
(chip->chip_status & VX_STAT_IS_STALE))
|
(chip->chip_status & VX_STAT_IS_STALE))
|
||||||
return IRQ_NONE;
|
return IRQ_NONE;
|
||||||
if (! vx_test_and_ack(chip))
|
if (! vx_test_and_ack(chip))
|
||||||
tasklet_schedule(&chip->tq);
|
return IRQ_WAKE_THREAD;
|
||||||
return IRQ_HANDLED;
|
return IRQ_NONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
EXPORT_SYMBOL(snd_vx_irq_handler);
|
EXPORT_SYMBOL(snd_vx_irq_handler);
|
||||||
@ -790,13 +789,11 @@ struct vx_core *snd_vx_create(struct snd_card *card, struct snd_vx_hardware *hw,
|
|||||||
snd_printk(KERN_ERR "vx_core: no memory\n");
|
snd_printk(KERN_ERR "vx_core: no memory\n");
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
spin_lock_init(&chip->lock);
|
mutex_init(&chip->lock);
|
||||||
spin_lock_init(&chip->irq_lock);
|
|
||||||
chip->irq = -1;
|
chip->irq = -1;
|
||||||
chip->hw = hw;
|
chip->hw = hw;
|
||||||
chip->type = hw->type;
|
chip->type = hw->type;
|
||||||
chip->ops = ops;
|
chip->ops = ops;
|
||||||
tasklet_init(&chip->tq, vx_interrupt, (unsigned long)chip);
|
|
||||||
mutex_init(&chip->mixer_mutex);
|
mutex_init(&chip->mixer_mutex);
|
||||||
|
|
||||||
chip->card = card;
|
chip->card = card;
|
||||||
|
@ -32,17 +32,15 @@
|
|||||||
*/
|
*/
|
||||||
static void vx_write_codec_reg(struct vx_core *chip, int codec, unsigned int data)
|
static void vx_write_codec_reg(struct vx_core *chip, int codec, unsigned int data)
|
||||||
{
|
{
|
||||||
unsigned long flags;
|
|
||||||
|
|
||||||
if (snd_BUG_ON(!chip->ops->write_codec))
|
if (snd_BUG_ON(!chip->ops->write_codec))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (chip->chip_status & VX_STAT_IS_STALE)
|
if (chip->chip_status & VX_STAT_IS_STALE)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
spin_lock_irqsave(&chip->lock, flags);
|
mutex_lock(&chip->lock);
|
||||||
chip->ops->write_codec(chip, codec, data);
|
chip->ops->write_codec(chip, codec, data);
|
||||||
spin_unlock_irqrestore(&chip->lock, flags);
|
mutex_unlock(&chip->lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -178,14 +176,12 @@ void vx_reset_codec(struct vx_core *chip, int cold_reset)
|
|||||||
*/
|
*/
|
||||||
static void vx_change_audio_source(struct vx_core *chip, int src)
|
static void vx_change_audio_source(struct vx_core *chip, int src)
|
||||||
{
|
{
|
||||||
unsigned long flags;
|
|
||||||
|
|
||||||
if (chip->chip_status & VX_STAT_IS_STALE)
|
if (chip->chip_status & VX_STAT_IS_STALE)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
spin_lock_irqsave(&chip->lock, flags);
|
mutex_lock(&chip->lock);
|
||||||
chip->ops->change_audio_source(chip, src);
|
chip->ops->change_audio_source(chip, src);
|
||||||
spin_unlock_irqrestore(&chip->lock, flags);
|
mutex_unlock(&chip->lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -229,7 +229,7 @@ static int vx_get_pipe_state(struct vx_core *chip, struct vx_pipe *pipe, int *st
|
|||||||
|
|
||||||
vx_init_rmh(&rmh, CMD_PIPE_STATE);
|
vx_init_rmh(&rmh, CMD_PIPE_STATE);
|
||||||
vx_set_pipe_cmd_params(&rmh, pipe->is_capture, pipe->number, 0);
|
vx_set_pipe_cmd_params(&rmh, pipe->is_capture, pipe->number, 0);
|
||||||
err = vx_send_msg_nolock(chip, &rmh); /* no lock needed for trigger */
|
err = vx_send_msg(chip, &rmh);
|
||||||
if (! err)
|
if (! err)
|
||||||
*state = (rmh.Stat[0] & (1 << pipe->number)) ? 1 : 0;
|
*state = (rmh.Stat[0] & (1 << pipe->number)) ? 1 : 0;
|
||||||
return err;
|
return err;
|
||||||
@ -280,7 +280,7 @@ static int vx_pipe_can_start(struct vx_core *chip, struct vx_pipe *pipe)
|
|||||||
vx_set_pipe_cmd_params(&rmh, pipe->is_capture, pipe->number, 0);
|
vx_set_pipe_cmd_params(&rmh, pipe->is_capture, pipe->number, 0);
|
||||||
rmh.Cmd[0] |= 1;
|
rmh.Cmd[0] |= 1;
|
||||||
|
|
||||||
err = vx_send_msg_nolock(chip, &rmh); /* no lock needed for trigger */
|
err = vx_send_msg(chip, &rmh);
|
||||||
if (! err) {
|
if (! err) {
|
||||||
if (rmh.Stat[0])
|
if (rmh.Stat[0])
|
||||||
err = 1;
|
err = 1;
|
||||||
@ -300,7 +300,7 @@ static int vx_conf_pipe(struct vx_core *chip, struct vx_pipe *pipe)
|
|||||||
if (pipe->is_capture)
|
if (pipe->is_capture)
|
||||||
rmh.Cmd[0] |= COMMAND_RECORD_MASK;
|
rmh.Cmd[0] |= COMMAND_RECORD_MASK;
|
||||||
rmh.Cmd[1] = 1 << pipe->number;
|
rmh.Cmd[1] = 1 << pipe->number;
|
||||||
return vx_send_msg_nolock(chip, &rmh); /* no lock needed for trigger */
|
return vx_send_msg(chip, &rmh);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -311,7 +311,7 @@ static int vx_send_irqa(struct vx_core *chip)
|
|||||||
struct vx_rmh rmh;
|
struct vx_rmh rmh;
|
||||||
|
|
||||||
vx_init_rmh(&rmh, CMD_SEND_IRQA);
|
vx_init_rmh(&rmh, CMD_SEND_IRQA);
|
||||||
return vx_send_msg_nolock(chip, &rmh); /* no lock needed for trigger */
|
return vx_send_msg(chip, &rmh);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -389,7 +389,7 @@ static int vx_stop_pipe(struct vx_core *chip, struct vx_pipe *pipe)
|
|||||||
struct vx_rmh rmh;
|
struct vx_rmh rmh;
|
||||||
vx_init_rmh(&rmh, CMD_STOP_PIPE);
|
vx_init_rmh(&rmh, CMD_STOP_PIPE);
|
||||||
vx_set_pipe_cmd_params(&rmh, pipe->is_capture, pipe->number, 0);
|
vx_set_pipe_cmd_params(&rmh, pipe->is_capture, pipe->number, 0);
|
||||||
return vx_send_msg_nolock(chip, &rmh); /* no lock needed for trigger */
|
return vx_send_msg(chip, &rmh);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -477,7 +477,7 @@ static int vx_start_stream(struct vx_core *chip, struct vx_pipe *pipe)
|
|||||||
vx_init_rmh(&rmh, CMD_START_ONE_STREAM);
|
vx_init_rmh(&rmh, CMD_START_ONE_STREAM);
|
||||||
vx_set_stream_cmd_params(&rmh, pipe->is_capture, pipe->number);
|
vx_set_stream_cmd_params(&rmh, pipe->is_capture, pipe->number);
|
||||||
vx_set_differed_time(chip, &rmh, pipe);
|
vx_set_differed_time(chip, &rmh, pipe);
|
||||||
return vx_send_msg_nolock(chip, &rmh); /* no lock needed for trigger */
|
return vx_send_msg(chip, &rmh);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -492,7 +492,7 @@ static int vx_stop_stream(struct vx_core *chip, struct vx_pipe *pipe)
|
|||||||
|
|
||||||
vx_init_rmh(&rmh, CMD_STOP_STREAM);
|
vx_init_rmh(&rmh, CMD_STOP_STREAM);
|
||||||
vx_set_stream_cmd_params(&rmh, pipe->is_capture, pipe->number);
|
vx_set_stream_cmd_params(&rmh, pipe->is_capture, pipe->number);
|
||||||
return vx_send_msg_nolock(chip, &rmh); /* no lock needed for trigger */
|
return vx_send_msg(chip, &rmh);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -520,8 +520,6 @@ static struct snd_pcm_hardware vx_pcm_playback_hw = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
static void vx_pcm_delayed_start(unsigned long arg);
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* vx_pcm_playback_open - open callback for playback
|
* vx_pcm_playback_open - open callback for playback
|
||||||
*/
|
*/
|
||||||
@ -553,7 +551,6 @@ static int vx_pcm_playback_open(struct snd_pcm_substream *subs)
|
|||||||
pipe->references++;
|
pipe->references++;
|
||||||
|
|
||||||
pipe->substream = subs;
|
pipe->substream = subs;
|
||||||
tasklet_init(&pipe->start_tq, vx_pcm_delayed_start, (unsigned long)subs);
|
|
||||||
chip->playback_pipes[audio] = pipe;
|
chip->playback_pipes[audio] = pipe;
|
||||||
|
|
||||||
runtime->hw = vx_pcm_playback_hw;
|
runtime->hw = vx_pcm_playback_hw;
|
||||||
@ -646,12 +643,12 @@ static int vx_pcm_playback_transfer_chunk(struct vx_core *chip,
|
|||||||
/* we don't need irqsave here, because this function
|
/* we don't need irqsave here, because this function
|
||||||
* is called from either trigger callback or irq handler
|
* is called from either trigger callback or irq handler
|
||||||
*/
|
*/
|
||||||
spin_lock(&chip->lock);
|
mutex_lock(&chip->lock);
|
||||||
vx_pseudo_dma_write(chip, runtime, pipe, size);
|
vx_pseudo_dma_write(chip, runtime, pipe, size);
|
||||||
err = vx_notify_end_of_buffer(chip, pipe);
|
err = vx_notify_end_of_buffer(chip, pipe);
|
||||||
/* disconnect the host, SIZE_HBUF command always switches to the stream mode */
|
/* disconnect the host, SIZE_HBUF command always switches to the stream mode */
|
||||||
vx_send_rih_nolock(chip, IRQ_CONNECT_STREAM_NEXT);
|
vx_send_rih_nolock(chip, IRQ_CONNECT_STREAM_NEXT);
|
||||||
spin_unlock(&chip->lock);
|
mutex_unlock(&chip->lock);
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -727,31 +724,6 @@ static void vx_pcm_playback_update(struct vx_core *chip,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* start the stream and pipe.
|
|
||||||
* this function is called from tasklet, which is invoked by the trigger
|
|
||||||
* START callback.
|
|
||||||
*/
|
|
||||||
static void vx_pcm_delayed_start(unsigned long arg)
|
|
||||||
{
|
|
||||||
struct snd_pcm_substream *subs = (struct snd_pcm_substream *)arg;
|
|
||||||
struct vx_core *chip = subs->pcm->private_data;
|
|
||||||
struct vx_pipe *pipe = subs->runtime->private_data;
|
|
||||||
int err;
|
|
||||||
|
|
||||||
/* printk( KERN_DEBUG "DDDD tasklet delayed start jiffies = %ld\n", jiffies);*/
|
|
||||||
|
|
||||||
if ((err = vx_start_stream(chip, pipe)) < 0) {
|
|
||||||
snd_printk(KERN_ERR "vx: cannot start stream\n");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if ((err = vx_toggle_pipe(chip, pipe, 1)) < 0) {
|
|
||||||
snd_printk(KERN_ERR "vx: cannot start pipe\n");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
/* printk( KERN_DEBUG "dddd tasklet delayed start jiffies = %ld \n", jiffies);*/
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* vx_pcm_playback_trigger - trigger callback for playback
|
* vx_pcm_playback_trigger - trigger callback for playback
|
||||||
*/
|
*/
|
||||||
@ -769,11 +741,17 @@ static int vx_pcm_trigger(struct snd_pcm_substream *subs, int cmd)
|
|||||||
case SNDRV_PCM_TRIGGER_RESUME:
|
case SNDRV_PCM_TRIGGER_RESUME:
|
||||||
if (! pipe->is_capture)
|
if (! pipe->is_capture)
|
||||||
vx_pcm_playback_transfer(chip, subs, pipe, 2);
|
vx_pcm_playback_transfer(chip, subs, pipe, 2);
|
||||||
/* FIXME:
|
err = vx_start_stream(chip, pipe);
|
||||||
* we trigger the pipe using tasklet, so that the interrupts are
|
if (err < 0) {
|
||||||
* issued surely after the trigger is completed.
|
pr_debug("vx: cannot start stream\n");
|
||||||
*/
|
return err;
|
||||||
tasklet_schedule(&pipe->start_tq);
|
}
|
||||||
|
err = vx_toggle_pipe(chip, pipe, 1);
|
||||||
|
if (err < 0) {
|
||||||
|
pr_debug("vx: cannot start pipe\n");
|
||||||
|
vx_stop_stream(chip, pipe);
|
||||||
|
return err;
|
||||||
|
}
|
||||||
chip->pcm_running++;
|
chip->pcm_running++;
|
||||||
pipe->running = 1;
|
pipe->running = 1;
|
||||||
break;
|
break;
|
||||||
@ -955,7 +933,6 @@ static int vx_pcm_capture_open(struct snd_pcm_substream *subs)
|
|||||||
if (err < 0)
|
if (err < 0)
|
||||||
return err;
|
return err;
|
||||||
pipe->substream = subs;
|
pipe->substream = subs;
|
||||||
tasklet_init(&pipe->start_tq, vx_pcm_delayed_start, (unsigned long)subs);
|
|
||||||
chip->capture_pipes[audio] = pipe;
|
chip->capture_pipes[audio] = pipe;
|
||||||
|
|
||||||
/* check if monitoring is needed */
|
/* check if monitoring is needed */
|
||||||
@ -1082,7 +1059,7 @@ static void vx_pcm_capture_update(struct vx_core *chip, struct snd_pcm_substream
|
|||||||
count -= 3;
|
count -= 3;
|
||||||
}
|
}
|
||||||
/* disconnect the host, SIZE_HBUF command always switches to the stream mode */
|
/* disconnect the host, SIZE_HBUF command always switches to the stream mode */
|
||||||
vx_send_rih_nolock(chip, IRQ_CONNECT_STREAM_NEXT);
|
vx_send_rih(chip, IRQ_CONNECT_STREAM_NEXT);
|
||||||
/* read the last pending 6 bytes */
|
/* read the last pending 6 bytes */
|
||||||
count = DMA_READ_ALIGN;
|
count = DMA_READ_ALIGN;
|
||||||
while (count > 0) {
|
while (count > 0) {
|
||||||
@ -1099,7 +1076,7 @@ static void vx_pcm_capture_update(struct vx_core *chip, struct snd_pcm_substream
|
|||||||
|
|
||||||
_error:
|
_error:
|
||||||
/* disconnect the host, SIZE_HBUF command always switches to the stream mode */
|
/* disconnect the host, SIZE_HBUF command always switches to the stream mode */
|
||||||
vx_send_rih_nolock(chip, IRQ_CONNECT_STREAM_NEXT);
|
vx_send_rih(chip, IRQ_CONNECT_STREAM_NEXT);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1275,6 +1252,7 @@ int snd_vx_pcm_new(struct vx_core *chip)
|
|||||||
pcm->private_data = chip;
|
pcm->private_data = chip;
|
||||||
pcm->private_free = snd_vx_pcm_free;
|
pcm->private_free = snd_vx_pcm_free;
|
||||||
pcm->info_flags = 0;
|
pcm->info_flags = 0;
|
||||||
|
pcm->nonatomic = true;
|
||||||
strcpy(pcm->name, chip->card->shortname);
|
strcpy(pcm->name, chip->card->shortname);
|
||||||
chip->pcm[i] = pcm;
|
chip->pcm[i] = pcm;
|
||||||
}
|
}
|
||||||
|
@ -60,9 +60,9 @@ static int vx_modify_board_inputs(struct vx_core *chip)
|
|||||||
*/
|
*/
|
||||||
static int vx_read_one_cbit(struct vx_core *chip, int index)
|
static int vx_read_one_cbit(struct vx_core *chip, int index)
|
||||||
{
|
{
|
||||||
unsigned long flags;
|
|
||||||
int val;
|
int val;
|
||||||
spin_lock_irqsave(&chip->lock, flags);
|
|
||||||
|
mutex_lock(&chip->lock);
|
||||||
if (chip->type >= VX_TYPE_VXPOCKET) {
|
if (chip->type >= VX_TYPE_VXPOCKET) {
|
||||||
vx_outb(chip, CSUER, 1); /* read */
|
vx_outb(chip, CSUER, 1); /* read */
|
||||||
vx_outb(chip, RUER, index & XX_UER_CBITS_OFFSET_MASK);
|
vx_outb(chip, RUER, index & XX_UER_CBITS_OFFSET_MASK);
|
||||||
@ -72,7 +72,7 @@ static int vx_read_one_cbit(struct vx_core *chip, int index)
|
|||||||
vx_outl(chip, RUER, index & XX_UER_CBITS_OFFSET_MASK);
|
vx_outl(chip, RUER, index & XX_UER_CBITS_OFFSET_MASK);
|
||||||
val = (vx_inl(chip, RUER) >> 7) & 0x01;
|
val = (vx_inl(chip, RUER) >> 7) & 0x01;
|
||||||
}
|
}
|
||||||
spin_unlock_irqrestore(&chip->lock, flags);
|
mutex_unlock(&chip->lock);
|
||||||
return val;
|
return val;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -83,9 +83,8 @@ static int vx_read_one_cbit(struct vx_core *chip, int index)
|
|||||||
*/
|
*/
|
||||||
static void vx_write_one_cbit(struct vx_core *chip, int index, int val)
|
static void vx_write_one_cbit(struct vx_core *chip, int index, int val)
|
||||||
{
|
{
|
||||||
unsigned long flags;
|
|
||||||
val = !!val; /* 0 or 1 */
|
val = !!val; /* 0 or 1 */
|
||||||
spin_lock_irqsave(&chip->lock, flags);
|
mutex_lock(&chip->lock);
|
||||||
if (vx_is_pcmcia(chip)) {
|
if (vx_is_pcmcia(chip)) {
|
||||||
vx_outb(chip, CSUER, 0); /* write */
|
vx_outb(chip, CSUER, 0); /* write */
|
||||||
vx_outb(chip, RUER, (val << 7) | (index & XX_UER_CBITS_OFFSET_MASK));
|
vx_outb(chip, RUER, (val << 7) | (index & XX_UER_CBITS_OFFSET_MASK));
|
||||||
@ -93,7 +92,7 @@ static void vx_write_one_cbit(struct vx_core *chip, int index, int val)
|
|||||||
vx_outl(chip, CSUER, 0); /* write */
|
vx_outl(chip, CSUER, 0); /* write */
|
||||||
vx_outl(chip, RUER, (val << 7) | (index & XX_UER_CBITS_OFFSET_MASK));
|
vx_outl(chip, RUER, (val << 7) | (index & XX_UER_CBITS_OFFSET_MASK));
|
||||||
}
|
}
|
||||||
spin_unlock_irqrestore(&chip->lock, flags);
|
mutex_unlock(&chip->lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -190,14 +189,12 @@ static int vx_calc_clock_from_freq(struct vx_core *chip, int freq)
|
|||||||
*/
|
*/
|
||||||
static void vx_change_clock_source(struct vx_core *chip, int source)
|
static void vx_change_clock_source(struct vx_core *chip, int source)
|
||||||
{
|
{
|
||||||
unsigned long flags;
|
|
||||||
|
|
||||||
/* we mute DAC to prevent clicks */
|
/* we mute DAC to prevent clicks */
|
||||||
vx_toggle_dac_mute(chip, 1);
|
vx_toggle_dac_mute(chip, 1);
|
||||||
spin_lock_irqsave(&chip->lock, flags);
|
mutex_lock(&chip->lock);
|
||||||
chip->ops->set_clock_source(chip, source);
|
chip->ops->set_clock_source(chip, source);
|
||||||
chip->clock_source = source;
|
chip->clock_source = source;
|
||||||
spin_unlock_irqrestore(&chip->lock, flags);
|
mutex_unlock(&chip->lock);
|
||||||
/* unmute */
|
/* unmute */
|
||||||
vx_toggle_dac_mute(chip, 0);
|
vx_toggle_dac_mute(chip, 0);
|
||||||
}
|
}
|
||||||
@ -209,11 +206,11 @@ static void vx_change_clock_source(struct vx_core *chip, int source)
|
|||||||
void vx_set_internal_clock(struct vx_core *chip, unsigned int freq)
|
void vx_set_internal_clock(struct vx_core *chip, unsigned int freq)
|
||||||
{
|
{
|
||||||
int clock;
|
int clock;
|
||||||
unsigned long flags;
|
|
||||||
/* Get real clock value */
|
/* Get real clock value */
|
||||||
clock = vx_calc_clock_from_freq(chip, freq);
|
clock = vx_calc_clock_from_freq(chip, freq);
|
||||||
snd_printdd(KERN_DEBUG "set internal clock to 0x%x from freq %d\n", clock, freq);
|
snd_printdd(KERN_DEBUG "set internal clock to 0x%x from freq %d\n", clock, freq);
|
||||||
spin_lock_irqsave(&chip->lock, flags);
|
mutex_lock(&chip->lock);
|
||||||
if (vx_is_pcmcia(chip)) {
|
if (vx_is_pcmcia(chip)) {
|
||||||
vx_outb(chip, HIFREQ, (clock >> 8) & 0x0f);
|
vx_outb(chip, HIFREQ, (clock >> 8) & 0x0f);
|
||||||
vx_outb(chip, LOFREQ, clock & 0xff);
|
vx_outb(chip, LOFREQ, clock & 0xff);
|
||||||
@ -221,7 +218,7 @@ void vx_set_internal_clock(struct vx_core *chip, unsigned int freq)
|
|||||||
vx_outl(chip, HIFREQ, (clock >> 8) & 0x0f);
|
vx_outl(chip, HIFREQ, (clock >> 8) & 0x0f);
|
||||||
vx_outl(chip, LOFREQ, clock & 0xff);
|
vx_outl(chip, LOFREQ, clock & 0xff);
|
||||||
}
|
}
|
||||||
spin_unlock_irqrestore(&chip->lock, flags);
|
mutex_unlock(&chip->lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -168,8 +168,9 @@ static int snd_vx222_create(struct snd_card *card, struct pci_dev *pci,
|
|||||||
for (i = 0; i < 2; i++)
|
for (i = 0; i < 2; i++)
|
||||||
vx->port[i] = pci_resource_start(pci, i + 1);
|
vx->port[i] = pci_resource_start(pci, i + 1);
|
||||||
|
|
||||||
if (request_irq(pci->irq, snd_vx_irq_handler, IRQF_SHARED,
|
if (request_threaded_irq(pci->irq, snd_vx_irq_handler,
|
||||||
KBUILD_MODNAME, chip)) {
|
snd_vx_threaded_irq_handler, IRQF_SHARED,
|
||||||
|
KBUILD_MODNAME, chip)) {
|
||||||
dev_err(card->dev, "unable to grab IRQ %d\n", pci->irq);
|
dev_err(card->dev, "unable to grab IRQ %d\n", pci->irq);
|
||||||
snd_vx222_free(chip);
|
snd_vx222_free(chip);
|
||||||
return -EBUSY;
|
return -EBUSY;
|
||||||
|
@ -468,12 +468,11 @@ static void vxp_write_codec_reg(struct vx_core *chip, int codec, unsigned int da
|
|||||||
void vx_set_mic_boost(struct vx_core *chip, int boost)
|
void vx_set_mic_boost(struct vx_core *chip, int boost)
|
||||||
{
|
{
|
||||||
struct snd_vxpocket *pchip = (struct snd_vxpocket *)chip;
|
struct snd_vxpocket *pchip = (struct snd_vxpocket *)chip;
|
||||||
unsigned long flags;
|
|
||||||
|
|
||||||
if (chip->chip_status & VX_STAT_IS_STALE)
|
if (chip->chip_status & VX_STAT_IS_STALE)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
spin_lock_irqsave(&chip->lock, flags);
|
mutex_lock(&chip->lock);
|
||||||
if (pchip->regCDSP & P24_CDSP_MICS_SEL_MASK) {
|
if (pchip->regCDSP & P24_CDSP_MICS_SEL_MASK) {
|
||||||
if (boost) {
|
if (boost) {
|
||||||
/* boost: 38 dB */
|
/* boost: 38 dB */
|
||||||
@ -486,7 +485,7 @@ void vx_set_mic_boost(struct vx_core *chip, int boost)
|
|||||||
}
|
}
|
||||||
vx_outb(chip, CDSP, pchip->regCDSP);
|
vx_outb(chip, CDSP, pchip->regCDSP);
|
||||||
}
|
}
|
||||||
spin_unlock_irqrestore(&chip->lock, flags);
|
mutex_unlock(&chip->lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -511,17 +510,16 @@ static int vx_compute_mic_level(int level)
|
|||||||
void vx_set_mic_level(struct vx_core *chip, int level)
|
void vx_set_mic_level(struct vx_core *chip, int level)
|
||||||
{
|
{
|
||||||
struct snd_vxpocket *pchip = (struct snd_vxpocket *)chip;
|
struct snd_vxpocket *pchip = (struct snd_vxpocket *)chip;
|
||||||
unsigned long flags;
|
|
||||||
|
|
||||||
if (chip->chip_status & VX_STAT_IS_STALE)
|
if (chip->chip_status & VX_STAT_IS_STALE)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
spin_lock_irqsave(&chip->lock, flags);
|
mutex_lock(&chip->lock);
|
||||||
if (pchip->regCDSP & VXP_CDSP_MIC_SEL_MASK) {
|
if (pchip->regCDSP & VXP_CDSP_MIC_SEL_MASK) {
|
||||||
level = vx_compute_mic_level(level);
|
level = vx_compute_mic_level(level);
|
||||||
vx_outb(chip, MICRO, level);
|
vx_outb(chip, MICRO, level);
|
||||||
}
|
}
|
||||||
spin_unlock_irqrestore(&chip->lock, flags);
|
mutex_unlock(&chip->lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -62,6 +62,7 @@ static unsigned int card_alloc;
|
|||||||
*/
|
*/
|
||||||
static void vxpocket_release(struct pcmcia_device *link)
|
static void vxpocket_release(struct pcmcia_device *link)
|
||||||
{
|
{
|
||||||
|
free_irq(link->irq, link->priv);
|
||||||
pcmcia_disable_device(link);
|
pcmcia_disable_device(link);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -227,11 +228,13 @@ static int vxpocket_config(struct pcmcia_device *link)
|
|||||||
|
|
||||||
ret = pcmcia_request_io(link);
|
ret = pcmcia_request_io(link);
|
||||||
if (ret)
|
if (ret)
|
||||||
goto failed;
|
goto failed_preirq;
|
||||||
|
|
||||||
ret = pcmcia_request_irq(link, snd_vx_irq_handler);
|
ret = request_threaded_irq(link->irq, snd_vx_irq_handler,
|
||||||
|
snd_vx_threaded_irq_handler,
|
||||||
|
IRQF_SHARED, link->devname, link->priv);
|
||||||
if (ret)
|
if (ret)
|
||||||
goto failed;
|
goto failed_preirq;
|
||||||
|
|
||||||
ret = pcmcia_enable_device(link);
|
ret = pcmcia_enable_device(link);
|
||||||
if (ret)
|
if (ret)
|
||||||
@ -245,7 +248,9 @@ static int vxpocket_config(struct pcmcia_device *link)
|
|||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
failed:
|
failed:
|
||||||
|
free_irq(link->irq, link->priv);
|
||||||
|
failed_preirq:
|
||||||
pcmcia_disable_device(link);
|
pcmcia_disable_device(link);
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user