summaryrefslogtreecommitdiff
path: root/sound
diff options
context:
space:
mode:
Diffstat (limited to 'sound')
-rw-r--r--sound/drivers/vx/vx_core.c49
-rw-r--r--sound/drivers/vx/vx_mixer.c12
-rw-r--r--sound/drivers/vx/vx_pcm.c68
-rw-r--r--sound/drivers/vx/vx_uer.c23
-rw-r--r--sound/pci/hda/hda_sysfs.c2
-rw-r--r--sound/pci/lx6464es/lx6464es.c43
-rw-r--r--sound/pci/lx6464es/lx6464es.h9
-rw-r--r--sound/pci/lx6464es/lx_core.c252
-rw-r--r--sound/pci/lx6464es/lx_core.h4
-rw-r--r--sound/pci/mixart/mixart.c17
-rw-r--r--sound/pci/mixart/mixart.h10
-rw-r--r--sound/pci/mixart/mixart_core.c79
-rw-r--r--sound/pci/mixart/mixart_core.h2
-rw-r--r--sound/pci/oxygen/oxygen_pcm.c10
-rw-r--r--sound/pci/oxygen/virtuoso.c1
-rw-r--r--sound/pci/oxygen/xonar_pcm179x.c133
-rw-r--r--sound/pci/pcxhr/pcxhr.c43
-rw-r--r--sound/pci/pcxhr/pcxhr.h8
-rw-r--r--sound/pci/pcxhr/pcxhr_core.c102
-rw-r--r--sound/pci/pcxhr/pcxhr_core.h2
-rw-r--r--sound/pci/vx222/vx222.c5
-rw-r--r--sound/pcmcia/pdaudiocf/pdaudiocf.c13
-rw-r--r--sound/pcmcia/pdaudiocf/pdaudiocf.h5
-rw-r--r--sound/pcmcia/pdaudiocf/pdaudiocf_core.c8
-rw-r--r--sound/pcmcia/pdaudiocf/pdaudiocf_irq.c23
-rw-r--r--sound/pcmcia/pdaudiocf/pdaudiocf_pcm.c5
-rw-r--r--sound/pcmcia/vx/vxp_ops.c10
-rw-r--r--sound/pcmcia/vx/vxpocket.c13
28 files changed, 479 insertions, 472 deletions
diff --git a/sound/drivers/vx/vx_core.c b/sound/drivers/vx/vx_core.c
index 83596891cde4..e8cc16993903 100644
--- a/sound/drivers/vx/vx_core.c
+++ b/sound/drivers/vx/vx_core.c
@@ -117,7 +117,7 @@ static int vx_reset_chk(struct vx_core *chip)
*
* returns 0 if successful, or a negative error code.
* 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)
{
@@ -155,7 +155,7 @@ static int vx_transfer_end(struct vx_core *chip, int cmd)
*
* returns 0 if successful, or a negative error code.
* 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)
{
@@ -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.
* 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)
{
@@ -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
*
* 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)
{
- unsigned long flags;
int err;
- spin_lock_irqsave(&chip->lock, flags);
+ mutex_lock(&chip->lock);
err = vx_send_msg_nolock(chip, rmh);
- spin_unlock_irqrestore(&chip->lock, flags);
+ mutex_unlock(&chip->lock);
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.
* 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.
*/
@@ -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
*
* see vx_send_rih_nolock().
*/
int vx_send_rih(struct vx_core *chip, int cmd)
{
- unsigned long flags;
int err;
- spin_lock_irqsave(&chip->lock, flags);
+ mutex_lock(&chip->lock);
err = vx_send_rih_nolock(chip, cmd);
- spin_unlock_irqrestore(&chip->lock, flags);
+ mutex_unlock(&chip->lock);
return err;
}
@@ -482,30 +480,30 @@ static int vx_test_irq_src(struct vx_core *chip, unsigned int *ret)
int err;
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);
if (err < 0)
*ret = 0;
else
*ret = chip->irq_rmh.Stat[0];
- spin_unlock(&chip->lock);
+ mutex_unlock(&chip->lock);
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;
if (chip->chip_status & VX_STAT_IS_STALE)
- return;
+ return IRQ_HANDLED;
if (vx_test_irq_src(chip, &events) < 0)
- return;
+ return IRQ_HANDLED;
#if 0
if (events & 0x000800)
@@ -519,7 +517,7 @@ static void vx_interrupt(unsigned long private_data)
*/
if (events & FATAL_DSP_ERROR) {
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
@@ -534,8 +532,9 @@ static void vx_interrupt(unsigned long private_data)
/* update the pcm streams */
vx_pcm_update_intr(chip, events);
+ return IRQ_HANDLED;
}
-
+EXPORT_SYMBOL(snd_vx_threaded_irq_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))
return IRQ_NONE;
if (! vx_test_and_ack(chip))
- tasklet_schedule(&chip->tq);
- return IRQ_HANDLED;
+ return IRQ_WAKE_THREAD;
+ return IRQ_NONE;
}
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");
return NULL;
}
- spin_lock_init(&chip->lock);
- spin_lock_init(&chip->irq_lock);
+ mutex_init(&chip->lock);
chip->irq = -1;
chip->hw = hw;
chip->type = hw->type;
chip->ops = ops;
- tasklet_init(&chip->tq, vx_interrupt, (unsigned long)chip);
mutex_init(&chip->mixer_mutex);
chip->card = card;
diff --git a/sound/drivers/vx/vx_mixer.c b/sound/drivers/vx/vx_mixer.c
index c71b8d148d7f..3b6823fc0606 100644
--- a/sound/drivers/vx/vx_mixer.c
+++ b/sound/drivers/vx/vx_mixer.c
@@ -32,17 +32,15 @@
*/
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))
return;
if (chip->chip_status & VX_STAT_IS_STALE)
return;
- spin_lock_irqsave(&chip->lock, flags);
+ mutex_lock(&chip->lock);
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)
{
- unsigned long flags;
-
if (chip->chip_status & VX_STAT_IS_STALE)
return;
- spin_lock_irqsave(&chip->lock, flags);
+ mutex_lock(&chip->lock);
chip->ops->change_audio_source(chip, src);
- spin_unlock_irqrestore(&chip->lock, flags);
+ mutex_unlock(&chip->lock);
}
diff --git a/sound/drivers/vx/vx_pcm.c b/sound/drivers/vx/vx_pcm.c
index deed5efff33c..11467272089e 100644
--- a/sound/drivers/vx/vx_pcm.c
+++ b/sound/drivers/vx/vx_pcm.c
@@ -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_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)
*state = (rmh.Stat[0] & (1 << pipe->number)) ? 1 : 0;
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);
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 (rmh.Stat[0])
err = 1;
@@ -300,7 +300,7 @@ static int vx_conf_pipe(struct vx_core *chip, struct vx_pipe *pipe)
if (pipe->is_capture)
rmh.Cmd[0] |= COMMAND_RECORD_MASK;
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;
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;
vx_init_rmh(&rmh, CMD_STOP_PIPE);
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_set_stream_cmd_params(&rmh, pipe->is_capture, pipe->number);
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_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
*/
@@ -553,7 +551,6 @@ static int vx_pcm_playback_open(struct snd_pcm_substream *subs)
pipe->references++;
pipe->substream = subs;
- tasklet_init(&pipe->start_tq, vx_pcm_delayed_start, (unsigned long)subs);
chip->playback_pipes[audio] = pipe;
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
* 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);
err = vx_notify_end_of_buffer(chip, pipe);
/* disconnect the host, SIZE_HBUF command always switches to the stream mode */
vx_send_rih_nolock(chip, IRQ_CONNECT_STREAM_NEXT);
- spin_unlock(&chip->lock);
+ mutex_unlock(&chip->lock);
return err;
}
@@ -728,31 +725,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
*/
static int vx_pcm_trigger(struct snd_pcm_substream *subs, int cmd)
@@ -769,11 +741,17 @@ static int vx_pcm_trigger(struct snd_pcm_substream *subs, int cmd)
case SNDRV_PCM_TRIGGER_RESUME:
if (! pipe->is_capture)
vx_pcm_playback_transfer(chip, subs, pipe, 2);
- /* FIXME:
- * we trigger the pipe using tasklet, so that the interrupts are
- * issued surely after the trigger is completed.
- */
- tasklet_schedule(&pipe->start_tq);
+ err = vx_start_stream(chip, pipe);
+ if (err < 0) {
+ pr_debug("vx: cannot start stream\n");
+ return err;
+ }
+ 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++;
pipe->running = 1;
break;
@@ -955,7 +933,6 @@ static int vx_pcm_capture_open(struct snd_pcm_substream *subs)
if (err < 0)
return err;
pipe->substream = subs;
- tasklet_init(&pipe->start_tq, vx_pcm_delayed_start, (unsigned long)subs);
chip->capture_pipes[audio] = pipe;
/* 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;
}
/* 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 */
count = DMA_READ_ALIGN;
while (count > 0) {
@@ -1099,7 +1076,7 @@ static void vx_pcm_capture_update(struct vx_core *chip, struct snd_pcm_substream
_error:
/* 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;
}
@@ -1275,6 +1252,7 @@ int snd_vx_pcm_new(struct vx_core *chip)
pcm->private_data = chip;
pcm->private_free = snd_vx_pcm_free;
pcm->info_flags = 0;
+ pcm->nonatomic = true;
strcpy(pcm->name, chip->card->shortname);
chip->pcm[i] = pcm;
}
diff --git a/sound/drivers/vx/vx_uer.c b/sound/drivers/vx/vx_uer.c
index b0560fec6bba..ef0b40c0a594 100644
--- a/sound/drivers/vx/vx_uer.c
+++ b/sound/drivers/vx/vx_uer.c
@@ -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)
{
- unsigned long flags;
int val;
- spin_lock_irqsave(&chip->lock, flags);
+
+ mutex_lock(&chip->lock);
if (chip->type >= VX_TYPE_VXPOCKET) {
vx_outb(chip, CSUER, 1); /* read */
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);
val = (vx_inl(chip, RUER) >> 7) & 0x01;
}
- spin_unlock_irqrestore(&chip->lock, flags);
+ mutex_unlock(&chip->lock);
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)
{
- unsigned long flags;
val = !!val; /* 0 or 1 */
- spin_lock_irqsave(&chip->lock, flags);
+ mutex_lock(&chip->lock);
if (vx_is_pcmcia(chip)) {
vx_outb(chip, CSUER, 0); /* write */
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, 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)
{
- unsigned long flags;
-
/* we mute DAC to prevent clicks */
vx_toggle_dac_mute(chip, 1);
- spin_lock_irqsave(&chip->lock, flags);
+ mutex_lock(&chip->lock);
chip->ops->set_clock_source(chip, source);
chip->clock_source = source;
- spin_unlock_irqrestore(&chip->lock, flags);
+ mutex_unlock(&chip->lock);
/* unmute */
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)
{
int clock;
- unsigned long flags;
+
/* Get real clock value */
clock = vx_calc_clock_from_freq(chip, 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)) {
vx_outb(chip, HIFREQ, (clock >> 8) & 0x0f);
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, LOFREQ, clock & 0xff);
}
- spin_unlock_irqrestore(&chip->lock, flags);
+ mutex_unlock(&chip->lock);
}
diff --git a/sound/pci/hda/hda_sysfs.c b/sound/pci/hda/hda_sysfs.c
index e2079090ca6f..9b49f156a12e 100644
--- a/sound/pci/hda/hda_sysfs.c
+++ b/sound/pci/hda/hda_sysfs.c
@@ -514,7 +514,7 @@ enum {
static inline int strmatch(const char *a, const char *b)
{
- return strnicmp(a, b, strlen(b)) == 0;
+ return strncasecmp(a, b, strlen(b)) == 0;
}
/* parse the contents after the line "[codec]"
diff --git a/sound/pci/lx6464es/lx6464es.c b/sound/pci/lx6464es/lx6464es.c
index a671f0865f71..601315a1f58f 100644
--- a/sound/pci/lx6464es/lx6464es.c
+++ b/sound/pci/lx6464es/lx6464es.c
@@ -279,7 +279,6 @@ static snd_pcm_uframes_t lx_pcm_stream_pointer(struct snd_pcm_substream
{
struct lx6464es *chip = snd_pcm_substream_chip(substream);
snd_pcm_uframes_t pos;
- unsigned long flags;
int is_capture = (substream->stream == SNDRV_PCM_STREAM_CAPTURE);
struct lx_stream *lx_stream = is_capture ? &chip->capture_stream :
@@ -287,9 +286,9 @@ static snd_pcm_uframes_t lx_pcm_stream_pointer(struct snd_pcm_substream
dev_dbg(chip->card->dev, "->lx_pcm_stream_pointer\n");
- spin_lock_irqsave(&chip->lock, flags);
+ mutex_lock(&chip->lock);
pos = lx_stream->frame_pos * substream->runtime->period_size;
- spin_unlock_irqrestore(&chip->lock, flags);
+ mutex_unlock(&chip->lock);
dev_dbg(chip->card->dev, "stream_pointer at %ld\n", pos);
return pos;
@@ -485,8 +484,8 @@ static void lx_trigger_stop(struct lx6464es *chip, struct lx_stream *lx_stream)
}
-static void lx_trigger_tasklet_dispatch_stream(struct lx6464es *chip,
- struct lx_stream *lx_stream)
+static void lx_trigger_dispatch_stream(struct lx6464es *chip,
+ struct lx_stream *lx_stream)
{
switch (lx_stream->status) {
case LX_STREAM_STATUS_SCHEDULE_RUN:
@@ -502,24 +501,12 @@ static void lx_trigger_tasklet_dispatch_stream(struct lx6464es *chip,
}
}
-static void lx_trigger_tasklet(unsigned long data)
-{
- struct lx6464es *chip = (struct lx6464es *)data;
- unsigned long flags;
-
- dev_dbg(chip->card->dev, "->lx_trigger_tasklet\n");
-
- spin_lock_irqsave(&chip->lock, flags);
- lx_trigger_tasklet_dispatch_stream(chip, &chip->capture_stream);
- lx_trigger_tasklet_dispatch_stream(chip, &chip->playback_stream);
- spin_unlock_irqrestore(&chip->lock, flags);
-}
-
static int lx_pcm_trigger_dispatch(struct lx6464es *chip,
struct lx_stream *lx_stream, int cmd)
{
int err = 0;
+ mutex_lock(&chip->lock);
switch (cmd) {
case SNDRV_PCM_TRIGGER_START:
lx_stream->status = LX_STREAM_STATUS_SCHEDULE_RUN;
@@ -533,9 +520,12 @@ static int lx_pcm_trigger_dispatch(struct lx6464es *chip,
err = -EINVAL;
goto exit;
}
- tasklet_schedule(&chip->trigger_tasklet);
+
+ lx_trigger_dispatch_stream(chip, &chip->capture_stream);
+ lx_trigger_dispatch_stream(chip, &chip->playback_stream);
exit:
+ mutex_unlock(&chip->lock);
return err;
}
@@ -861,6 +851,7 @@ static int lx_pcm_create(struct lx6464es *chip)
snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &lx_ops_capture);
pcm->info_flags = 0;
+ pcm->nonatomic = true;
strcpy(pcm->name, card_name);
err = snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV,
@@ -1009,15 +1000,9 @@ static int snd_lx6464es_create(struct snd_card *card,
chip->irq = -1;
/* initialize synchronization structs */
- spin_lock_init(&chip->lock);
- spin_lock_init(&chip->msg_lock);
+ mutex_init(&chip->lock);
+ mutex_init(&chip->msg_lock);
mutex_init(&chip->setup_mutex);
- tasklet_init(&chip->trigger_tasklet, lx_trigger_tasklet,
- (unsigned long)chip);
- tasklet_init(&chip->tasklet_capture, lx_tasklet_capture,
- (unsigned long)chip);
- tasklet_init(&chip->tasklet_playback, lx_tasklet_playback,
- (unsigned long)chip);
/* request resources */
err = pci_request_regions(pci, card_name);
@@ -1032,8 +1017,8 @@ static int snd_lx6464es_create(struct snd_card *card,
/* dsp port */
chip->port_dsp_bar = pci_ioremap_bar(pci, 2);
- err = request_irq(pci->irq, lx_interrupt, IRQF_SHARED,
- KBUILD_MODNAME, chip);
+ err = request_threaded_irq(pci->irq, lx_interrupt, lx_threaded_irq,
+ IRQF_SHARED, KBUILD_MODNAME, chip);
if (err) {
dev_err(card->dev, "unable to grab IRQ %d\n", pci->irq);
goto request_irq_failed;
diff --git a/sound/pci/lx6464es/lx6464es.h b/sound/pci/lx6464es/lx6464es.h
index 6792eda9c9a5..1bec187d772f 100644
--- a/sound/pci/lx6464es/lx6464es.h
+++ b/sound/pci/lx6464es/lx6464es.h
@@ -71,14 +71,10 @@ struct lx6464es {
u8 mac_address[6];
- spinlock_t lock; /* interrupt spinlock */
+ struct mutex lock; /* interrupt lock */
struct mutex setup_mutex; /* mutex used in hw_params, open
* and close */
- struct tasklet_struct trigger_tasklet; /* trigger tasklet */
- struct tasklet_struct tasklet_capture;
- struct tasklet_struct tasklet_playback;
-
/* ports */
unsigned long port_plx; /* io port (size=256) */
void __iomem *port_plx_remapped; /* remapped plx port */
@@ -87,8 +83,9 @@ struct lx6464es {
* size=8K) */
/* messaging */
- spinlock_t msg_lock; /* message spinlock */
+ struct mutex msg_lock; /* message lock */
struct lx_rmh rmh;
+ u32 irqsrc;
/* configuration */
uint freq_ratio : 2;
diff --git a/sound/pci/lx6464es/lx_core.c b/sound/pci/lx6464es/lx_core.c
index e8f38e5df10a..f3d62020ef66 100644
--- a/sound/pci/lx6464es/lx_core.c
+++ b/sound/pci/lx6464es/lx_core.c
@@ -332,27 +332,25 @@ polling_successful:
int lx_dsp_get_version(struct lx6464es *chip, u32 *rdsp_version)
{
u16 ret;
- unsigned long flags;
- spin_lock_irqsave(&chip->msg_lock, flags);
+ mutex_lock(&chip->msg_lock);
lx_message_init(&chip->rmh, CMD_01_GET_SYS_CFG);
ret = lx_message_send_atomic(chip, &chip->rmh);
*rdsp_version = chip->rmh.stat[1];
- spin_unlock_irqrestore(&chip->msg_lock, flags);
+ mutex_unlock(&chip->msg_lock);
return ret;
}
int lx_dsp_get_clock_frequency(struct lx6464es *chip, u32 *rfreq)
{
u16 ret = 0;
- unsigned long flags;
u32 freq_raw = 0;
u32 freq = 0;
u32 frequency = 0;
- spin_lock_irqsave(&chip->msg_lock, flags);
+ mutex_lock(&chip->msg_lock);
lx_message_init(&chip->rmh, CMD_01_GET_SYS_CFG);
ret = lx_message_send_atomic(chip, &chip->rmh);
@@ -370,7 +368,7 @@ int lx_dsp_get_clock_frequency(struct lx6464es *chip, u32 *rfreq)
frequency = 48000;
}
- spin_unlock_irqrestore(&chip->msg_lock, flags);
+ mutex_unlock(&chip->msg_lock);
*rfreq = frequency * chip->freq_ratio;
@@ -398,25 +396,23 @@ int lx_dsp_get_mac(struct lx6464es *chip)
int lx_dsp_set_granularity(struct lx6464es *chip, u32 gran)
{
- unsigned long flags;
int ret;
- spin_lock_irqsave(&chip->msg_lock, flags);
+ mutex_lock(&chip->msg_lock);
lx_message_init(&chip->rmh, CMD_02_SET_GRANULARITY);
chip->rmh.cmd[0] |= gran;
ret = lx_message_send_atomic(chip, &chip->rmh);
- spin_unlock_irqrestore(&chip->msg_lock, flags);
+ mutex_unlock(&chip->msg_lock);
return ret;
}
int lx_dsp_read_async_events(struct lx6464es *chip, u32 *data)
{
- unsigned long flags;
int ret;
- spin_lock_irqsave(&chip->msg_lock, flags);
+ mutex_lock(&chip->msg_lock);
lx_message_init(&chip->rmh, CMD_04_GET_EVENT);
chip->rmh.stat_len = 9; /* we don't necessarily need the full length */
@@ -426,7 +422,7 @@ int lx_dsp_read_async_events(struct lx6464es *chip, u32 *data)
if (!ret)
memcpy(data, chip->rmh.stat, chip->rmh.stat_len * sizeof(u32));
- spin_unlock_irqrestore(&chip->msg_lock, flags);
+ mutex_unlock(&chip->msg_lock);
return ret;
}
@@ -440,18 +436,16 @@ int lx_pipe_allocate(struct lx6464es *chip, u32 pipe, int is_capture,
int channels)
{
int err;
- unsigned long flags;
-
u32 pipe_cmd = PIPE_INFO_TO_CMD(is_capture, pipe);
- spin_lock_irqsave(&chip->msg_lock, flags);
+ mutex_lock(&chip->msg_lock);
lx_message_init(&chip->rmh, CMD_06_ALLOCATE_PIPE);
chip->rmh.cmd[0] |= pipe_cmd;
chip->rmh.cmd[0] |= channels;
err = lx_message_send_atomic(chip, &chip->rmh);
- spin_unlock_irqrestore(&chip->msg_lock, flags);
+ mutex_unlock(&chip->msg_lock);
if (err != 0)
dev_err(chip->card->dev, "could not allocate pipe\n");
@@ -462,17 +456,15 @@ int lx_pipe_allocate(struct lx6464es *chip, u32 pipe, int is_capture,
int lx_pipe_release(struct lx6464es *chip, u32 pipe, int is_capture)
{
int err;
- unsigned long flags;
-
u32 pipe_cmd = PIPE_INFO_TO_CMD(is_capture, pipe);
- spin_lock_irqsave(&chip->msg_lock, flags);
+ mutex_lock(&chip->msg_lock);
lx_message_init(&chip->rmh, CMD_07_RELEASE_PIPE);
chip->rmh.cmd[0] |= pipe_cmd;
err = lx_message_send_atomic(chip, &chip->rmh);
- spin_unlock_irqrestore(&chip->msg_lock, flags);
+ mutex_unlock(&chip->msg_lock);
return err;
}
@@ -481,8 +473,6 @@ int lx_buffer_ask(struct lx6464es *chip, u32 pipe, int is_capture,
u32 *r_needed, u32 *r_freed, u32 *size_array)
{
int err;
- unsigned long flags;
-
u32 pipe_cmd = PIPE_INFO_TO_CMD(is_capture, pipe);
#ifdef CONFIG_SND_DEBUG
@@ -493,7 +483,7 @@ int lx_buffer_ask(struct lx6464es *chip, u32 pipe, int is_capture,
*r_needed = 0;
*r_freed = 0;
- spin_lock_irqsave(&chip->msg_lock, flags);
+ mutex_lock(&chip->msg_lock);
lx_message_init(&chip->rmh, CMD_08_ASK_BUFFERS);
chip->rmh.cmd[0] |= pipe_cmd;
@@ -527,7 +517,7 @@ int lx_buffer_ask(struct lx6464es *chip, u32 pipe, int is_capture,
}
}
- spin_unlock_irqrestore(&chip->msg_lock, flags);
+ mutex_unlock(&chip->msg_lock);
return err;
}
@@ -535,36 +525,32 @@ int lx_buffer_ask(struct lx6464es *chip, u32 pipe, int is_capture,
int lx_pipe_stop(struct lx6464es *chip, u32 pipe, int is_capture)
{
int err;
- unsigned long flags;
-
u32 pipe_cmd = PIPE_INFO_TO_CMD(is_capture, pipe);
- spin_lock_irqsave(&chip->msg_lock, flags);
+ mutex_lock(&chip->msg_lock);
lx_message_init(&chip->rmh, CMD_09_STOP_PIPE);
chip->rmh.cmd[0] |= pipe_cmd;
err = lx_message_send_atomic(chip, &chip->rmh);
- spin_unlock_irqrestore(&chip->msg_lock, flags);
+ mutex_unlock(&chip->msg_lock);
return err;
}
static int lx_pipe_toggle_state(struct lx6464es *chip, u32 pipe, int is_capture)
{
int err;
- unsigned long flags;
-
u32 pipe_cmd = PIPE_INFO_TO_CMD(is_capture, pipe);
- spin_lock_irqsave(&chip->msg_lock, flags);
+ mutex_lock(&chip->msg_lock);
lx_message_init(&chip->rmh, CMD_0B_TOGGLE_PIPE_STATE);
chip->rmh.cmd[0] |= pipe_cmd;
err = lx_message_send_atomic(chip, &chip->rmh);
- spin_unlock_irqrestore(&chip->msg_lock, flags);
+ mutex_unlock(&chip->msg_lock);
return err;
}
@@ -600,11 +586,9 @@ int lx_pipe_sample_count(struct lx6464es *chip, u32 pipe, int is_capture,
u64 *rsample_count)
{
int err;
- unsigned long flags;
-
u32 pipe_cmd = PIPE_INFO_TO_CMD(is_capture, pipe);
- spin_lock_irqsave(&chip->msg_lock, flags);
+ mutex_lock(&chip->msg_lock);
lx_message_init(&chip->rmh, CMD_0A_GET_PIPE_SPL_COUNT);
chip->rmh.cmd[0] |= pipe_cmd;
@@ -621,18 +605,16 @@ int lx_pipe_sample_count(struct lx6464es *chip, u32 pipe, int is_capture,
+ chip->rmh.stat[1]; /* lo part */
}
- spin_unlock_irqrestore(&chip->msg_lock, flags);
+ mutex_unlock(&chip->msg_lock);
return err;
}
int lx_pipe_state(struct lx6464es *chip, u32 pipe, int is_capture, u16 *rstate)
{
int err;
- unsigned long flags;
-
u32 pipe_cmd = PIPE_INFO_TO_CMD(is_capture, pipe);
- spin_lock_irqsave(&chip->msg_lock, flags);
+ mutex_lock(&chip->msg_lock);
lx_message_init(&chip->rmh, CMD_0A_GET_PIPE_SPL_COUNT);
chip->rmh.cmd[0] |= pipe_cmd;
@@ -644,7 +626,7 @@ int lx_pipe_state(struct lx6464es *chip, u32 pipe, int is_capture, u16 *rstate)
else
*rstate = (chip->rmh.stat[0] >> PSTATE_OFFSET) & 0x0F;
- spin_unlock_irqrestore(&chip->msg_lock, flags);
+ mutex_unlock(&chip->msg_lock);
return err;
}
@@ -686,18 +668,16 @@ int lx_stream_set_state(struct lx6464es *chip, u32 pipe,
int is_capture, enum stream_state_t state)
{
int err;
- unsigned long flags;
-
u32 pipe_cmd = PIPE_INFO_TO_CMD(is_capture, pipe);
- spin_lock_irqsave(&chip->msg_lock, flags);
+ mutex_lock(&chip->msg_lock);
lx_message_init(&chip->rmh, CMD_13_SET_STREAM_STATE);
chip->rmh.cmd[0] |= pipe_cmd;
chip->rmh.cmd[0] |= state;
err = lx_message_send_atomic(chip, &chip->rmh);
- spin_unlock_irqrestore(&chip->msg_lock, flags);
+ mutex_unlock(&chip->msg_lock);
return err;
}
@@ -706,17 +686,14 @@ int lx_stream_set_format(struct lx6464es *chip, struct snd_pcm_runtime *runtime,
u32 pipe, int is_capture)
{
int err;
- unsigned long flags;
-
u32 pipe_cmd = PIPE_INFO_TO_CMD(is_capture, pipe);
-
u32 channels = runtime->channels;
if (runtime->channels != channels)
dev_err(chip->card->dev, "channel count mismatch: %d vs %d",
runtime->channels, channels);
- spin_lock_irqsave(&chip->msg_lock, flags);
+ mutex_lock(&chip->msg_lock);
lx_message_init(&chip->rmh, CMD_0C_DEF_STREAM);
chip->rmh.cmd[0] |= pipe_cmd;
@@ -732,7 +709,7 @@ int lx_stream_set_format(struct lx6464es *chip, struct snd_pcm_runtime *runtime,
chip->rmh.cmd[0] |= channels-1;
err = lx_message_send_atomic(chip, &chip->rmh);
- spin_unlock_irqrestore(&chip->msg_lock, flags);
+ mutex_unlock(&chip->msg_lock);
return err;
}
@@ -741,11 +718,9 @@ int lx_stream_state(struct lx6464es *chip, u32 pipe, int is_capture,
int *rstate)
{
int err;
- unsigned long flags;
-
u32 pipe_cmd = PIPE_INFO_TO_CMD(is_capture, pipe);
- spin_lock_irqsave(&chip->msg_lock, flags);
+ mutex_lock(&chip->msg_lock);
lx_message_init(&chip->rmh, CMD_0E_GET_STREAM_SPL_COUNT);
chip->rmh.cmd[0] |= pipe_cmd;
@@ -754,7 +729,7 @@ int lx_stream_state(struct lx6464es *chip, u32 pipe, int is_capture,
*rstate = (chip->rmh.stat[0] & SF_START) ? START_STATE : PAUSE_STATE;
- spin_unlock_irqrestore(&chip->msg_lock, flags);
+ mutex_unlock(&chip->msg_lock);
return err;
}
@@ -762,11 +737,9 @@ int lx_stream_sample_position(struct lx6464es *chip, u32 pipe, int is_capture,
u64 *r_bytepos)
{
int err;
- unsigned long flags;
-
u32 pipe_cmd = PIPE_INFO_TO_CMD(is_capture, pipe);
- spin_lock_irqsave(&chip->msg_lock, flags);
+ mutex_lock(&chip->msg_lock);
lx_message_init(&chip->rmh, CMD_0E_GET_STREAM_SPL_COUNT);
chip->rmh.cmd[0] |= pipe_cmd;
@@ -777,7 +750,7 @@ int lx_stream_sample_position(struct lx6464es *chip, u32 pipe, int is_capture,
<< 32) /* hi part */
+ chip->rmh.stat[1]; /* lo part */
- spin_unlock_irqrestore(&chip->msg_lock, flags);
+ mutex_unlock(&chip->msg_lock);
return err;
}
@@ -787,11 +760,9 @@ int lx_buffer_give(struct lx6464es *chip, u32 pipe, int is_capture,
u32 *r_buffer_index)
{
int err;
- unsigned long flags;
-
u32 pipe_cmd = PIPE_INFO_TO_CMD(is_capture, pipe);
- spin_lock_irqsave(&chip->msg_lock, flags);
+ mutex_lock(&chip->msg_lock);
lx_message_init(&chip->rmh, CMD_0F_UPDATE_BUFFER);
chip->rmh.cmd[0] |= pipe_cmd;
@@ -828,7 +799,7 @@ int lx_buffer_give(struct lx6464es *chip, u32 pipe, int is_capture,
"lx_buffer_give EB_CMD_REFUSED\n");
done:
- spin_unlock_irqrestore(&chip->msg_lock, flags);
+ mutex_unlock(&chip->msg_lock);
return err;
}
@@ -836,11 +807,9 @@ int lx_buffer_free(struct lx6464es *chip, u32 pipe, int is_capture,
u32 *r_buffer_size)
{
int err;
- unsigned long flags;
-
u32 pipe_cmd = PIPE_INFO_TO_CMD(is_capture, pipe);
- spin_lock_irqsave(&chip->msg_lock, flags);
+ mutex_lock(&chip->msg_lock);
lx_message_init(&chip->rmh, CMD_11_CANCEL_BUFFER);
chip->rmh.cmd[0] |= pipe_cmd;
@@ -852,7 +821,7 @@ int lx_buffer_free(struct lx6464es *chip, u32 pipe, int is_capture,
if (err == 0)
*r_buffer_size = chip->rmh.stat[0] & MASK_DATA_SIZE;
- spin_unlock_irqrestore(&chip->msg_lock, flags);
+ mutex_unlock(&chip->msg_lock);
return err;
}
@@ -860,11 +829,9 @@ int lx_buffer_cancel(struct lx6464es *chip, u32 pipe, int is_capture,
u32 buffer_index)
{
int err;
- unsigned long flags;
-
u32 pipe_cmd = PIPE_INFO_TO_CMD(is_capture, pipe);
- spin_lock_irqsave(&chip->msg_lock, flags);
+ mutex_lock(&chip->msg_lock);
lx_message_init(&chip->rmh, CMD_11_CANCEL_BUFFER);
chip->rmh.cmd[0] |= pipe_cmd;
@@ -872,7 +839,7 @@ int lx_buffer_cancel(struct lx6464es *chip, u32 pipe, int is_capture,
err = lx_message_send_atomic(chip, &chip->rmh);
- spin_unlock_irqrestore(&chip->msg_lock, flags);
+ mutex_unlock(&chip->msg_lock);
return err;
}
@@ -885,12 +852,10 @@ int lx_buffer_cancel(struct lx6464es *chip, u32 pipe, int is_capture,
int lx_level_unmute(struct lx6464es *chip, int is_capture, int unmute)
{
int err;
- unsigned long flags;
-
/* bit set to 1: channel muted */
u64 mute_mask = unmute ? 0 : 0xFFFFFFFFFFFFFFFFLLU;
- spin_lock_irqsave(&chip->msg_lock, flags);
+ mutex_lock(&chip->msg_lock);
lx_message_init(&chip->rmh, CMD_0D_SET_MUTE);
chip->rmh.cmd[0] |= PIPE_INFO_TO_CMD(is_capture, 0);
@@ -904,7 +869,7 @@ int lx_level_unmute(struct lx6464es *chip, int is_capture, int unmute)
err = lx_message_send_atomic(chip, &chip->rmh);
- spin_unlock_irqrestore(&chip->msg_lock, flags);
+ mutex_unlock(&chip->msg_lock);
return err;
}
@@ -931,10 +896,9 @@ int lx_level_peaks(struct lx6464es *chip, int is_capture, int channels,
u32 *r_levels)
{
int err = 0;
- unsigned long flags;
int i;
- spin_lock_irqsave(&chip->msg_lock, flags);
+ mutex_lock(&chip->msg_lock);
for (i = 0; i < channels; i += 4) {
u32 s0, s1, s2, s3;
@@ -959,7 +923,7 @@ int lx_level_peaks(struct lx6464es *chip, int is_capture, int channels,
r_levels += 4;
}
- spin_unlock_irqrestore(&chip->msg_lock, flags);
+ mutex_unlock(&chip->msg_lock);
return err;
}
@@ -1075,7 +1039,6 @@ static int lx_interrupt_request_new_buffer(struct lx6464es *chip,
struct snd_pcm_substream *substream = lx_stream->stream;
const unsigned int is_capture = lx_stream->is_capture;
int err;
- unsigned long flags;
const u32 channels = substream->runtime->channels;
const u32 bytes_per_frame = channels * 3;
@@ -1095,7 +1058,7 @@ static int lx_interrupt_request_new_buffer(struct lx6464es *chip,
dev_dbg(chip->card->dev, "->lx_interrupt_request_new_buffer\n");
- spin_lock_irqsave(&chip->lock, flags);
+ mutex_lock(&chip->lock);
err = lx_buffer_ask(chip, 0, is_capture, &needed, &freed, size_array);
dev_dbg(chip->card->dev,
@@ -1109,85 +1072,28 @@ static int lx_interrupt_request_new_buffer(struct lx6464es *chip,
buffer_index, (unsigned long)buf, period_bytes);
lx_stream->frame_pos = next_pos;
- spin_unlock_irqrestore(&chip->lock, flags);
+ mutex_unlock(&chip->lock);
return err;
}
-void lx_tasklet_playback(unsigned long data)
-{
- struct lx6464es *chip = (struct lx6464es *)data;
- struct lx_stream *lx_stream = &chip->playback_stream;
- int err;
-
- dev_dbg(chip->card->dev, "->lx_tasklet_playback\n");
-
- err = lx_interrupt_request_new_buffer(chip, lx_stream);
- if (err < 0)
- dev_err(chip->card->dev,
- "cannot request new buffer for playback\n");
-
- snd_pcm_period_elapsed(lx_stream->stream);
-}
-
-void lx_tasklet_capture(unsigned long data)
-{
- struct lx6464es *chip = (struct lx6464es *)data;
- struct lx_stream *lx_stream = &chip->capture_stream;
- int err;
-
- dev_dbg(chip->card->dev, "->lx_tasklet_capture\n");
- err = lx_interrupt_request_new_buffer(chip, lx_stream);
- if (err < 0)
- dev_err(chip->card->dev,
- "cannot request new buffer for capture\n");
-
- snd_pcm_period_elapsed(lx_stream->stream);
-}
-
-
-
-static int lx_interrupt_handle_audio_transfer(struct lx6464es *chip,
- u64 notified_in_pipe_mask,
- u64 notified_out_pipe_mask)
-{
- int err = 0;
-
- if (notified_in_pipe_mask) {
- dev_dbg(chip->card->dev,
- "requesting audio transfer for capture\n");
- tasklet_hi_schedule(&chip->tasklet_capture);
- }
-
- if (notified_out_pipe_mask) {
- dev_dbg(chip->card->dev,
- "requesting audio transfer for playback\n");
- tasklet_hi_schedule(&chip->tasklet_playback);
- }
-
- return err;
-}
-
-
irqreturn_t lx_interrupt(int irq, void *dev_id)
{
struct lx6464es *chip = dev_id;
int async_pending, async_escmd;
u32 irqsrc;
-
- spin_lock(&chip->lock);
+ bool wake_thread = false;
dev_dbg(chip->card->dev,
"**************************************************\n");
if (!lx_interrupt_ack(chip, &irqsrc, &async_pending, &async_escmd)) {
- spin_unlock(&chip->lock);
dev_dbg(chip->card->dev, "IRQ_NONE\n");
return IRQ_NONE; /* this device did not cause the interrupt */
}
if (irqsrc & MASK_SYS_STATUS_CMD_DONE)
- goto exit;
+ return IRQ_HANDLED;
if (irqsrc & MASK_SYS_STATUS_EOBI)
dev_dbg(chip->card->dev, "interrupt: EOBI\n");
@@ -1202,27 +1108,8 @@ irqreturn_t lx_interrupt(int irq, void *dev_id)
dev_dbg(chip->card->dev, "interrupt: ORUN\n");
if (async_pending) {
- u64 notified_in_pipe_mask = 0;
- u64 notified_out_pipe_mask = 0;
- int freq_changed;
- int err;
-
- /* handle async events */
- err = lx_interrupt_handle_async_events(chip, irqsrc,
- &freq_changed,
- &notified_in_pipe_mask,
- &notified_out_pipe_mask);
- if (err)
- dev_err(chip->card->dev,
- "error handling async events\n");
-
- err = lx_interrupt_handle_audio_transfer(chip,
- notified_in_pipe_mask,
- notified_out_pipe_mask
- );
- if (err)
- dev_err(chip->card->dev,
- "error during audio transfer\n");
+ wake_thread = true;
+ chip->irqsrc = irqsrc;
}
if (async_escmd) {
@@ -1235,9 +1122,50 @@ irqreturn_t lx_interrupt(int irq, void *dev_id)
dev_dbg(chip->card->dev, "interrupt requests escmd handling\n");
}
-exit:
- spin_unlock(&chip->lock);
- return IRQ_HANDLED; /* this device caused the interrupt */
+ return wake_thread ? IRQ_WAKE_THREAD : IRQ_HANDLED;
+}
+
+irqreturn_t lx_threaded_irq(int irq, void *dev_id)
+{
+ struct lx6464es *chip = dev_id;
+ u64 notified_in_pipe_mask = 0;
+ u64 notified_out_pipe_mask = 0;
+ int freq_changed;
+ int err;
+
+ /* handle async events */
+ err = lx_interrupt_handle_async_events(chip, chip->irqsrc,
+ &freq_changed,
+ &notified_in_pipe_mask,
+ &notified_out_pipe_mask);
+ if (err)
+ dev_err(chip->card->dev, "error handling async events\n");
+
+ if (notified_in_pipe_mask) {
+ struct lx_stream *lx_stream = &chip->capture_stream;
+
+ dev_dbg(chip->card->dev,
+ "requesting audio transfer for capture\n");
+ err = lx_interrupt_request_new_buffer(chip, lx_stream);
+ if (err < 0)
+ dev_err(chip->card->dev,
+ "cannot request new buffer for capture\n");
+ snd_pcm_period_elapsed(lx_stream->stream);
+ }
+
+ if (notified_out_pipe_mask) {
+ struct lx_stream *lx_stream = &chip->playback_stream;
+
+ dev_dbg(chip->card->dev,
+ "requesting audio transfer for playback\n");
+ err = lx_interrupt_request_new_buffer(chip, lx_stream);
+ if (err < 0)
+ dev_err(chip->card->dev,
+ "cannot request new buffer for playback\n");
+ snd_pcm_period_elapsed(lx_stream->stream);
+ }
+
+ return IRQ_HANDLED;
}
diff --git a/sound/pci/lx6464es/lx_core.h b/sound/pci/lx6464es/lx_core.h
index 5ec5e04da1a5..0cc140ca98e3 100644
--- a/sound/pci/lx6464es/lx_core.h
+++ b/sound/pci/lx6464es/lx_core.h
@@ -181,12 +181,10 @@ int lx_level_peaks(struct lx6464es *chip, int is_capture, int channels,
/* interrupt handling */
irqreturn_t lx_interrupt(int irq, void *dev_id);
+irqreturn_t lx_threaded_irq(int irq, void *dev_id);
void lx_irq_enable(struct lx6464es *chip);
void lx_irq_disable(struct lx6464es *chip);
-void lx_tasklet_capture(unsigned long data);
-void lx_tasklet_playback(unsigned long data);
-
/* Stream Format Header Defines (for LIN and IEEE754) */
#define HEADER_FMT_BASE HEADER_FMT_BASE_LIN
diff --git a/sound/pci/mixart/mixart.c b/sound/pci/mixart/mixart.c
index 75fc342cff2a..1faf47e81570 100644
--- a/sound/pci/mixart/mixart.c
+++ b/sound/pci/mixart/mixart.c
@@ -986,6 +986,7 @@ static int snd_mixart_pcm_analog(struct snd_mixart *chip)
snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_mixart_capture_ops);
pcm->info_flags = 0;
+ pcm->nonatomic = true;
strcpy(pcm->name, name);
preallocate_buffers(chip, pcm);
@@ -1018,6 +1019,7 @@ static int snd_mixart_pcm_digital(struct snd_mixart *chip)
snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_mixart_capture_ops);
pcm->info_flags = 0;
+ pcm->nonatomic = true;
strcpy(pcm->name, name);
preallocate_buffers(chip, pcm);
@@ -1303,8 +1305,9 @@ static int snd_mixart_probe(struct pci_dev *pci,
}
}
- if (request_irq(pci->irq, snd_mixart_interrupt, IRQF_SHARED,
- KBUILD_MODNAME, mgr)) {
+ if (request_threaded_irq(pci->irq, snd_mixart_interrupt,
+ snd_mixart_threaded_irq, IRQF_SHARED,
+ KBUILD_MODNAME, mgr)) {
dev_err(&pci->dev, "unable to grab IRQ %d\n", pci->irq);
snd_mixart_free(mgr);
return -EBUSY;
@@ -1314,24 +1317,18 @@ static int snd_mixart_probe(struct pci_dev *pci,
sprintf(mgr->shortname, "Digigram miXart");
sprintf(mgr->longname, "%s at 0x%lx & 0x%lx, irq %i", mgr->shortname, mgr->mem[0].phys, mgr->mem[1].phys, mgr->irq);
- /* ISR spinlock */
- spin_lock_init(&mgr->lock);
-
/* init mailbox */
mgr->msg_fifo_readptr = 0;
mgr->msg_fifo_writeptr = 0;
- spin_lock_init(&mgr->msg_lock);
- mutex_init(&mgr->msg_mutex);
+ mutex_init(&mgr->lock);
+ mutex_init(&mgr->msg_lock);
init_waitqueue_head(&mgr->msg_sleep);
atomic_set(&mgr->msg_processed, 0);
/* init setup mutex*/
mutex_init(&mgr->setup_mutex);
- /* init message taslket */
- tasklet_init(&mgr->msg_taskq, snd_mixart_msg_tasklet, (unsigned long) mgr);
-
/* card assignment */
mgr->num_cards = MIXART_MAX_CARDS; /* 4 FIXME: configurable? */
for (i = 0; i < mgr->num_cards; i++) {
diff --git a/sound/pci/mixart/mixart.h b/sound/pci/mixart/mixart.h
index 561634d5c007..0cc17e0ea34a 100644
--- a/sound/pci/mixart/mixart.h
+++ b/sound/pci/mixart/mixart.h
@@ -78,22 +78,18 @@ struct mixart_mgr {
char shortname[32]; /* short name of this soundcard */
char longname[80]; /* name of this soundcard */
- /* message tasklet */
- struct tasklet_struct msg_taskq;
-
/* one and only blocking message or notification may be pending */
u32 pending_event;
wait_queue_head_t msg_sleep;
- /* messages stored for tasklet */
+ /* messages fifo */
u32 msg_fifo[MSG_FIFO_SIZE];
int msg_fifo_readptr;
int msg_fifo_writeptr;
atomic_t msg_processed; /* number of messages to be processed in takslet */
- spinlock_t lock; /* interrupt spinlock */
- spinlock_t msg_lock; /* mailbox spinlock */
- struct mutex msg_mutex; /* mutex for blocking_requests */
+ struct mutex lock; /* interrupt lock */
+ struct mutex msg_lock; /* mailbox lock */
struct mutex setup_mutex; /* mutex used in hw_params, open and close */
diff --git a/sound/pci/mixart/mixart_core.c b/sound/pci/mixart/mixart_core.c
index 84f67450924e..fe80313674d9 100644
--- a/sound/pci/mixart/mixart_core.c
+++ b/sound/pci/mixart/mixart_core.c
@@ -76,7 +76,6 @@ static int retrieve_msg_frame(struct mixart_mgr *mgr, u32 *msg_frame)
static int get_msg(struct mixart_mgr *mgr, struct mixart_msg *resp,
u32 msg_frame_address )
{
- unsigned long flags;
u32 headptr;
u32 size;
int err;
@@ -84,7 +83,7 @@ static int get_msg(struct mixart_mgr *mgr, struct mixart_msg *resp,
unsigned int i;
#endif
- spin_lock_irqsave(&mgr->msg_lock, flags);
+ mutex_lock(&mgr->msg_lock);
err = 0;
/* copy message descriptor from miXart to driver */
@@ -133,7 +132,7 @@ static int get_msg(struct mixart_mgr *mgr, struct mixart_msg *resp,
writel_be(headptr, MIXART_MEM(mgr, MSG_OUTBOUND_FREE_HEAD));
_clean_exit:
- spin_unlock_irqrestore(&mgr->msg_lock, flags);
+ mutex_unlock(&mgr->msg_lock);
return err;
}
@@ -243,28 +242,24 @@ int snd_mixart_send_msg(struct mixart_mgr *mgr, struct mixart_msg *request, int
wait_queue_t wait;
long timeout;
- mutex_lock(&mgr->msg_mutex);
-
init_waitqueue_entry(&wait, current);
- spin_lock_irq(&mgr->msg_lock);
+ mutex_lock(&mgr->msg_lock);
/* send the message */
err = send_msg(mgr, request, max_resp_size, 1, &msg_frame); /* send and mark the answer pending */
if (err) {
- spin_unlock_irq(&mgr->msg_lock);
- mutex_unlock(&mgr->msg_mutex);
+ mutex_unlock(&mgr->msg_lock);
return err;
}
set_current_state(TASK_UNINTERRUPTIBLE);
add_wait_queue(&mgr->msg_sleep, &wait);
- spin_unlock_irq(&mgr->msg_lock);
+ mutex_unlock(&mgr->msg_lock);
timeout = schedule_timeout(MSG_TIMEOUT_JIFFIES);
remove_wait_queue(&mgr->msg_sleep, &wait);
if (! timeout) {
/* error - no ack */
- mutex_unlock(&mgr->msg_mutex);
dev_err(&mgr->pci->dev,
"error: no response on msg %x\n", msg_frame);
return -EIO;
@@ -281,7 +276,6 @@ int snd_mixart_send_msg(struct mixart_mgr *mgr, struct mixart_msg *request, int
if( request->message_id != resp.message_id )
dev_err(&mgr->pci->dev, "RESPONSE ERROR!\n");
- mutex_unlock(&mgr->msg_mutex);
return err;
}
@@ -300,34 +294,29 @@ int snd_mixart_send_msg_wait_notif(struct mixart_mgr *mgr,
if (snd_BUG_ON(notif_event & MSG_CANCEL_NOTIFY_MASK))
return -EINVAL;
- mutex_lock(&mgr->msg_mutex);
-
init_waitqueue_entry(&wait, current);
- spin_lock_irq(&mgr->msg_lock);
+ mutex_lock(&mgr->msg_lock);
/* send the message */
err = send_msg(mgr, request, MSG_DEFAULT_SIZE, 1, &notif_event); /* send and mark the notification event pending */
if(err) {
- spin_unlock_irq(&mgr->msg_lock);
- mutex_unlock(&mgr->msg_mutex);
+ mutex_unlock(&mgr->msg_lock);
return err;
}
set_current_state(TASK_UNINTERRUPTIBLE);
add_wait_queue(&mgr->msg_sleep, &wait);
- spin_unlock_irq(&mgr->msg_lock);
+ mutex_unlock(&mgr->msg_lock);
timeout = schedule_timeout(MSG_TIMEOUT_JIFFIES);
remove_wait_queue(&mgr->msg_sleep, &wait);
if (! timeout) {
/* error - no ack */
- mutex_unlock(&mgr->msg_mutex);
dev_err(&mgr->pci->dev,
"error: notification %x not received\n", notif_event);
return -EIO;
}
- mutex_unlock(&mgr->msg_mutex);
return 0;
}
@@ -335,13 +324,12 @@ int snd_mixart_send_msg_wait_notif(struct mixart_mgr *mgr,
int snd_mixart_send_msg_nonblock(struct mixart_mgr *mgr, struct mixart_msg *request)
{
u32 message_frame;
- unsigned long flags;
int err;
/* just send the message (do not mark it as a pending one) */
- spin_lock_irqsave(&mgr->msg_lock, flags);
+ mutex_lock(&mgr->msg_lock);
err = send_msg(mgr, request, MSG_DEFAULT_SIZE, 0, &message_frame);
- spin_unlock_irqrestore(&mgr->msg_lock, flags);
+ mutex_unlock(&mgr->msg_lock);
/* the answer will be handled by snd_struct mixart_msgasklet() */
atomic_inc(&mgr->msg_processed);
@@ -350,19 +338,16 @@ int snd_mixart_send_msg_nonblock(struct mixart_mgr *mgr, struct mixart_msg *requ
}
-/* common buffer of tasklet and interrupt to send/receive messages */
+/* common buffer of interrupt to send/receive messages */
static u32 mixart_msg_data[MSG_DEFAULT_SIZE / 4];
-void snd_mixart_msg_tasklet(unsigned long arg)
+static void snd_mixart_process_msg(struct mixart_mgr *mgr)
{
- struct mixart_mgr *mgr = ( struct mixart_mgr*)(arg);
struct mixart_msg resp;
u32 msg, addr, type;
int err;
- spin_lock(&mgr->lock);
-
while (mgr->msg_fifo_readptr != mgr->msg_fifo_writeptr) {
msg = mgr->msg_fifo[mgr->msg_fifo_readptr];
mgr->msg_fifo_readptr++;
@@ -381,7 +366,7 @@ void snd_mixart_msg_tasklet(unsigned long arg)
err = get_msg(mgr, &resp, addr);
if( err < 0 ) {
dev_err(&mgr->pci->dev,
- "tasklet: error(%d) reading mf %x\n",
+ "error(%d) reading mf %x\n",
err, msg);
break;
}
@@ -393,12 +378,12 @@ void snd_mixart_msg_tasklet(unsigned long arg)
case MSG_STREAM_STOP_OUTPUT_STAGE_PACKET:
if(mixart_msg_data[0])
dev_err(&mgr->pci->dev,
- "tasklet : error MSG_STREAM_ST***_***PUT_STAGE_PACKET status=%x\n",
+ "error MSG_STREAM_ST***_***PUT_STAGE_PACKET status=%x\n",
mixart_msg_data[0]);
break;
default:
dev_dbg(&mgr->pci->dev,
- "tasklet received mf(%x) : msg_id(%x) uid(%x, %x) size(%zd)\n",
+ "received mf(%x) : msg_id(%x) uid(%x, %x) size(%zd)\n",
msg, resp.message_id, resp.uid.object_id, resp.uid.desc, resp.size);
break;
}
@@ -409,7 +394,7 @@ void snd_mixart_msg_tasklet(unsigned long arg)
/* get_msg() necessary */
default:
dev_err(&mgr->pci->dev,
- "tasklet doesn't know what to do with message %x\n",
+ "doesn't know what to do with message %x\n",
msg);
} /* switch type */
@@ -417,26 +402,17 @@ void snd_mixart_msg_tasklet(unsigned long arg)
atomic_dec(&mgr->msg_processed);
} /* while there is a msg in fifo */
-
- spin_unlock(&mgr->lock);
}
irqreturn_t snd_mixart_interrupt(int irq, void *dev_id)
{
struct mixart_mgr *mgr = dev_id;
- int err;
- struct mixart_msg resp;
-
- u32 msg;
u32 it_reg;
- spin_lock(&mgr->lock);
-
it_reg = readl_le(MIXART_REG(mgr, MIXART_PCI_OMISR_OFFSET));
if( !(it_reg & MIXART_OIDI) ) {
/* this device did not cause the interrupt */
- spin_unlock(&mgr->lock);
return IRQ_NONE;
}
@@ -450,6 +426,17 @@ irqreturn_t snd_mixart_interrupt(int irq, void *dev_id)
/* clear interrupt */
writel_le( MIXART_OIDI, MIXART_REG(mgr, MIXART_PCI_OMISR_OFFSET) );
+ return IRQ_WAKE_THREAD;
+}
+
+irqreturn_t snd_mixart_threaded_irq(int irq, void *dev_id)
+{
+ struct mixart_mgr *mgr = dev_id;
+ int err;
+ struct mixart_msg resp;
+ u32 msg;
+
+ mutex_lock(&mgr->lock);
/* process interrupt */
while (retrieve_msg_frame(mgr, &msg)) {
@@ -518,9 +505,9 @@ irqreturn_t snd_mixart_interrupt(int irq, void *dev_id)
stream->buf_period_frag = (u32)( sample_count - stream->abs_period_elapsed );
if(elapsed) {
- spin_unlock(&mgr->lock);
+ mutex_unlock(&mgr->lock);
snd_pcm_period_elapsed(stream->substream);
- spin_lock(&mgr->lock);
+ mutex_lock(&mgr->lock);
}
}
}
@@ -556,7 +543,7 @@ irqreturn_t snd_mixart_interrupt(int irq, void *dev_id)
/* no break, continue ! */
case MSG_TYPE_ANSWER:
/* answer or notification to a message we are waiting for*/
- spin_lock(&mgr->msg_lock);
+ mutex_lock(&mgr->msg_lock);
if( (msg & ~MSG_TYPE_MASK) == mgr->pending_event ) {
wake_up(&mgr->msg_sleep);
mgr->pending_event = 0;
@@ -566,9 +553,9 @@ irqreturn_t snd_mixart_interrupt(int irq, void *dev_id)
mgr->msg_fifo[mgr->msg_fifo_writeptr] = msg;
mgr->msg_fifo_writeptr++;
mgr->msg_fifo_writeptr %= MSG_FIFO_SIZE;
- tasklet_schedule(&mgr->msg_taskq);
+ snd_mixart_process_msg(mgr);
}
- spin_unlock(&mgr->msg_lock);
+ mutex_unlock(&mgr->msg_lock);
break;
case MSG_TYPE_REQUEST:
default:
@@ -582,7 +569,7 @@ irqreturn_t snd_mixart_interrupt(int irq, void *dev_id)
/* allow interrupt again */
writel_le( MIXART_ALLOW_OUTBOUND_DOORBELL, MIXART_REG( mgr, MIXART_PCI_OMIMR_OFFSET));
- spin_unlock(&mgr->lock);
+ mutex_unlock(&mgr->lock);
return IRQ_HANDLED;
}
diff --git a/sound/pci/mixart/mixart_core.h b/sound/pci/mixart/mixart_core.h
index c919b734756f..d1722e575409 100644
--- a/sound/pci/mixart/mixart_core.h
+++ b/sound/pci/mixart/mixart_core.h
@@ -564,7 +564,7 @@ int snd_mixart_send_msg_wait_notif(struct mixart_mgr *mgr, struct mixart_msg *r
int snd_mixart_send_msg_nonblock(struct mixart_mgr *mgr, struct mixart_msg *request);
irqreturn_t snd_mixart_interrupt(int irq, void *dev_id);
-void snd_mixart_msg_tasklet(unsigned long arg);
+irqreturn_t snd_mixart_threaded_irq(int irq, void *dev_id);
void snd_mixart_reset_board(struct mixart_mgr *mgr);
diff --git a/sound/pci/oxygen/oxygen_pcm.c b/sound/pci/oxygen/oxygen_pcm.c
index cc0bcd9f3350..02828240ba15 100644
--- a/sound/pci/oxygen/oxygen_pcm.c
+++ b/sound/pci/oxygen/oxygen_pcm.c
@@ -29,6 +29,9 @@
/* the multichannel DMA channel has a 24-bit counter */
#define BUFFER_BYTES_MAX_MULTICH ((1 << 24) * 4)
+#define FIFO_BYTES 256
+#define FIFO_BYTES_MULTICH 1024
+
#define PERIOD_BYTES_MIN 64
#define DEFAULT_BUFFER_BYTES (BUFFER_BYTES_MAX / 2)
@@ -60,6 +63,7 @@ static const struct snd_pcm_hardware oxygen_stereo_hardware = {
.period_bytes_max = BUFFER_BYTES_MAX,
.periods_min = 1,
.periods_max = BUFFER_BYTES_MAX / PERIOD_BYTES_MIN,
+ .fifo_size = FIFO_BYTES,
};
static const struct snd_pcm_hardware oxygen_multichannel_hardware = {
.info = SNDRV_PCM_INFO_MMAP |
@@ -87,6 +91,7 @@ static const struct snd_pcm_hardware oxygen_multichannel_hardware = {
.period_bytes_max = BUFFER_BYTES_MAX_MULTICH,
.periods_min = 1,
.periods_max = BUFFER_BYTES_MAX_MULTICH / PERIOD_BYTES_MIN,
+ .fifo_size = FIFO_BYTES_MULTICH,
};
static const struct snd_pcm_hardware oxygen_ac97_hardware = {
.info = SNDRV_PCM_INFO_MMAP |
@@ -106,6 +111,7 @@ static const struct snd_pcm_hardware oxygen_ac97_hardware = {
.period_bytes_max = BUFFER_BYTES_MAX,
.periods_min = 1,
.periods_max = BUFFER_BYTES_MAX / PERIOD_BYTES_MIN,
+ .fifo_size = FIFO_BYTES,
};
static const struct snd_pcm_hardware *const oxygen_hardware[PCM_COUNT] = {
@@ -141,6 +147,10 @@ static int oxygen_open(struct snd_pcm_substream *substream,
runtime->hw.rates &= ~(SNDRV_PCM_RATE_32000 |
SNDRV_PCM_RATE_64000);
runtime->hw.rate_min = 44100;
+ /* fall through */
+ case PCM_A:
+ case PCM_B:
+ runtime->hw.fifo_size = 0;
break;
case PCM_MULTICH:
runtime->hw.channels_max = chip->model.dac_channels_pcm;
diff --git a/sound/pci/oxygen/virtuoso.c b/sound/pci/oxygen/virtuoso.c
index 7b317a28a19c..83de6fb01021 100644
--- a/sound/pci/oxygen/virtuoso.c
+++ b/sound/pci/oxygen/virtuoso.c
@@ -52,6 +52,7 @@ static const struct pci_device_id xonar_ids[] = {
{ OXYGEN_PCI_SUBID(0x1043, 0x835d) },
{ OXYGEN_PCI_SUBID(0x1043, 0x835e) },
{ OXYGEN_PCI_SUBID(0x1043, 0x838e) },
+ { OXYGEN_PCI_SUBID(0x1043, 0x8428) },
{ OXYGEN_PCI_SUBID(0x1043, 0x8522) },
{ OXYGEN_PCI_SUBID(0x1043, 0x85f4) },
{ OXYGEN_PCI_SUBID_BROKEN_EEPROM },
diff --git a/sound/pci/oxygen/xonar_pcm179x.c b/sound/pci/oxygen/xonar_pcm179x.c
index 0d6a805e8b62..24109d37ca09 100644
--- a/sound/pci/oxygen/xonar_pcm179x.c
+++ b/sound/pci/oxygen/xonar_pcm179x.c
@@ -212,6 +212,9 @@
#define GPIO_ST_MAGIC 0x0040
#define GPIO_ST_HP 0x0080
+#define GPIO_XENSE_OUTPUT_ENABLE (0x0001 | 0x0010 | 0x0020)
+#define GPIO_XENSE_SPEAKERS 0x0080
+
#define I2C_DEVICE_PCM1796(i) (0x98 + ((i) << 1)) /* 10011, ii, /W=0 */
#define I2C_DEVICE_CS2000 0x9c /* 100111, 0, /W=0 */
@@ -500,6 +503,51 @@ static void xonar_stx_init(struct oxygen *chip)
xonar_st_init_common(chip);
}
+static void xonar_xense_init(struct oxygen *chip)
+{
+ struct xonar_pcm179x *data = chip->model_data;
+
+ data->generic.ext_power_reg = OXYGEN_GPI_DATA;
+ data->generic.ext_power_int_reg = OXYGEN_GPI_INTERRUPT_MASK;
+ data->generic.ext_power_bit = GPI_EXT_POWER;
+ xonar_init_ext_power(chip);
+
+ data->generic.anti_pop_delay = 100;
+ data->has_cs2000 = 1;
+ data->cs2000_regs[CS2000_FUN_CFG_1] = CS2000_REF_CLK_DIV_1;
+
+ oxygen_write16(chip, OXYGEN_I2S_A_FORMAT,
+ OXYGEN_RATE_48000 |
+ OXYGEN_I2S_FORMAT_I2S |
+ OXYGEN_I2S_MCLK(MCLK_512) |
+ OXYGEN_I2S_BITS_16 |
+ OXYGEN_I2S_MASTER |
+ OXYGEN_I2S_BCLK_64);
+
+ xonar_st_init_i2c(chip);
+ cs2000_registers_init(chip);
+
+ data->generic.output_enable_bit = GPIO_XENSE_OUTPUT_ENABLE;
+ data->dacs = 1;
+ data->hp_gain_offset = 2*-18;
+
+ pcm1796_init(chip);
+
+ oxygen_set_bits16(chip, OXYGEN_GPIO_CONTROL,
+ GPIO_INPUT_ROUTE | GPIO_ST_HP_REAR |
+ GPIO_ST_MAGIC | GPIO_XENSE_SPEAKERS);
+ oxygen_clear_bits16(chip, OXYGEN_GPIO_DATA,
+ GPIO_INPUT_ROUTE | GPIO_ST_HP_REAR |
+ GPIO_XENSE_SPEAKERS);
+
+ xonar_init_cs53x1(chip);
+ xonar_enable_output(chip);
+
+ snd_component_add(chip->card, "PCM1796");
+ snd_component_add(chip->card, "CS5381");
+ snd_component_add(chip->card, "CS2000");
+}
+
static void xonar_d2_cleanup(struct oxygen *chip)
{
xonar_disable_output(chip);
@@ -862,6 +910,67 @@ static const struct snd_kcontrol_new st_controls[] = {
},
};
+static int xense_output_switch_get(struct snd_kcontrol *ctl,
+ struct snd_ctl_elem_value *value)
+{
+ struct oxygen *chip = ctl->private_data;
+ u16 gpio;
+
+ gpio = oxygen_read16(chip, OXYGEN_GPIO_DATA);
+ if (gpio & GPIO_XENSE_SPEAKERS)
+ value->value.enumerated.item[0] = 0;
+ else if (!(gpio & GPIO_XENSE_SPEAKERS) && (gpio & GPIO_ST_HP_REAR))
+ value->value.enumerated.item[0] = 1;
+ else
+ value->value.enumerated.item[0] = 2;
+ return 0;
+}
+
+static int xense_output_switch_put(struct snd_kcontrol *ctl,
+ struct snd_ctl_elem_value *value)
+{
+ struct oxygen *chip = ctl->private_data;
+ struct xonar_pcm179x *data = chip->model_data;
+ u16 gpio_old, gpio;
+
+ mutex_lock(&chip->mutex);
+ gpio_old = oxygen_read16(chip, OXYGEN_GPIO_DATA);
+ gpio = gpio_old;
+ switch (value->value.enumerated.item[0]) {
+ case 0:
+ gpio |= GPIO_XENSE_SPEAKERS | GPIO_ST_HP_REAR;
+ break;
+ case 1:
+ gpio = (gpio | GPIO_ST_HP_REAR) & ~GPIO_XENSE_SPEAKERS;
+ break;
+ case 2:
+ gpio &= ~(GPIO_XENSE_SPEAKERS | GPIO_ST_HP_REAR);
+ break;
+ }
+ oxygen_write16(chip, OXYGEN_GPIO_DATA, gpio);
+ data->hp_active = !(gpio & GPIO_XENSE_SPEAKERS);
+ update_pcm1796_volume(chip);
+ mutex_unlock(&chip->mutex);
+ return gpio != gpio_old;
+}
+
+static const struct snd_kcontrol_new xense_controls[] = {
+ {
+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ .name = "Analog Output",
+ .info = st_output_switch_info,
+ .get = xense_output_switch_get,
+ .put = xense_output_switch_put,
+ },
+ {
+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ .name = "Headphones Impedance Playback Enum",
+ .info = st_hp_volume_offset_info,
+ .get = st_hp_volume_offset_get,
+ .put = st_hp_volume_offset_put,
+ },
+};
+
static void xonar_line_mic_ac97_switch(struct oxygen *chip,
unsigned int reg, unsigned int mute)
{
@@ -949,6 +1058,23 @@ static int xonar_st_mixer_init(struct oxygen *chip)
return 0;
}
+static int xonar_xense_mixer_init(struct oxygen *chip)
+{
+ unsigned int i;
+ int err;
+
+ for (i = 0; i < ARRAY_SIZE(xense_controls); ++i) {
+ err = snd_ctl_add(chip->card,
+ snd_ctl_new1(&xense_controls[i], chip));
+ if (err < 0)
+ return err;
+ }
+ err = add_pcm1796_controls(chip);
+ if (err < 0)
+ return err;
+ return 0;
+}
+
static void dump_pcm1796_registers(struct oxygen *chip,
struct snd_info_buffer *buffer)
{
@@ -1159,6 +1285,13 @@ int get_xonar_pcm179x_model(struct oxygen *chip,
chip->model.resume = xonar_stx_resume;
chip->model.set_dac_params = set_pcm1796_params;
break;
+ case 0x8428:
+ chip->model = model_xonar_st;
+ chip->model.shortname = "Xonar Xense";
+ chip->model.chip = "AV100";
+ chip->model.init = xonar_xense_init;
+ chip->model.mixer_init = xonar_xense_mixer_init;
+ break;
default:
return -EINVAL;
}
diff --git a/sound/pci/pcxhr/pcxhr.c b/sound/pci/pcxhr/pcxhr.c
index 68a37a7906c1..b854fc5e01f5 100644
--- a/sound/pci/pcxhr/pcxhr.c
+++ b/sound/pci/pcxhr/pcxhr.c
@@ -702,13 +702,11 @@ static inline int pcxhr_stream_scheduled_get_pipe(struct pcxhr_stream *stream,
return 0;
}
-static void pcxhr_trigger_tasklet(unsigned long arg)
+static void pcxhr_start_linked_stream(struct pcxhr_mgr *mgr)
{
- unsigned long flags;
int i, j, err;
struct pcxhr_pipe *pipe;
struct snd_pcxhr *chip;
- struct pcxhr_mgr *mgr = (struct pcxhr_mgr*)(arg);
int capture_mask = 0;
int playback_mask = 0;
@@ -736,11 +734,11 @@ static void pcxhr_trigger_tasklet(unsigned long arg)
}
if (capture_mask == 0 && playback_mask == 0) {
mutex_unlock(&mgr->setup_mutex);
- dev_err(&mgr->pci->dev, "pcxhr_trigger_tasklet : no pipes\n");
+ dev_err(&mgr->pci->dev, "pcxhr_start_linked_stream : no pipes\n");
return;
}
- dev_dbg(&mgr->pci->dev, "pcxhr_trigger_tasklet : "
+ dev_dbg(&mgr->pci->dev, "pcxhr_start_linked_stream : "
"playback_mask=%x capture_mask=%x\n",
playback_mask, capture_mask);
@@ -748,7 +746,7 @@ static void pcxhr_trigger_tasklet(unsigned long arg)
err = pcxhr_set_pipe_state(mgr, playback_mask, capture_mask, 0);
if (err) {
mutex_unlock(&mgr->setup_mutex);
- dev_err(&mgr->pci->dev, "pcxhr_trigger_tasklet : "
+ dev_err(&mgr->pci->dev, "pcxhr_start_linked_stream : "
"error stop pipes (P%x C%x)\n",
playback_mask, capture_mask);
return;
@@ -793,7 +791,7 @@ static void pcxhr_trigger_tasklet(unsigned long arg)
err = pcxhr_set_pipe_state(mgr, playback_mask, capture_mask, 1);
if (err) {
mutex_unlock(&mgr->setup_mutex);
- dev_err(&mgr->pci->dev, "pcxhr_trigger_tasklet : "
+ dev_err(&mgr->pci->dev, "pcxhr_start_linked_stream : "
"error start pipes (P%x C%x)\n",
playback_mask, capture_mask);
return;
@@ -802,7 +800,7 @@ static void pcxhr_trigger_tasklet(unsigned long arg)
/* put the streams into the running state now
* (increment pointer by interrupt)
*/
- spin_lock_irqsave(&mgr->lock, flags);
+ mutex_lock(&mgr->lock);
for ( i =0; i < mgr->num_cards; i++) {
struct pcxhr_stream *stream;
chip = mgr->chip[i];
@@ -820,13 +818,13 @@ static void pcxhr_trigger_tasklet(unsigned long arg)
}
}
}
- spin_unlock_irqrestore(&mgr->lock, flags);
+ mutex_unlock(&mgr->lock);
mutex_unlock(&mgr->setup_mutex);
#ifdef CONFIG_SND_DEBUG_VERBOSE
do_gettimeofday(&my_tv2);
- dev_dbg(&mgr->pci->dev, "***TRIGGER TASKLET*** TIME = %ld (err = %x)\n",
+ dev_dbg(&mgr->pci->dev, "***TRIGGER START*** TIME = %ld (err = %x)\n",
(long)(my_tv2.tv_usec - my_tv1.tv_usec), err);
#endif
}
@@ -853,7 +851,7 @@ static int pcxhr_trigger(struct snd_pcm_substream *subs, int cmd)
PCXHR_STREAM_STATUS_SCHEDULE_RUN;
snd_pcm_trigger_done(s, subs);
}
- tasklet_schedule(&chip->mgr->trigger_taskq);
+ pcxhr_start_linked_stream(chip->mgr);
} else {
stream = subs->runtime->private_data;
snd_printdd("Only one Substream %c %d\n",
@@ -1127,20 +1125,19 @@ static int pcxhr_close(struct snd_pcm_substream *subs)
static snd_pcm_uframes_t pcxhr_stream_pointer(struct snd_pcm_substream *subs)
{
- unsigned long flags;
u_int32_t timer_period_frag;
int timer_buf_periods;
struct snd_pcxhr *chip = snd_pcm_substream_chip(subs);
struct snd_pcm_runtime *runtime = subs->runtime;
struct pcxhr_stream *stream = runtime->private_data;
- spin_lock_irqsave(&chip->mgr->lock, flags);
+ mutex_lock(&chip->mgr->lock);
/* get the period fragment and the nb of periods in the buffer */
timer_period_frag = stream->timer_period_frag;
timer_buf_periods = stream->timer_buf_periods;
- spin_unlock_irqrestore(&chip->mgr->lock, flags);
+ mutex_unlock(&chip->mgr->lock);
return (snd_pcm_uframes_t)((timer_buf_periods * runtime->period_size) +
timer_period_frag);
@@ -1181,6 +1178,7 @@ int pcxhr_create_pcm(struct snd_pcxhr *chip)
snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &pcxhr_ops);
pcm->info_flags = 0;
+ pcm->nonatomic = true;
strcpy(pcm->name, name);
snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV,
@@ -1588,8 +1586,9 @@ static int pcxhr_probe(struct pci_dev *pci,
mgr->pci = pci;
mgr->irq = -1;
- if (request_irq(pci->irq, pcxhr_interrupt, IRQF_SHARED,
- KBUILD_MODNAME, mgr)) {
+ if (request_threaded_irq(pci->irq, pcxhr_interrupt,
+ pcxhr_threaded_irq, IRQF_SHARED,
+ KBUILD_MODNAME, mgr)) {
dev_err(&pci->dev, "unable to grab IRQ %d\n", pci->irq);
pcxhr_free(mgr);
return -EBUSY;
@@ -1601,19 +1600,13 @@ static int pcxhr_probe(struct pci_dev *pci,
mgr->shortname,
mgr->port[0], mgr->port[1], mgr->port[2], mgr->irq);
- /* ISR spinlock */
- spin_lock_init(&mgr->lock);
- spin_lock_init(&mgr->msg_lock);
+ /* ISR lock */
+ mutex_init(&mgr->lock);
+ mutex_init(&mgr->msg_lock);
/* init setup mutex*/
mutex_init(&mgr->setup_mutex);
- /* init taslket */
- tasklet_init(&mgr->msg_taskq, pcxhr_msg_tasklet,
- (unsigned long) mgr);
- tasklet_init(&mgr->trigger_taskq, pcxhr_trigger_tasklet,
- (unsigned long) mgr);
-
mgr->prmh = kmalloc(sizeof(*mgr->prmh) +
sizeof(u32) * (PCXHR_SIZE_MAX_LONG_STATUS -
PCXHR_SIZE_MAX_STATUS),
diff --git a/sound/pci/pcxhr/pcxhr.h b/sound/pci/pcxhr/pcxhr.h
index a4c602c45173..9e39e509a3ef 100644
--- a/sound/pci/pcxhr/pcxhr.h
+++ b/sound/pci/pcxhr/pcxhr.h
@@ -78,14 +78,10 @@ struct pcxhr_mgr {
char shortname[32]; /* short name of this soundcard */
char longname[96]; /* name of this soundcard */
- /* message tasklet */
- struct tasklet_struct msg_taskq;
struct pcxhr_rmh *prmh;
- /* trigger tasklet */
- struct tasklet_struct trigger_taskq;
- spinlock_t lock; /* interrupt spinlock */
- spinlock_t msg_lock; /* message spinlock */
+ struct mutex lock; /* interrupt lock */
+ struct mutex msg_lock; /* message lock */
struct mutex setup_mutex; /* mutex used in hw_params, open and close */
struct mutex mixer_mutex; /* mutex for mixer */
diff --git a/sound/pci/pcxhr/pcxhr_core.c b/sound/pci/pcxhr/pcxhr_core.c
index df9371918601..a584acb61c00 100644
--- a/sound/pci/pcxhr/pcxhr_core.c
+++ b/sound/pci/pcxhr/pcxhr_core.c
@@ -767,11 +767,11 @@ void pcxhr_set_pipe_cmd_params(struct pcxhr_rmh *rmh, int capture,
*/
int pcxhr_send_msg(struct pcxhr_mgr *mgr, struct pcxhr_rmh *rmh)
{
- unsigned long flags;
int err;
- spin_lock_irqsave(&mgr->msg_lock, flags);
+
+ mutex_lock(&mgr->msg_lock);
err = pcxhr_send_msg_nolock(mgr, rmh);
- spin_unlock_irqrestore(&mgr->msg_lock, flags);
+ mutex_unlock(&mgr->msg_lock);
return err;
}
@@ -971,17 +971,16 @@ int pcxhr_write_io_num_reg_cont(struct pcxhr_mgr *mgr, unsigned int mask,
unsigned int value, int *changed)
{
struct pcxhr_rmh rmh;
- unsigned long flags;
int err;
- spin_lock_irqsave(&mgr->msg_lock, flags);
+ mutex_lock(&mgr->msg_lock);
if ((mgr->io_num_reg_cont & mask) == value) {
dev_dbg(&mgr->pci->dev,
"IO_NUM_REG_CONT mask %x already is set to %x\n",
mask, value);
if (changed)
*changed = 0;
- spin_unlock_irqrestore(&mgr->msg_lock, flags);
+ mutex_unlock(&mgr->msg_lock);
return 0; /* already programmed */
}
pcxhr_init_rmh(&rmh, CMD_ACCESS_IO_WRITE);
@@ -996,7 +995,7 @@ int pcxhr_write_io_num_reg_cont(struct pcxhr_mgr *mgr, unsigned int mask,
if (changed)
*changed = 1;
}
- spin_unlock_irqrestore(&mgr->msg_lock, flags);
+ mutex_unlock(&mgr->msg_lock);
return err;
}
@@ -1043,22 +1042,21 @@ static int pcxhr_handle_async_err(struct pcxhr_mgr *mgr, u32 err,
}
-void pcxhr_msg_tasklet(unsigned long arg)
+static void pcxhr_msg_thread(struct pcxhr_mgr *mgr)
{
- struct pcxhr_mgr *mgr = (struct pcxhr_mgr *)(arg);
struct pcxhr_rmh *prmh = mgr->prmh;
int err;
int i, j;
if (mgr->src_it_dsp & PCXHR_IRQ_FREQ_CHANGE)
dev_dbg(&mgr->pci->dev,
- "TASKLET : PCXHR_IRQ_FREQ_CHANGE event occurred\n");
+ "PCXHR_IRQ_FREQ_CHANGE event occurred\n");
if (mgr->src_it_dsp & PCXHR_IRQ_TIME_CODE)
dev_dbg(&mgr->pci->dev,
- "TASKLET : PCXHR_IRQ_TIME_CODE event occurred\n");
+ "PCXHR_IRQ_TIME_CODE event occurred\n");
if (mgr->src_it_dsp & PCXHR_IRQ_NOTIFY)
dev_dbg(&mgr->pci->dev,
- "TASKLET : PCXHR_IRQ_NOTIFY event occurred\n");
+ "PCXHR_IRQ_NOTIFY event occurred\n");
if (mgr->src_it_dsp & (PCXHR_IRQ_FREQ_CHANGE | PCXHR_IRQ_TIME_CODE)) {
/* clear events FREQ_CHANGE and TIME_CODE */
pcxhr_init_rmh(prmh, CMD_TEST_IT);
@@ -1068,7 +1066,7 @@ void pcxhr_msg_tasklet(unsigned long arg)
}
if (mgr->src_it_dsp & PCXHR_IRQ_ASYNC) {
dev_dbg(&mgr->pci->dev,
- "TASKLET : PCXHR_IRQ_ASYNC event occurred\n");
+ "PCXHR_IRQ_ASYNC event occurred\n");
pcxhr_init_rmh(prmh, CMD_ASYNC);
prmh->cmd[0] |= 1; /* add SEL_ASYNC_EVENTS */
@@ -1076,7 +1074,7 @@ void pcxhr_msg_tasklet(unsigned long arg)
prmh->stat_len = PCXHR_SIZE_MAX_LONG_STATUS;
err = pcxhr_send_msg(mgr, prmh);
if (err)
- dev_err(&mgr->pci->dev, "ERROR pcxhr_msg_tasklet=%x;\n",
+ dev_err(&mgr->pci->dev, "ERROR pcxhr_msg_thread=%x;\n",
err);
i = 1;
while (i < prmh->stat_len) {
@@ -1220,9 +1218,9 @@ static void pcxhr_update_timer_pos(struct pcxhr_mgr *mgr,
}
if (elapsed) {
- spin_unlock(&mgr->lock);
+ mutex_unlock(&mgr->lock);
snd_pcm_period_elapsed(stream->substream);
- spin_lock(&mgr->lock);
+ mutex_lock(&mgr->lock);
}
}
}
@@ -1231,14 +1229,10 @@ irqreturn_t pcxhr_interrupt(int irq, void *dev_id)
{
struct pcxhr_mgr *mgr = dev_id;
unsigned int reg;
- int i, j;
- struct snd_pcxhr *chip;
-
- spin_lock(&mgr->lock);
+ bool wake_thread = false;
reg = PCXHR_INPL(mgr, PCXHR_PLX_IRQCS);
if (! (reg & PCXHR_IRQCS_ACTIVE_PCIDB)) {
- spin_unlock(&mgr->lock);
/* this device did not cause the interrupt */
return IRQ_NONE;
}
@@ -1250,6 +1244,44 @@ irqreturn_t pcxhr_interrupt(int irq, void *dev_id)
/* timer irq occurred */
if (reg & PCXHR_IRQ_TIMER) {
int timer_toggle = reg & PCXHR_IRQ_TIMER;
+ if (timer_toggle == mgr->timer_toggle) {
+ dev_dbg(&mgr->pci->dev, "ERROR TIMER TOGGLE\n");
+ mgr->dsp_time_err++;
+ }
+
+ mgr->timer_toggle = timer_toggle;
+ mgr->src_it_dsp = reg;
+ wake_thread = true;
+ }
+
+ /* other irq's handled in the thread */
+ if (reg & PCXHR_IRQ_MASK) {
+ if (reg & PCXHR_IRQ_ASYNC) {
+ /* as we didn't request any async notifications,
+ * some kind of xrun error will probably occurred
+ */
+ /* better resynchronize all streams next interrupt : */
+ mgr->dsp_time_last = PCXHR_DSP_TIME_INVALID;
+ }
+ mgr->src_it_dsp = reg;
+ wake_thread = true;
+ }
+#ifdef CONFIG_SND_DEBUG_VERBOSE
+ if (reg & PCXHR_FATAL_DSP_ERR)
+ dev_dbg(&mgr->pci->dev, "FATAL DSP ERROR : %x\n", reg);
+#endif
+
+ return wake_thread ? IRQ_WAKE_THREAD : IRQ_HANDLED;
+}
+
+irqreturn_t pcxhr_threaded_irq(int irq, void *dev_id)
+{
+ struct pcxhr_mgr *mgr = dev_id;
+ int i, j;
+ struct snd_pcxhr *chip;
+
+ mutex_lock(&mgr->lock);
+ if (mgr->src_it_dsp & PCXHR_IRQ_TIMER) {
/* is a 24 bit counter */
int dsp_time_new =
PCXHR_INPL(mgr, PCXHR_PLX_MBOX4) & PCXHR_DSP_TIME_MASK;
@@ -1290,13 +1322,6 @@ irqreturn_t pcxhr_interrupt(int irq, void *dev_id)
#endif
mgr->dsp_time_last = dsp_time_new;
- if (timer_toggle == mgr->timer_toggle) {
- dev_dbg(&mgr->pci->dev, "ERROR TIMER TOGGLE\n");
- mgr->dsp_time_err++;
- }
- mgr->timer_toggle = timer_toggle;
-
- reg &= ~PCXHR_IRQ_TIMER;
for (i = 0; i < mgr->num_cards; i++) {
chip = mgr->chip[i];
for (j = 0; j < chip->nb_streams_capt; j++)
@@ -1312,22 +1337,7 @@ irqreturn_t pcxhr_interrupt(int irq, void *dev_id)
dsp_time_diff);
}
}
- /* other irq's handled in the tasklet */
- if (reg & PCXHR_IRQ_MASK) {
- if (reg & PCXHR_IRQ_ASYNC) {
- /* as we didn't request any async notifications,
- * some kind of xrun error will probably occurred
- */
- /* better resynchronize all streams next interrupt : */
- mgr->dsp_time_last = PCXHR_DSP_TIME_INVALID;
- }
- mgr->src_it_dsp = reg;
- tasklet_schedule(&mgr->msg_taskq);
- }
-#ifdef CONFIG_SND_DEBUG_VERBOSE
- if (reg & PCXHR_FATAL_DSP_ERR)
- dev_dbg(&mgr->pci->dev, "FATAL DSP ERROR : %x\n", reg);
-#endif
- spin_unlock(&mgr->lock);
- return IRQ_HANDLED; /* this device caused the interrupt */
+
+ pcxhr_msg_thread(mgr);
+ return IRQ_HANDLED;
}
diff --git a/sound/pci/pcxhr/pcxhr_core.h b/sound/pci/pcxhr/pcxhr_core.h
index a81ab6b811e7..dc267e4c1074 100644
--- a/sound/pci/pcxhr/pcxhr_core.h
+++ b/sound/pci/pcxhr/pcxhr_core.h
@@ -200,6 +200,6 @@ int pcxhr_write_io_num_reg_cont(struct pcxhr_mgr *mgr, unsigned int mask,
/* interrupt handling */
irqreturn_t pcxhr_interrupt(int irq, void *dev_id);
-void pcxhr_msg_tasklet(unsigned long arg);
+irqreturn_t pcxhr_threaded_irq(int irq, void *dev_id);
#endif /* __SOUND_PCXHR_CORE_H */
diff --git a/sound/pci/vx222/vx222.c b/sound/pci/vx222/vx222.c
index 3dc4732142ee..c5a25e39e3a8 100644
--- a/sound/pci/vx222/vx222.c
+++ b/sound/pci/vx222/vx222.c
@@ -168,8 +168,9 @@ static int snd_vx222_create(struct snd_card *card, struct pci_dev *pci,
for (i = 0; i < 2; i++)
vx->port[i] = pci_resource_start(pci, i + 1);
- if (request_irq(pci->irq, snd_vx_irq_handler, IRQF_SHARED,
- KBUILD_MODNAME, chip)) {
+ if (request_threaded_irq(pci->irq, snd_vx_irq_handler,
+ snd_vx_threaded_irq_handler, IRQF_SHARED,
+ KBUILD_MODNAME, chip)) {
dev_err(card->dev, "unable to grab IRQ %d\n", pci->irq);
snd_vx222_free(chip);
return -EBUSY;
diff --git a/sound/pcmcia/pdaudiocf/pdaudiocf.c b/sound/pcmcia/pdaudiocf/pdaudiocf.c
index 56bda124cd4a..07f4b33db3af 100644
--- a/sound/pcmcia/pdaudiocf/pdaudiocf.c
+++ b/sound/pcmcia/pdaudiocf/pdaudiocf.c
@@ -61,6 +61,7 @@ static void snd_pdacf_detach(struct pcmcia_device *p_dev);
static void pdacf_release(struct pcmcia_device *link)
{
+ free_irq(link->irq, link->priv);
pcmcia_disable_device(link);
}
@@ -220,11 +221,13 @@ static int pdacf_config(struct pcmcia_device *link)
ret = pcmcia_request_io(link);
if (ret)
- goto failed;
+ goto failed_preirq;
- ret = pcmcia_request_irq(link, pdacf_interrupt);
+ ret = request_threaded_irq(link->irq, pdacf_interrupt,
+ pdacf_threaded_irq,
+ IRQF_SHARED, link->devname, link->priv);
if (ret)
- goto failed;
+ goto failed_preirq;
ret = pcmcia_enable_device(link);
if (ret)
@@ -236,7 +239,9 @@ static int pdacf_config(struct pcmcia_device *link)
return 0;
-failed:
+ failed:
+ free_irq(link->irq, link->priv);
+failed_preirq:
pcmcia_disable_device(link);
return -ENODEV;
}
diff --git a/sound/pcmcia/pdaudiocf/pdaudiocf.h b/sound/pcmcia/pdaudiocf/pdaudiocf.h
index ea41e57d7179..e9a7d3a784f7 100644
--- a/sound/pcmcia/pdaudiocf/pdaudiocf.h
+++ b/sound/pcmcia/pdaudiocf/pdaudiocf.h
@@ -88,10 +88,9 @@ struct snd_pdacf {
unsigned long port;
int irq;
- spinlock_t reg_lock;
+ struct mutex reg_lock;
unsigned short regmap[8];
unsigned short suspend_reg_scr;
- struct tasklet_struct tq;
spinlock_t ak4117_lock;
struct ak4117 *ak4117;
@@ -136,7 +135,7 @@ int snd_pdacf_resume(struct snd_pdacf *chip);
#endif
int snd_pdacf_pcm_new(struct snd_pdacf *chip);
irqreturn_t pdacf_interrupt(int irq, void *dev);
-void pdacf_tasklet(unsigned long private_data);
+irqreturn_t pdacf_threaded_irq(int irq, void *dev);
void pdacf_reinit(struct snd_pdacf *chip, int resume);
#endif /* __PDAUDIOCF_H */
diff --git a/sound/pcmcia/pdaudiocf/pdaudiocf_core.c b/sound/pcmcia/pdaudiocf/pdaudiocf_core.c
index ea0adfb984ad..d724ab0653cf 100644
--- a/sound/pcmcia/pdaudiocf/pdaudiocf_core.c
+++ b/sound/pcmcia/pdaudiocf/pdaudiocf_core.c
@@ -162,9 +162,8 @@ struct snd_pdacf *snd_pdacf_create(struct snd_card *card)
if (chip == NULL)
return NULL;
chip->card = card;
- spin_lock_init(&chip->reg_lock);
+ mutex_init(&chip->reg_lock);
spin_lock_init(&chip->ak4117_lock);
- tasklet_init(&chip->tq, pdacf_tasklet, (unsigned long)chip);
card->private_data = chip;
pdacf_proc_init(chip);
@@ -174,19 +173,18 @@ struct snd_pdacf *snd_pdacf_create(struct snd_card *card)
static void snd_pdacf_ak4117_change(struct ak4117 *ak4117, unsigned char c0, unsigned char c1)
{
struct snd_pdacf *chip = ak4117->change_callback_private;
- unsigned long flags;
u16 val;
if (!(c0 & AK4117_UNLCK))
return;
- spin_lock_irqsave(&chip->reg_lock, flags);
+ mutex_lock(&chip->reg_lock);
val = chip->regmap[PDAUDIOCF_REG_SCR>>1];
if (ak4117->rcs0 & AK4117_UNLCK)
val |= PDAUDIOCF_BLUE_LED_OFF;
else
val &= ~PDAUDIOCF_BLUE_LED_OFF;
pdacf_reg_write(chip, PDAUDIOCF_REG_SCR, val);
- spin_unlock_irqrestore(&chip->reg_lock, flags);
+ mutex_unlock(&chip->reg_lock);
}
int snd_pdacf_ak4117_create(struct snd_pdacf *chip)
diff --git a/sound/pcmcia/pdaudiocf/pdaudiocf_irq.c b/sound/pcmcia/pdaudiocf/pdaudiocf_irq.c
index dcd32201bc8c..ecf0fbd91794 100644
--- a/sound/pcmcia/pdaudiocf/pdaudiocf_irq.c
+++ b/sound/pcmcia/pdaudiocf/pdaudiocf_irq.c
@@ -30,6 +30,7 @@ irqreturn_t pdacf_interrupt(int irq, void *dev)
{
struct snd_pdacf *chip = dev;
unsigned short stat;
+ bool wake_thread = false;
if ((chip->chip_status & (PDAUDIOCF_STAT_IS_STALE|
PDAUDIOCF_STAT_IS_CONFIGURED|
@@ -41,13 +42,13 @@ irqreturn_t pdacf_interrupt(int irq, void *dev)
if (stat & PDAUDIOCF_IRQOVR) /* should never happen */
snd_printk(KERN_ERR "PDAUDIOCF SRAM buffer overrun detected!\n");
if (chip->pcm_substream)
- tasklet_schedule(&chip->tq);
+ wake_thread = true;
if (!(stat & PDAUDIOCF_IRQAKM))
stat |= PDAUDIOCF_IRQAKM; /* check rate */
}
if (get_irq_regs() != NULL)
snd_ak4117_check_rate_and_errors(chip->ak4117, 0);
- return IRQ_HANDLED;
+ return wake_thread ? IRQ_WAKE_THREAD : IRQ_HANDLED;
}
static inline void pdacf_transfer_mono16(u16 *dst, u16 xor, unsigned int size, unsigned long rdp_port)
@@ -256,16 +257,16 @@ static void pdacf_transfer(struct snd_pdacf *chip, unsigned int size, unsigned i
}
}
-void pdacf_tasklet(unsigned long private_data)
+irqreturn_t pdacf_threaded_irq(int irq, void *dev)
{
- struct snd_pdacf *chip = (struct snd_pdacf *) private_data;
+ struct snd_pdacf *chip = dev;
int size, off, cont, rdp, wdp;
if ((chip->chip_status & (PDAUDIOCF_STAT_IS_STALE|PDAUDIOCF_STAT_IS_CONFIGURED)) != PDAUDIOCF_STAT_IS_CONFIGURED)
- return;
+ return IRQ_HANDLED;
if (chip->pcm_substream == NULL || chip->pcm_substream->runtime == NULL || !snd_pcm_running(chip->pcm_substream))
- return;
+ return IRQ_HANDLED;
rdp = inw(chip->port + PDAUDIOCF_REG_RDP);
wdp = inw(chip->port + PDAUDIOCF_REG_WDP);
@@ -311,15 +312,15 @@ void pdacf_tasklet(unsigned long private_data)
size -= cont;
}
#endif
- spin_lock(&chip->reg_lock);
+ mutex_lock(&chip->reg_lock);
while (chip->pcm_tdone >= chip->pcm_period) {
chip->pcm_hwptr += chip->pcm_period;
chip->pcm_hwptr %= chip->pcm_size;
chip->pcm_tdone -= chip->pcm_period;
- spin_unlock(&chip->reg_lock);
+ mutex_unlock(&chip->reg_lock);
snd_pcm_period_elapsed(chip->pcm_substream);
- spin_lock(&chip->reg_lock);
+ mutex_lock(&chip->reg_lock);
}
- spin_unlock(&chip->reg_lock);
- /* printk(KERN_DEBUG "TASKLET: end\n"); */
+ mutex_unlock(&chip->reg_lock);
+ return IRQ_HANDLED;
}
diff --git a/sound/pcmcia/pdaudiocf/pdaudiocf_pcm.c b/sound/pcmcia/pdaudiocf/pdaudiocf_pcm.c
index 43f995a3f960..b48aa0a78c19 100644
--- a/sound/pcmcia/pdaudiocf/pdaudiocf_pcm.c
+++ b/sound/pcmcia/pdaudiocf/pdaudiocf_pcm.c
@@ -77,7 +77,7 @@ static int pdacf_pcm_trigger(struct snd_pcm_substream *subs, int cmd)
default:
return -EINVAL;
}
- spin_lock(&chip->reg_lock);
+ mutex_lock(&chip->reg_lock);
chip->pcm_running += inc;
tmp = pdacf_reg_read(chip, PDAUDIOCF_REG_SCR);
if (chip->pcm_running) {
@@ -91,7 +91,7 @@ static int pdacf_pcm_trigger(struct snd_pcm_substream *subs, int cmd)
tmp |= val;
pdacf_reg_write(chip, PDAUDIOCF_REG_SCR, tmp);
__end:
- spin_unlock(&chip->reg_lock);
+ mutex_unlock(&chip->reg_lock);
snd_ak4117_check_rate_and_errors(chip->ak4117, AK4117_CHECK_NO_RATE);
return ret;
}
@@ -296,6 +296,7 @@ int snd_pdacf_pcm_new(struct snd_pdacf *chip)
pcm->private_data = chip;
pcm->info_flags = 0;
+ pcm->nonatomic = true;
strcpy(pcm->name, chip->card->shortname);
chip->pcm = pcm;
diff --git a/sound/pcmcia/vx/vxp_ops.c b/sound/pcmcia/vx/vxp_ops.c
index fe33e122e372..281972913c32 100644
--- a/sound/pcmcia/vx/vxp_ops.c
+++ b/sound/pcmcia/vx/vxp_ops.c
@@ -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)
{
struct snd_vxpocket *pchip = (struct snd_vxpocket *)chip;
- unsigned long flags;
if (chip->chip_status & VX_STAT_IS_STALE)
return;
- spin_lock_irqsave(&chip->lock, flags);
+ mutex_lock(&chip->lock);
if (pchip->regCDSP & P24_CDSP_MICS_SEL_MASK) {
if (boost) {
/* boost: 38 dB */
@@ -486,7 +485,7 @@ void vx_set_mic_boost(struct vx_core *chip, int boost)
}
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)
{
struct snd_vxpocket *pchip = (struct snd_vxpocket *)chip;
- unsigned long flags;
if (chip->chip_status & VX_STAT_IS_STALE)
return;
- spin_lock_irqsave(&chip->lock, flags);
+ mutex_lock(&chip->lock);
if (pchip->regCDSP & VXP_CDSP_MIC_SEL_MASK) {
level = vx_compute_mic_level(level);
vx_outb(chip, MICRO, level);
}
- spin_unlock_irqrestore(&chip->lock, flags);
+ mutex_unlock(&chip->lock);
}
diff --git a/sound/pcmcia/vx/vxpocket.c b/sound/pcmcia/vx/vxpocket.c
index 786e7e139c9e..92ec11456e3a 100644
--- a/sound/pcmcia/vx/vxpocket.c
+++ b/sound/pcmcia/vx/vxpocket.c
@@ -62,6 +62,7 @@ static unsigned int card_alloc;
*/
static void vxpocket_release(struct pcmcia_device *link)
{
+ free_irq(link->irq, link->priv);
pcmcia_disable_device(link);
}
@@ -227,11 +228,13 @@ static int vxpocket_config(struct pcmcia_device *link)
ret = pcmcia_request_io(link);
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)
- goto failed;
+ goto failed_preirq;
ret = pcmcia_enable_device(link);
if (ret)
@@ -245,7 +248,9 @@ static int vxpocket_config(struct pcmcia_device *link)
return 0;
-failed:
+ failed:
+ free_irq(link->irq, link->priv);
+failed_preirq:
pcmcia_disable_device(link);
return -ENODEV;
}