aboutsummaryrefslogtreecommitdiffstats
path: root/sound/drivers
diff options
context:
space:
mode:
Diffstat (limited to 'sound/drivers')
-rw-r--r--sound/drivers/Kconfig2
-rw-r--r--sound/drivers/dummy.c2
-rw-r--r--sound/drivers/ml403-ac97cr.c4
-rw-r--r--sound/drivers/pcsp/pcsp.c8
-rw-r--r--sound/drivers/pcsp/pcsp.h3
-rw-r--r--sound/drivers/pcsp/pcsp_input.c4
-rw-r--r--sound/drivers/pcsp/pcsp_lib.c167
-rw-r--r--sound/drivers/vx/vx_core.c2
-rw-r--r--sound/drivers/vx/vx_pcm.c2
9 files changed, 115 insertions, 79 deletions
diff --git a/sound/drivers/Kconfig b/sound/drivers/Kconfig
index 255fd18b9aec..0bcf14640fde 100644
--- a/sound/drivers/Kconfig
+++ b/sound/drivers/Kconfig
@@ -163,7 +163,7 @@ config SND_ML403_AC97CR
163 163
164config SND_AC97_POWER_SAVE 164config SND_AC97_POWER_SAVE
165 bool "AC97 Power-Saving Mode" 165 bool "AC97 Power-Saving Mode"
166 depends on SND_AC97_CODEC && EXPERIMENTAL 166 depends on SND_AC97_CODEC
167 default n 167 default n
168 help 168 help
169 Say Y here to enable the aggressive power-saving support of 169 Say Y here to enable the aggressive power-saving support of
diff --git a/sound/drivers/dummy.c b/sound/drivers/dummy.c
index e5e749f3e0ef..73be7e14a603 100644
--- a/sound/drivers/dummy.c
+++ b/sound/drivers/dummy.c
@@ -51,7 +51,7 @@ static int emu10k1_playback_constraints(struct snd_pcm_runtime *runtime)
51 if (err < 0) 51 if (err < 0)
52 return err; 52 return err;
53 err = snd_pcm_hw_constraint_minmax(runtime, SNDRV_PCM_HW_PARAM_BUFFER_BYTES, 256, UINT_MAX); 53 err = snd_pcm_hw_constraint_minmax(runtime, SNDRV_PCM_HW_PARAM_BUFFER_BYTES, 256, UINT_MAX);
54 if (err) < 0) 54 if (err < 0)
55 return err; 55 return err;
56 return 0; 56 return 0;
57} 57}
diff --git a/sound/drivers/ml403-ac97cr.c b/sound/drivers/ml403-ac97cr.c
index ecdbeb6d3603..7783843ca9ae 100644
--- a/sound/drivers/ml403-ac97cr.c
+++ b/sound/drivers/ml403-ac97cr.c
@@ -1153,7 +1153,7 @@ snd_ml403_ac97cr_create(struct snd_card *card, struct platform_device *pfdev,
1153 /* get irq */ 1153 /* get irq */
1154 irq = platform_get_irq(pfdev, 0); 1154 irq = platform_get_irq(pfdev, 0);
1155 if (request_irq(irq, snd_ml403_ac97cr_irq, IRQF_DISABLED, 1155 if (request_irq(irq, snd_ml403_ac97cr_irq, IRQF_DISABLED,
1156 pfdev->dev.bus_id, (void *)ml403_ac97cr)) { 1156 dev_name(&pfdev->dev), (void *)ml403_ac97cr)) {
1157 snd_printk(KERN_ERR SND_ML403_AC97CR_DRIVER ": " 1157 snd_printk(KERN_ERR SND_ML403_AC97CR_DRIVER ": "
1158 "unable to grab IRQ %d\n", 1158 "unable to grab IRQ %d\n",
1159 irq); 1159 irq);
@@ -1166,7 +1166,7 @@ snd_ml403_ac97cr_create(struct snd_card *card, struct platform_device *pfdev,
1166 ml403_ac97cr->irq); 1166 ml403_ac97cr->irq);
1167 irq = platform_get_irq(pfdev, 1); 1167 irq = platform_get_irq(pfdev, 1);
1168 if (request_irq(irq, snd_ml403_ac97cr_irq, IRQF_DISABLED, 1168 if (request_irq(irq, snd_ml403_ac97cr_irq, IRQF_DISABLED,
1169 pfdev->dev.bus_id, (void *)ml403_ac97cr)) { 1169 dev_name(&pfdev->dev), (void *)ml403_ac97cr)) {
1170 snd_printk(KERN_ERR SND_ML403_AC97CR_DRIVER ": " 1170 snd_printk(KERN_ERR SND_ML403_AC97CR_DRIVER ": "
1171 "unable to grab IRQ %d\n", 1171 "unable to grab IRQ %d\n",
1172 irq); 1172 irq);
diff --git a/sound/drivers/pcsp/pcsp.c b/sound/drivers/pcsp/pcsp.c
index 1899cf0685bc..2a02f704f366 100644
--- a/sound/drivers/pcsp/pcsp.c
+++ b/sound/drivers/pcsp/pcsp.c
@@ -96,7 +96,7 @@ static int __devinit snd_card_pcsp_probe(int devnum, struct device *dev)
96 return -EINVAL; 96 return -EINVAL;
97 97
98 hrtimer_init(&pcsp_chip.timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL); 98 hrtimer_init(&pcsp_chip.timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
99 pcsp_chip.timer.cb_mode = HRTIMER_CB_SOFTIRQ; 99 pcsp_chip.timer.cb_mode = HRTIMER_CB_IRQSAFE_UNLOCKED;
100 pcsp_chip.timer.function = pcsp_do_timer; 100 pcsp_chip.timer.function = pcsp_do_timer;
101 101
102 card = snd_card_new(index, id, THIS_MODULE, 0); 102 card = snd_card_new(index, id, THIS_MODULE, 0);
@@ -188,10 +188,8 @@ static int __devexit pcsp_remove(struct platform_device *dev)
188 188
189static void pcsp_stop_beep(struct snd_pcsp *chip) 189static void pcsp_stop_beep(struct snd_pcsp *chip)
190{ 190{
191 spin_lock_irq(&chip->substream_lock); 191 pcsp_sync_stop(chip);
192 if (!chip->playback_substream) 192 pcspkr_stop_sound();
193 pcspkr_stop_sound();
194 spin_unlock_irq(&chip->substream_lock);
195} 193}
196 194
197#ifdef CONFIG_PM 195#ifdef CONFIG_PM
diff --git a/sound/drivers/pcsp/pcsp.h b/sound/drivers/pcsp/pcsp.h
index 1d661f795e8c..cdef2664218f 100644
--- a/sound/drivers/pcsp/pcsp.h
+++ b/sound/drivers/pcsp/pcsp.h
@@ -62,6 +62,8 @@ struct snd_pcsp {
62 unsigned short port, irq, dma; 62 unsigned short port, irq, dma;
63 spinlock_t substream_lock; 63 spinlock_t substream_lock;
64 struct snd_pcm_substream *playback_substream; 64 struct snd_pcm_substream *playback_substream;
65 unsigned int fmt_size;
66 unsigned int is_signed;
65 size_t playback_ptr; 67 size_t playback_ptr;
66 size_t period_ptr; 68 size_t period_ptr;
67 atomic_t timer_active; 69 atomic_t timer_active;
@@ -77,6 +79,7 @@ struct snd_pcsp {
77extern struct snd_pcsp pcsp_chip; 79extern struct snd_pcsp pcsp_chip;
78 80
79extern enum hrtimer_restart pcsp_do_timer(struct hrtimer *handle); 81extern enum hrtimer_restart pcsp_do_timer(struct hrtimer *handle);
82extern void pcsp_sync_stop(struct snd_pcsp *chip);
80 83
81extern int snd_pcsp_new_pcm(struct snd_pcsp *chip); 84extern int snd_pcsp_new_pcm(struct snd_pcsp *chip);
82extern int snd_pcsp_new_mixer(struct snd_pcsp *chip); 85extern int snd_pcsp_new_mixer(struct snd_pcsp *chip);
diff --git a/sound/drivers/pcsp/pcsp_input.c b/sound/drivers/pcsp/pcsp_input.c
index cd9b83e7f7d1..0444cdeb4bec 100644
--- a/sound/drivers/pcsp/pcsp_input.c
+++ b/sound/drivers/pcsp/pcsp_input.c
@@ -24,13 +24,13 @@ static void pcspkr_do_sound(unsigned int count)
24 spin_lock_irqsave(&i8253_lock, flags); 24 spin_lock_irqsave(&i8253_lock, flags);
25 25
26 if (count) { 26 if (count) {
27 /* enable counter 2 */
28 outb_p(inb_p(0x61) | 3, 0x61);
29 /* set command for counter 2, 2 byte write */ 27 /* set command for counter 2, 2 byte write */
30 outb_p(0xB6, 0x43); 28 outb_p(0xB6, 0x43);
31 /* select desired HZ */ 29 /* select desired HZ */
32 outb_p(count & 0xff, 0x42); 30 outb_p(count & 0xff, 0x42);
33 outb((count >> 8) & 0xff, 0x42); 31 outb((count >> 8) & 0xff, 0x42);
32 /* enable counter 2 */
33 outb_p(inb_p(0x61) | 3, 0x61);
34 } else { 34 } else {
35 /* disable counter 2 */ 35 /* disable counter 2 */
36 outb(inb_p(0x61) & 0xFC, 0x61); 36 outb(inb_p(0x61) & 0xFC, 0x61);
diff --git a/sound/drivers/pcsp/pcsp_lib.c b/sound/drivers/pcsp/pcsp_lib.c
index e341f3f83b6a..84cc2658c05b 100644
--- a/sound/drivers/pcsp/pcsp_lib.c
+++ b/sound/drivers/pcsp/pcsp_lib.c
@@ -8,6 +8,7 @@
8 8
9#include <linux/module.h> 9#include <linux/module.h>
10#include <linux/moduleparam.h> 10#include <linux/moduleparam.h>
11#include <linux/interrupt.h>
11#include <sound/pcm.h> 12#include <sound/pcm.h>
12#include <asm/io.h> 13#include <asm/io.h>
13#include "pcsp.h" 14#include "pcsp.h"
@@ -19,61 +20,57 @@ MODULE_PARM_DESC(nforce_wa, "Apply NForce chipset workaround "
19 20
20#define DMIX_WANTS_S16 1 21#define DMIX_WANTS_S16 1
21 22
22enum hrtimer_restart pcsp_do_timer(struct hrtimer *handle) 23/*
24 * Call snd_pcm_period_elapsed in a tasklet
25 * This avoids spinlock messes and long-running irq contexts
26 */
27static void pcsp_call_pcm_elapsed(unsigned long priv)
28{
29 if (atomic_read(&pcsp_chip.timer_active)) {
30 struct snd_pcm_substream *substream;
31 substream = pcsp_chip.playback_substream;
32 if (substream)
33 snd_pcm_period_elapsed(substream);
34 }
35}
36
37static DECLARE_TASKLET(pcsp_pcm_tasklet, pcsp_call_pcm_elapsed, 0);
38
39/* write the port and returns the next expire time in ns;
40 * called at the trigger-start and in hrtimer callback
41 */
42static unsigned long pcsp_timer_update(struct hrtimer *handle)
23{ 43{
24 unsigned char timer_cnt, val; 44 unsigned char timer_cnt, val;
25 int fmt_size, periods_elapsed;
26 u64 ns; 45 u64 ns;
27 size_t period_bytes, buffer_bytes;
28 struct snd_pcm_substream *substream; 46 struct snd_pcm_substream *substream;
29 struct snd_pcm_runtime *runtime; 47 struct snd_pcm_runtime *runtime;
30 struct snd_pcsp *chip = container_of(handle, struct snd_pcsp, timer); 48 struct snd_pcsp *chip = container_of(handle, struct snd_pcsp, timer);
49 unsigned long flags;
31 50
32 if (chip->thalf) { 51 if (chip->thalf) {
33 outb(chip->val61, 0x61); 52 outb(chip->val61, 0x61);
34 chip->thalf = 0; 53 chip->thalf = 0;
35 if (!atomic_read(&chip->timer_active)) 54 if (!atomic_read(&chip->timer_active))
36 return HRTIMER_NORESTART; 55 return 0;
37 hrtimer_forward(&chip->timer, chip->timer.expires, 56 return chip->ns_rem;
38 ktime_set(0, chip->ns_rem));
39 return HRTIMER_RESTART;
40 } 57 }
41 58
42 spin_lock_irq(&chip->substream_lock);
43 /* Takashi Iwai says regarding this extra lock:
44
45 If the irq handler handles some data on the DMA buffer, it should
46 do snd_pcm_stream_lock().
47 That protects basically against all races among PCM callbacks, yes.
48 However, there are two remaining issues:
49 1. The substream pointer you try to lock isn't protected _before_
50 this lock yet.
51 2. snd_pcm_period_elapsed() itself acquires the lock.
52 The requirement of another lock is because of 1. When you get
53 chip->playback_substream, it's not protected.
54 Keeping this lock while snd_pcm_period_elapsed() assures the substream
55 is still protected (at least, not released). And the other status is
56 handled properly inside snd_pcm_stream_lock() in
57 snd_pcm_period_elapsed().
58
59 */
60 if (!chip->playback_substream)
61 goto exit_nr_unlock1;
62 substream = chip->playback_substream;
63 snd_pcm_stream_lock(substream);
64 if (!atomic_read(&chip->timer_active)) 59 if (!atomic_read(&chip->timer_active))
65 goto exit_nr_unlock2; 60 return 0;
61 substream = chip->playback_substream;
62 if (!substream)
63 return 0;
66 64
67 runtime = substream->runtime; 65 runtime = substream->runtime;
68 fmt_size = snd_pcm_format_physical_width(runtime->format) >> 3;
69 /* assume it is mono! */ 66 /* assume it is mono! */
70 val = runtime->dma_area[chip->playback_ptr + fmt_size - 1]; 67 val = runtime->dma_area[chip->playback_ptr + chip->fmt_size - 1];
71 if (snd_pcm_format_signed(runtime->format)) 68 if (chip->is_signed)
72 val ^= 0x80; 69 val ^= 0x80;
73 timer_cnt = val * CUR_DIV() / 256; 70 timer_cnt = val * CUR_DIV() / 256;
74 71
75 if (timer_cnt && chip->enable) { 72 if (timer_cnt && chip->enable) {
76 spin_lock(&i8253_lock); 73 spin_lock_irqsave(&i8253_lock, flags);
77 if (!nforce_wa) { 74 if (!nforce_wa) {
78 outb_p(chip->val61, 0x61); 75 outb_p(chip->val61, 0x61);
79 outb_p(timer_cnt, 0x42); 76 outb_p(timer_cnt, 0x42);
@@ -82,12 +79,39 @@ enum hrtimer_restart pcsp_do_timer(struct hrtimer *handle)
82 outb(chip->val61 ^ 2, 0x61); 79 outb(chip->val61 ^ 2, 0x61);
83 chip->thalf = 1; 80 chip->thalf = 1;
84 } 81 }
85 spin_unlock(&i8253_lock); 82 spin_unlock_irqrestore(&i8253_lock, flags);
86 } 83 }
87 84
85 chip->ns_rem = PCSP_PERIOD_NS();
86 ns = (chip->thalf ? PCSP_CALC_NS(timer_cnt) : chip->ns_rem);
87 chip->ns_rem -= ns;
88 return ns;
89}
90
91enum hrtimer_restart pcsp_do_timer(struct hrtimer *handle)
92{
93 struct snd_pcsp *chip = container_of(handle, struct snd_pcsp, timer);
94 struct snd_pcm_substream *substream;
95 int periods_elapsed, pointer_update;
96 size_t period_bytes, buffer_bytes;
97 unsigned long ns;
98 unsigned long flags;
99
100 pointer_update = !chip->thalf;
101 ns = pcsp_timer_update(handle);
102 if (!ns)
103 return HRTIMER_NORESTART;
104
105 /* update the playback position */
106 substream = chip->playback_substream;
107 if (!substream)
108 return HRTIMER_NORESTART;
109
88 period_bytes = snd_pcm_lib_period_bytes(substream); 110 period_bytes = snd_pcm_lib_period_bytes(substream);
89 buffer_bytes = snd_pcm_lib_buffer_bytes(substream); 111 buffer_bytes = snd_pcm_lib_buffer_bytes(substream);
90 chip->playback_ptr += PCSP_INDEX_INC() * fmt_size; 112
113 spin_lock_irqsave(&chip->substream_lock, flags);
114 chip->playback_ptr += PCSP_INDEX_INC() * chip->fmt_size;
91 periods_elapsed = chip->playback_ptr - chip->period_ptr; 115 periods_elapsed = chip->playback_ptr - chip->period_ptr;
92 if (periods_elapsed < 0) { 116 if (periods_elapsed < 0) {
93#if PCSP_DEBUG 117#if PCSP_DEBUG
@@ -102,40 +126,30 @@ enum hrtimer_restart pcsp_do_timer(struct hrtimer *handle)
102 * or ALSA will BUG on us. */ 126 * or ALSA will BUG on us. */
103 chip->playback_ptr %= buffer_bytes; 127 chip->playback_ptr %= buffer_bytes;
104 128
105 snd_pcm_stream_unlock(substream);
106
107 if (periods_elapsed) { 129 if (periods_elapsed) {
108 snd_pcm_period_elapsed(substream);
109 chip->period_ptr += periods_elapsed * period_bytes; 130 chip->period_ptr += periods_elapsed * period_bytes;
110 chip->period_ptr %= buffer_bytes; 131 chip->period_ptr %= buffer_bytes;
111 } 132 }
133 spin_unlock_irqrestore(&chip->substream_lock, flags);
112 134
113 spin_unlock_irq(&chip->substream_lock); 135 if (periods_elapsed)
136 tasklet_schedule(&pcsp_pcm_tasklet);
114 137
115 if (!atomic_read(&chip->timer_active)) 138 hrtimer_forward(handle, hrtimer_get_expires(handle), ns_to_ktime(ns));
116 return HRTIMER_NORESTART;
117 139
118 chip->ns_rem = PCSP_PERIOD_NS();
119 ns = (chip->thalf ? PCSP_CALC_NS(timer_cnt) : chip->ns_rem);
120 chip->ns_rem -= ns;
121 hrtimer_forward(&chip->timer, chip->timer.expires, ktime_set(0, ns));
122 return HRTIMER_RESTART; 140 return HRTIMER_RESTART;
123
124exit_nr_unlock2:
125 snd_pcm_stream_unlock(substream);
126exit_nr_unlock1:
127 spin_unlock_irq(&chip->substream_lock);
128 return HRTIMER_NORESTART;
129} 141}
130 142
131static void pcsp_start_playing(struct snd_pcsp *chip) 143static int pcsp_start_playing(struct snd_pcsp *chip)
132{ 144{
145 unsigned long ns;
146
133#if PCSP_DEBUG 147#if PCSP_DEBUG
134 printk(KERN_INFO "PCSP: start_playing called\n"); 148 printk(KERN_INFO "PCSP: start_playing called\n");
135#endif 149#endif
136 if (atomic_read(&chip->timer_active)) { 150 if (atomic_read(&chip->timer_active)) {
137 printk(KERN_ERR "PCSP: Timer already active\n"); 151 printk(KERN_ERR "PCSP: Timer already active\n");
138 return; 152 return -EIO;
139 } 153 }
140 154
141 spin_lock(&i8253_lock); 155 spin_lock(&i8253_lock);
@@ -145,7 +159,12 @@ static void pcsp_start_playing(struct snd_pcsp *chip)
145 atomic_set(&chip->timer_active, 1); 159 atomic_set(&chip->timer_active, 1);
146 chip->thalf = 0; 160 chip->thalf = 0;
147 161
148 hrtimer_start(&pcsp_chip.timer, ktime_set(0, 0), HRTIMER_MODE_REL); 162 ns = pcsp_timer_update(&pcsp_chip.timer);
163 if (!ns)
164 return -EIO;
165
166 hrtimer_start(&pcsp_chip.timer, ktime_set(0, ns), HRTIMER_MODE_REL);
167 return 0;
149} 168}
150 169
151static void pcsp_stop_playing(struct snd_pcsp *chip) 170static void pcsp_stop_playing(struct snd_pcsp *chip)
@@ -164,26 +183,35 @@ static void pcsp_stop_playing(struct snd_pcsp *chip)
164 spin_unlock(&i8253_lock); 183 spin_unlock(&i8253_lock);
165} 184}
166 185
186/*
187 * Force to stop and sync the stream
188 */
189void pcsp_sync_stop(struct snd_pcsp *chip)
190{
191 local_irq_disable();
192 pcsp_stop_playing(chip);
193 local_irq_enable();
194 hrtimer_cancel(&chip->timer);
195 tasklet_kill(&pcsp_pcm_tasklet);
196}
197
167static int snd_pcsp_playback_close(struct snd_pcm_substream *substream) 198static int snd_pcsp_playback_close(struct snd_pcm_substream *substream)
168{ 199{
169 struct snd_pcsp *chip = snd_pcm_substream_chip(substream); 200 struct snd_pcsp *chip = snd_pcm_substream_chip(substream);
170#if PCSP_DEBUG 201#if PCSP_DEBUG
171 printk(KERN_INFO "PCSP: close called\n"); 202 printk(KERN_INFO "PCSP: close called\n");
172#endif 203#endif
173 if (atomic_read(&chip->timer_active)) { 204 pcsp_sync_stop(chip);
174 printk(KERN_ERR "PCSP: timer still active\n");
175 pcsp_stop_playing(chip);
176 }
177 spin_lock_irq(&chip->substream_lock);
178 chip->playback_substream = NULL; 205 chip->playback_substream = NULL;
179 spin_unlock_irq(&chip->substream_lock);
180 return 0; 206 return 0;
181} 207}
182 208
183static int snd_pcsp_playback_hw_params(struct snd_pcm_substream *substream, 209static int snd_pcsp_playback_hw_params(struct snd_pcm_substream *substream,
184 struct snd_pcm_hw_params *hw_params) 210 struct snd_pcm_hw_params *hw_params)
185{ 211{
212 struct snd_pcsp *chip = snd_pcm_substream_chip(substream);
186 int err; 213 int err;
214 pcsp_sync_stop(chip);
187 err = snd_pcm_lib_malloc_pages(substream, 215 err = snd_pcm_lib_malloc_pages(substream,
188 params_buffer_bytes(hw_params)); 216 params_buffer_bytes(hw_params));
189 if (err < 0) 217 if (err < 0)
@@ -193,9 +221,11 @@ static int snd_pcsp_playback_hw_params(struct snd_pcm_substream *substream,
193 221
194static int snd_pcsp_playback_hw_free(struct snd_pcm_substream *substream) 222static int snd_pcsp_playback_hw_free(struct snd_pcm_substream *substream)
195{ 223{
224 struct snd_pcsp *chip = snd_pcm_substream_chip(substream);
196#if PCSP_DEBUG 225#if PCSP_DEBUG
197 printk(KERN_INFO "PCSP: hw_free called\n"); 226 printk(KERN_INFO "PCSP: hw_free called\n");
198#endif 227#endif
228 pcsp_sync_stop(chip);
199 return snd_pcm_lib_free_pages(substream); 229 return snd_pcm_lib_free_pages(substream);
200} 230}
201 231
@@ -211,8 +241,12 @@ static int snd_pcsp_playback_prepare(struct snd_pcm_substream *substream)
211 snd_pcm_lib_period_bytes(substream), 241 snd_pcm_lib_period_bytes(substream),
212 substream->runtime->periods); 242 substream->runtime->periods);
213#endif 243#endif
244 pcsp_sync_stop(chip);
214 chip->playback_ptr = 0; 245 chip->playback_ptr = 0;
215 chip->period_ptr = 0; 246 chip->period_ptr = 0;
247 chip->fmt_size =
248 snd_pcm_format_physical_width(substream->runtime->format) >> 3;
249 chip->is_signed = snd_pcm_format_signed(substream->runtime->format);
216 return 0; 250 return 0;
217} 251}
218 252
@@ -225,8 +259,7 @@ static int snd_pcsp_trigger(struct snd_pcm_substream *substream, int cmd)
225 switch (cmd) { 259 switch (cmd) {
226 case SNDRV_PCM_TRIGGER_START: 260 case SNDRV_PCM_TRIGGER_START:
227 case SNDRV_PCM_TRIGGER_RESUME: 261 case SNDRV_PCM_TRIGGER_RESUME:
228 pcsp_start_playing(chip); 262 return pcsp_start_playing(chip);
229 break;
230 case SNDRV_PCM_TRIGGER_STOP: 263 case SNDRV_PCM_TRIGGER_STOP:
231 case SNDRV_PCM_TRIGGER_SUSPEND: 264 case SNDRV_PCM_TRIGGER_SUSPEND:
232 pcsp_stop_playing(chip); 265 pcsp_stop_playing(chip);
@@ -241,7 +274,11 @@ static snd_pcm_uframes_t snd_pcsp_playback_pointer(struct snd_pcm_substream
241 *substream) 274 *substream)
242{ 275{
243 struct snd_pcsp *chip = snd_pcm_substream_chip(substream); 276 struct snd_pcsp *chip = snd_pcm_substream_chip(substream);
244 return bytes_to_frames(substream->runtime, chip->playback_ptr); 277 unsigned int pos;
278 spin_lock(&chip->substream_lock);
279 pos = chip->playback_ptr;
280 spin_unlock(&chip->substream_lock);
281 return bytes_to_frames(substream->runtime, pos);
245} 282}
246 283
247static struct snd_pcm_hardware snd_pcsp_playback = { 284static struct snd_pcm_hardware snd_pcsp_playback = {
@@ -278,9 +315,7 @@ static int snd_pcsp_playback_open(struct snd_pcm_substream *substream)
278 return -EBUSY; 315 return -EBUSY;
279 } 316 }
280 runtime->hw = snd_pcsp_playback; 317 runtime->hw = snd_pcsp_playback;
281 spin_lock_irq(&chip->substream_lock);
282 chip->playback_substream = substream; 318 chip->playback_substream = substream;
283 spin_unlock_irq(&chip->substream_lock);
284 return 0; 319 return 0;
285} 320}
286 321
diff --git a/sound/drivers/vx/vx_core.c b/sound/drivers/vx/vx_core.c
index 473b07f6ae85..14e3354be43a 100644
--- a/sound/drivers/vx/vx_core.c
+++ b/sound/drivers/vx/vx_core.c
@@ -548,7 +548,7 @@ irqreturn_t snd_vx_irq_handler(int irq, void *dev)
548 (chip->chip_status & VX_STAT_IS_STALE)) 548 (chip->chip_status & VX_STAT_IS_STALE))
549 return IRQ_NONE; 549 return IRQ_NONE;
550 if (! vx_test_and_ack(chip)) 550 if (! vx_test_and_ack(chip))
551 tasklet_hi_schedule(&chip->tq); 551 tasklet_schedule(&chip->tq);
552 return IRQ_HANDLED; 552 return IRQ_HANDLED;
553} 553}
554 554
diff --git a/sound/drivers/vx/vx_pcm.c b/sound/drivers/vx/vx_pcm.c
index 27de574c08f7..6644d0034fba 100644
--- a/sound/drivers/vx/vx_pcm.c
+++ b/sound/drivers/vx/vx_pcm.c
@@ -823,7 +823,7 @@ static int vx_pcm_trigger(struct snd_pcm_substream *subs, int cmd)
823 * we trigger the pipe using tasklet, so that the interrupts are 823 * we trigger the pipe using tasklet, so that the interrupts are
824 * issued surely after the trigger is completed. 824 * issued surely after the trigger is completed.
825 */ 825 */
826 tasklet_hi_schedule(&pipe->start_tq); 826 tasklet_schedule(&pipe->start_tq);
827 chip->pcm_running++; 827 chip->pcm_running++;
828 pipe->running = 1; 828 pipe->running = 1;
829 break; 829 break;