| .. | .. |
|---|
| 10 | 10 | #include <linux/interrupt.h> |
|---|
| 11 | 11 | #include <linux/usb.h> |
|---|
| 12 | 12 | #include <linux/slab.h> |
|---|
| 13 | | -#include <linux/vmalloc.h> |
|---|
| 14 | 13 | |
|---|
| 15 | 14 | #include <linux/delay.h> |
|---|
| 16 | 15 | #include <sound/core.h> |
|---|
| .. | .. |
|---|
| 58 | 57 | MODULE_PARM_DESC(debug, "enable debug messages"); |
|---|
| 59 | 58 | |
|---|
| 60 | 59 | /**************************************************************************** |
|---|
| 61 | | - Module specific funtions |
|---|
| 60 | + Module specific functions |
|---|
| 62 | 61 | ****************************************************************************/ |
|---|
| 63 | 62 | |
|---|
| 64 | 63 | /* |
|---|
| .. | .. |
|---|
| 93 | 92 | |
|---|
| 94 | 93 | return 0; |
|---|
| 95 | 94 | } |
|---|
| 96 | | - |
|---|
| 97 | | -static void dsp_buffer_free(struct snd_pcm_substream *substream) |
|---|
| 98 | | -{ |
|---|
| 99 | | - struct snd_tm6000_card *chip = snd_pcm_substream_chip(substream); |
|---|
| 100 | | - |
|---|
| 101 | | - dprintk(2, "Freeing buffer\n"); |
|---|
| 102 | | - |
|---|
| 103 | | - vfree(substream->runtime->dma_area); |
|---|
| 104 | | - substream->runtime->dma_area = NULL; |
|---|
| 105 | | - substream->runtime->dma_bytes = 0; |
|---|
| 106 | | -} |
|---|
| 107 | | - |
|---|
| 108 | | -static int dsp_buffer_alloc(struct snd_pcm_substream *substream, int size) |
|---|
| 109 | | -{ |
|---|
| 110 | | - struct snd_tm6000_card *chip = snd_pcm_substream_chip(substream); |
|---|
| 111 | | - |
|---|
| 112 | | - dprintk(2, "Allocating buffer\n"); |
|---|
| 113 | | - |
|---|
| 114 | | - if (substream->runtime->dma_area) { |
|---|
| 115 | | - if (substream->runtime->dma_bytes > size) |
|---|
| 116 | | - return 0; |
|---|
| 117 | | - |
|---|
| 118 | | - dsp_buffer_free(substream); |
|---|
| 119 | | - } |
|---|
| 120 | | - |
|---|
| 121 | | - substream->runtime->dma_area = vmalloc(size); |
|---|
| 122 | | - if (!substream->runtime->dma_area) |
|---|
| 123 | | - return -ENOMEM; |
|---|
| 124 | | - |
|---|
| 125 | | - substream->runtime->dma_bytes = size; |
|---|
| 126 | | - |
|---|
| 127 | | - return 0; |
|---|
| 128 | | -} |
|---|
| 129 | | - |
|---|
| 130 | 95 | |
|---|
| 131 | 96 | /**************************************************************************** |
|---|
| 132 | 97 | ALSA PCM Interface |
|---|
| .. | .. |
|---|
| 269 | 234 | } |
|---|
| 270 | 235 | |
|---|
| 271 | 236 | /* |
|---|
| 272 | | - * hw_params callback |
|---|
| 273 | | - */ |
|---|
| 274 | | -static int snd_tm6000_hw_params(struct snd_pcm_substream *substream, |
|---|
| 275 | | - struct snd_pcm_hw_params *hw_params) |
|---|
| 276 | | -{ |
|---|
| 277 | | - int size, rc; |
|---|
| 278 | | - |
|---|
| 279 | | - size = params_period_bytes(hw_params) * params_periods(hw_params); |
|---|
| 280 | | - |
|---|
| 281 | | - rc = dsp_buffer_alloc(substream, size); |
|---|
| 282 | | - if (rc < 0) |
|---|
| 283 | | - return rc; |
|---|
| 284 | | - |
|---|
| 285 | | - return 0; |
|---|
| 286 | | -} |
|---|
| 287 | | - |
|---|
| 288 | | -/* |
|---|
| 289 | | - * hw free callback |
|---|
| 290 | | - */ |
|---|
| 291 | | -static int snd_tm6000_hw_free(struct snd_pcm_substream *substream) |
|---|
| 292 | | -{ |
|---|
| 293 | | - struct snd_tm6000_card *chip = snd_pcm_substream_chip(substream); |
|---|
| 294 | | - struct tm6000_core *core = chip->core; |
|---|
| 295 | | - |
|---|
| 296 | | - if (atomic_read(&core->stream_started) > 0) { |
|---|
| 297 | | - atomic_set(&core->stream_started, 0); |
|---|
| 298 | | - schedule_work(&core->wq_trigger); |
|---|
| 299 | | - } |
|---|
| 300 | | - |
|---|
| 301 | | - dsp_buffer_free(substream); |
|---|
| 302 | | - return 0; |
|---|
| 303 | | -} |
|---|
| 304 | | - |
|---|
| 305 | | -/* |
|---|
| 306 | 237 | * prepare callback |
|---|
| 307 | 238 | */ |
|---|
| 308 | 239 | static int snd_tm6000_prepare(struct snd_pcm_substream *substream) |
|---|
| .. | .. |
|---|
| 341 | 272 | int err = 0; |
|---|
| 342 | 273 | |
|---|
| 343 | 274 | switch (cmd) { |
|---|
| 344 | | - case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: /* fall through */ |
|---|
| 345 | | - case SNDRV_PCM_TRIGGER_RESUME: /* fall through */ |
|---|
| 275 | + case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: |
|---|
| 276 | + case SNDRV_PCM_TRIGGER_RESUME: |
|---|
| 346 | 277 | case SNDRV_PCM_TRIGGER_START: |
|---|
| 347 | 278 | atomic_set(&core->stream_started, 1); |
|---|
| 348 | 279 | break; |
|---|
| 349 | | - case SNDRV_PCM_TRIGGER_PAUSE_PUSH: /* fall through */ |
|---|
| 350 | | - case SNDRV_PCM_TRIGGER_SUSPEND: /* fall through */ |
|---|
| 280 | + case SNDRV_PCM_TRIGGER_PAUSE_PUSH: |
|---|
| 281 | + case SNDRV_PCM_TRIGGER_SUSPEND: |
|---|
| 351 | 282 | case SNDRV_PCM_TRIGGER_STOP: |
|---|
| 352 | 283 | atomic_set(&core->stream_started, 0); |
|---|
| 353 | 284 | break; |
|---|
| .. | .. |
|---|
| 369 | 300 | return chip->buf_pos; |
|---|
| 370 | 301 | } |
|---|
| 371 | 302 | |
|---|
| 372 | | -static struct page *snd_pcm_get_vmalloc_page(struct snd_pcm_substream *subs, |
|---|
| 373 | | - unsigned long offset) |
|---|
| 374 | | -{ |
|---|
| 375 | | - void *pageptr = subs->runtime->dma_area + offset; |
|---|
| 376 | | - |
|---|
| 377 | | - return vmalloc_to_page(pageptr); |
|---|
| 378 | | -} |
|---|
| 379 | | - |
|---|
| 380 | 303 | /* |
|---|
| 381 | 304 | * operators |
|---|
| 382 | 305 | */ |
|---|
| 383 | 306 | static const struct snd_pcm_ops snd_tm6000_pcm_ops = { |
|---|
| 384 | 307 | .open = snd_tm6000_pcm_open, |
|---|
| 385 | 308 | .close = snd_tm6000_close, |
|---|
| 386 | | - .ioctl = snd_pcm_lib_ioctl, |
|---|
| 387 | | - .hw_params = snd_tm6000_hw_params, |
|---|
| 388 | | - .hw_free = snd_tm6000_hw_free, |
|---|
| 389 | 309 | .prepare = snd_tm6000_prepare, |
|---|
| 390 | 310 | .trigger = snd_tm6000_card_trigger, |
|---|
| 391 | 311 | .pointer = snd_tm6000_pointer, |
|---|
| 392 | | - .page = snd_pcm_get_vmalloc_page, |
|---|
| 393 | 312 | }; |
|---|
| 394 | 313 | |
|---|
| 395 | 314 | /* |
|---|
| .. | .. |
|---|
| 429 | 348 | snd_printk(KERN_ERR "cannot create card instance %d\n", devnr); |
|---|
| 430 | 349 | return rc; |
|---|
| 431 | 350 | } |
|---|
| 432 | | - strcpy(card->driver, "tm6000-alsa"); |
|---|
| 433 | | - strcpy(card->shortname, "TM5600/60x0"); |
|---|
| 351 | + strscpy(card->driver, "tm6000-alsa", sizeof(card->driver)); |
|---|
| 352 | + strscpy(card->shortname, "TM5600/60x0", sizeof(card->shortname)); |
|---|
| 434 | 353 | sprintf(card->longname, "TM5600/60x0 Audio at bus %d device %d", |
|---|
| 435 | 354 | dev->udev->bus->busnum, dev->udev->devnum); |
|---|
| 436 | 355 | |
|---|
| .. | .. |
|---|
| 456 | 375 | |
|---|
| 457 | 376 | pcm->info_flags = 0; |
|---|
| 458 | 377 | pcm->private_data = chip; |
|---|
| 459 | | - strcpy(pcm->name, "Trident TM5600/60x0"); |
|---|
| 378 | + strscpy(pcm->name, "Trident TM5600/60x0", sizeof(pcm->name)); |
|---|
| 460 | 379 | |
|---|
| 461 | 380 | snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_tm6000_pcm_ops); |
|---|
| 381 | + snd_pcm_set_managed_buffer_all(pcm, SNDRV_DMA_TYPE_VMALLOC, NULL, 0, 0); |
|---|
| 462 | 382 | |
|---|
| 463 | 383 | INIT_WORK(&dev->wq_trigger, audio_trigger); |
|---|
| 464 | 384 | rc = snd_card_register(card); |
|---|