.. | .. |
---|
23 | 23 | #define DMIX_WANTS_S16 1 |
---|
24 | 24 | |
---|
25 | 25 | /* |
---|
26 | | - * Call snd_pcm_period_elapsed in a tasklet |
---|
| 26 | + * Call snd_pcm_period_elapsed in a work |
---|
27 | 27 | * This avoids spinlock messes and long-running irq contexts |
---|
28 | 28 | */ |
---|
29 | | -static void pcsp_call_pcm_elapsed(unsigned long priv) |
---|
| 29 | +static void pcsp_call_pcm_elapsed(struct work_struct *work) |
---|
30 | 30 | { |
---|
31 | 31 | if (atomic_read(&pcsp_chip.timer_active)) { |
---|
32 | 32 | struct snd_pcm_substream *substream; |
---|
.. | .. |
---|
36 | 36 | } |
---|
37 | 37 | } |
---|
38 | 38 | |
---|
39 | | -static DECLARE_TASKLET(pcsp_pcm_tasklet, pcsp_call_pcm_elapsed, 0); |
---|
| 39 | +static DECLARE_WORK(pcsp_pcm_work, pcsp_call_pcm_elapsed); |
---|
40 | 40 | |
---|
41 | 41 | /* write the port and returns the next expire time in ns; |
---|
42 | 42 | * called at the trigger-start and in hrtimer callback |
---|
.. | .. |
---|
119 | 119 | if (periods_elapsed) { |
---|
120 | 120 | chip->period_ptr += periods_elapsed * period_bytes; |
---|
121 | 121 | chip->period_ptr %= buffer_bytes; |
---|
| 122 | + queue_work(system_highpri_wq, &pcsp_pcm_work); |
---|
122 | 123 | } |
---|
123 | 124 | spin_unlock_irqrestore(&chip->substream_lock, flags); |
---|
124 | | - |
---|
125 | | - if (periods_elapsed) |
---|
126 | | - tasklet_schedule(&pcsp_pcm_tasklet); |
---|
127 | 125 | } |
---|
128 | 126 | |
---|
129 | 127 | enum hrtimer_restart pcsp_do_timer(struct hrtimer *handle) |
---|
.. | .. |
---|
196 | 194 | pcsp_stop_playing(chip); |
---|
197 | 195 | local_irq_enable(); |
---|
198 | 196 | hrtimer_cancel(&chip->timer); |
---|
199 | | - tasklet_kill(&pcsp_pcm_tasklet); |
---|
| 197 | + cancel_work_sync(&pcsp_pcm_work); |
---|
200 | 198 | } |
---|
201 | 199 | |
---|
202 | 200 | static int snd_pcsp_playback_close(struct snd_pcm_substream *substream) |
---|
.. | .. |
---|
214 | 212 | struct snd_pcm_hw_params *hw_params) |
---|
215 | 213 | { |
---|
216 | 214 | struct snd_pcsp *chip = snd_pcm_substream_chip(substream); |
---|
217 | | - int err; |
---|
218 | 215 | pcsp_sync_stop(chip); |
---|
219 | | - err = snd_pcm_lib_malloc_pages(substream, |
---|
220 | | - params_buffer_bytes(hw_params)); |
---|
221 | | - if (err < 0) |
---|
222 | | - return err; |
---|
223 | 216 | return 0; |
---|
224 | 217 | } |
---|
225 | 218 | |
---|
.. | .. |
---|
230 | 223 | printk(KERN_INFO "PCSP: hw_free called\n"); |
---|
231 | 224 | #endif |
---|
232 | 225 | pcsp_sync_stop(chip); |
---|
233 | | - return snd_pcm_lib_free_pages(substream); |
---|
| 226 | + return 0; |
---|
234 | 227 | } |
---|
235 | 228 | |
---|
236 | 229 | static int snd_pcsp_playback_prepare(struct snd_pcm_substream *substream) |
---|
.. | .. |
---|
327 | 320 | static const struct snd_pcm_ops snd_pcsp_playback_ops = { |
---|
328 | 321 | .open = snd_pcsp_playback_open, |
---|
329 | 322 | .close = snd_pcsp_playback_close, |
---|
330 | | - .ioctl = snd_pcm_lib_ioctl, |
---|
331 | 323 | .hw_params = snd_pcsp_playback_hw_params, |
---|
332 | 324 | .hw_free = snd_pcsp_playback_hw_free, |
---|
333 | 325 | .prepare = snd_pcsp_playback_prepare, |
---|
.. | .. |
---|
350 | 342 | chip->pcm->info_flags = SNDRV_PCM_INFO_HALF_DUPLEX; |
---|
351 | 343 | strcpy(chip->pcm->name, "pcsp"); |
---|
352 | 344 | |
---|
353 | | - snd_pcm_lib_preallocate_pages_for_all(chip->pcm, |
---|
354 | | - SNDRV_DMA_TYPE_CONTINUOUS, |
---|
355 | | - snd_dma_continuous_data |
---|
356 | | - (GFP_KERNEL), PCSP_BUFFER_SIZE, |
---|
357 | | - PCSP_BUFFER_SIZE); |
---|
| 345 | + snd_pcm_set_managed_buffer_all(chip->pcm, |
---|
| 346 | + SNDRV_DMA_TYPE_CONTINUOUS, |
---|
| 347 | + NULL, |
---|
| 348 | + PCSP_BUFFER_SIZE, |
---|
| 349 | + PCSP_BUFFER_SIZE); |
---|
358 | 350 | |
---|
359 | 351 | return 0; |
---|
360 | 352 | } |
---|