aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorRicardo Cerqueira <v4l@cerqueira.org>2005-11-13 19:08:10 -0500
committerLinus Torvalds <torvalds@g5.osdl.org>2005-11-13 21:14:20 -0500
commitd5ee43afc9fdde8f853346d32f5ca5c00e8ed886 (patch)
tree47bc8712fc8650058e614774ff9e8cc25653e988 /drivers
parentc01ee851d3e64753877017e8fb19f2e23a1945bc (diff)
[PATCH] v4l: 975: apply saa7134-alsa fixes
Merged parts of a patch from Takashi Iwai for an older version of the module. This patch was adapted and tested by Ricardo Cerqueira. Signed-off-by: Ricardo Cerqueira <v4l@cerqueira.org> Signed-off-by: Mauro Carvalho Chehab <mchehab@brturbo.com.br> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/media/video/saa7134/saa7134-alsa.c277
1 files changed, 120 insertions, 157 deletions
diff --git a/drivers/media/video/saa7134/saa7134-alsa.c b/drivers/media/video/saa7134/saa7134-alsa.c
index 289ca3ac99b..5707c666660 100644
--- a/drivers/media/video/saa7134/saa7134-alsa.c
+++ b/drivers/media/video/saa7134/saa7134-alsa.c
@@ -30,6 +30,7 @@
30#include <sound/core.h> 30#include <sound/core.h>
31#include <sound/control.h> 31#include <sound/control.h>
32#include <sound/pcm.h> 32#include <sound/pcm.h>
33#include <sound/pcm_params.h>
33#include <sound/initval.h> 34#include <sound/initval.h>
34#include <linux/interrupt.h> 35#include <linux/interrupt.h>
35 36
@@ -168,8 +169,9 @@ void saa7134_irq_alsa_done(struct saa7134_dev *dev, unsigned long status)
168 if (dev->dmasound.read_count >= dev->dmasound.blksize * (dev->dmasound.blocks-2)) { 169 if (dev->dmasound.read_count >= dev->dmasound.blksize * (dev->dmasound.blocks-2)) {
169 dprintk("irq: overrun [full=%d/%d] - Blocks in %d\n",dev->dmasound.read_count, 170 dprintk("irq: overrun [full=%d/%d] - Blocks in %d\n",dev->dmasound.read_count,
170 dev->dmasound.bufsize, dev->dmasound.blocks); 171 dev->dmasound.bufsize, dev->dmasound.blocks);
172 spin_unlock(&dev->slock);
171 snd_pcm_stop(dev->dmasound.substream,SNDRV_PCM_STATE_XRUN); 173 snd_pcm_stop(dev->dmasound.substream,SNDRV_PCM_STATE_XRUN);
172 goto done; 174 return;
173 } 175 }
174 176
175 /* next block addr */ 177 /* next block addr */
@@ -252,7 +254,7 @@ static int snd_card_saa7134_capture_trigger(snd_pcm_substream_t * substream,
252 struct saa7134_dev *dev=pcm->dev; 254 struct saa7134_dev *dev=pcm->dev;
253 int err = 0; 255 int err = 0;
254 256
255 spin_lock_irq(&dev->slock); 257 spin_lock(&dev->slock);
256 if (cmd == SNDRV_PCM_TRIGGER_START) { 258 if (cmd == SNDRV_PCM_TRIGGER_START) {
257 /* start dma */ 259 /* start dma */
258 saa7134_dma_start(dev); 260 saa7134_dma_start(dev);
@@ -262,45 +264,12 @@ static int snd_card_saa7134_capture_trigger(snd_pcm_substream_t * substream,
262 } else { 264 } else {
263 err = -EINVAL; 265 err = -EINVAL;
264 } 266 }
265 spin_unlock_irq(&dev->slock); 267 spin_unlock(&dev->slock);
266 268
267 return err; 269 return err;
268} 270}
269 271
270/* 272/*
271 * DMA buffer config
272 *
273 * Sets the values that will later be used as the size of the buffer,
274 * size of the fragments, and total number of fragments.
275 * Must be called during the preparation stage, before memory is
276 * allocated
277 *
278 * - Copied verbatim from saa7134-oss.
279 *
280 */
281
282static int dsp_buffer_conf(struct saa7134_dev *dev, int blksize, int blocks)
283{
284 if (blksize < 0x100)
285 blksize = 0x100;
286 if (blksize > 0x10000)
287 blksize = 0x10000;
288
289 if (blocks < 2)
290 blocks = 2;
291 if ((blksize * blocks) > 1024*1024)
292 blocks = 1024*1024 / blksize;
293
294 dev->dmasound.blocks = blocks;
295 dev->dmasound.blksize = blksize;
296 dev->dmasound.bufsize = blksize * blocks;
297
298 dprintk("buffer config: %d blocks / %d bytes, %d kB total\n",
299 blocks,blksize,blksize * blocks / 1024);
300 return 0;
301}
302
303/*
304 * DMA buffer initialization 273 * DMA buffer initialization
305 * 274 *
306 * Uses V4L functions to initialize the DMA. Shouldn't be necessary in 275 * Uses V4L functions to initialize the DMA. Shouldn't be necessary in
@@ -326,6 +295,28 @@ static int dsp_buffer_init(struct saa7134_dev *dev)
326} 295}
327 296
328/* 297/*
298 * DMA buffer release
299 *
300 * Called after closing the device, during snd_card_saa7134_capture_close
301 *
302 */
303
304static int dsp_buffer_free(struct saa7134_dev *dev)
305{
306 if (!dev->dmasound.blksize)
307 BUG();
308
309 videobuf_dma_free(&dev->dmasound.dma);
310
311 dev->dmasound.blocks = 0;
312 dev->dmasound.blksize = 0;
313 dev->dmasound.bufsize = 0;
314
315 return 0;
316}
317
318
319/*
329 * ALSA PCM preparation 320 * ALSA PCM preparation
330 * 321 *
331 * - One of the ALSA capture callbacks. 322 * - One of the ALSA capture callbacks.
@@ -340,74 +331,30 @@ static int dsp_buffer_init(struct saa7134_dev *dev)
340static int snd_card_saa7134_capture_prepare(snd_pcm_substream_t * substream) 331static int snd_card_saa7134_capture_prepare(snd_pcm_substream_t * substream)
341{ 332{
342 snd_pcm_runtime_t *runtime = substream->runtime; 333 snd_pcm_runtime_t *runtime = substream->runtime;
343 int err, bswap, sign; 334 int bswap, sign;
344 u32 fmt, control; 335 u32 fmt, control;
345 snd_card_saa7134_t *saa7134 = snd_pcm_substream_chip(substream); 336 snd_card_saa7134_t *saa7134 = snd_pcm_substream_chip(substream);
346 struct saa7134_dev *dev; 337 struct saa7134_dev *dev;
347 snd_card_saa7134_pcm_t *pcm = runtime->private_data; 338 snd_card_saa7134_pcm_t *pcm = runtime->private_data;
348 unsigned long size;
349 unsigned count;
350
351 size = snd_pcm_lib_buffer_bytes(substream);
352 count = snd_pcm_lib_period_bytes(substream);
353 339
354 pcm->dev->dmasound.substream = substream; 340 pcm->dev->dmasound.substream = substream;
355 341
356 dev=saa7134->dev; 342 dev = saa7134->dev;
357
358 dsp_buffer_conf(dev,count,(size/count));
359
360 err = dsp_buffer_init(dev);
361 if (0 != err)
362 return err;
363
364 /* prepare buffer */
365 if (0 != (err = videobuf_dma_pci_map(dev->pci,&dev->dmasound.dma)))
366 return err;
367 if (0 != (err = saa7134_pgtable_alloc(dev->pci,&dev->dmasound.pt)))
368 goto fail1;
369 if (0 != (err = saa7134_pgtable_build(dev->pci,&dev->dmasound.pt,
370 dev->dmasound.dma.sglist,
371 dev->dmasound.dma.sglen,
372 0)))
373 goto fail2;
374
375
376 343
377 switch (runtime->format) { 344 if (snd_pcm_format_width(runtime->format) == 8)
378 case SNDRV_PCM_FORMAT_U8:
379 case SNDRV_PCM_FORMAT_S8:
380 fmt = 0x00; 345 fmt = 0x00;
381 break; 346 else
382 case SNDRV_PCM_FORMAT_U16_LE:
383 case SNDRV_PCM_FORMAT_U16_BE:
384 case SNDRV_PCM_FORMAT_S16_LE:
385 case SNDRV_PCM_FORMAT_S16_BE:
386 fmt = 0x01; 347 fmt = 0x01;
387 break;
388 default:
389 err = -EINVAL;
390 return 1;
391 }
392 348
393 switch (runtime->format) { 349 if (snd_pcm_format_signed(runtime->format))
394 case SNDRV_PCM_FORMAT_S8:
395 case SNDRV_PCM_FORMAT_S16_LE:
396 case SNDRV_PCM_FORMAT_S16_BE:
397 sign = 1; 350 sign = 1;
398 break; 351 else
399 default:
400 sign = 0; 352 sign = 0;
401 break;
402 }
403 353
404 switch (runtime->format) { 354 if (snd_pcm_format_big_endian(runtime->format))
405 case SNDRV_PCM_FORMAT_U16_BE: 355 bswap = 1;
406 case SNDRV_PCM_FORMAT_S16_BE: 356 else
407 bswap = 1; break; 357 bswap = 0;
408 default:
409 bswap = 0; break;
410 }
411 358
412 switch (dev->pci->device) { 359 switch (dev->pci->device) {
413 case PCI_DEVICE_ID_PHILIPS_SAA7134: 360 case PCI_DEVICE_ID_PHILIPS_SAA7134:
@@ -448,12 +395,6 @@ static int snd_card_saa7134_capture_prepare(snd_pcm_substream_t * substream)
448 if (bswap) 395 if (bswap)
449 control |= SAA7134_RS_CONTROL_BSWAP; 396 control |= SAA7134_RS_CONTROL_BSWAP;
450 397
451 /* I should be able to use runtime->dma_addr in the control
452 byte, but it doesn't work. So I allocate the DMA using the
453 V4L functions, and force ALSA to use that as the DMA area */
454
455 runtime->dma_area = dev->dmasound.dma.vmalloc;
456
457 saa_writel(SAA7134_RS_BA1(6),0); 398 saa_writel(SAA7134_RS_BA1(6),0);
458 saa_writel(SAA7134_RS_BA2(6),dev->dmasound.blksize); 399 saa_writel(SAA7134_RS_BA2(6),dev->dmasound.blksize);
459 saa_writel(SAA7134_RS_PITCH(6),0); 400 saa_writel(SAA7134_RS_PITCH(6),0);
@@ -462,12 +403,6 @@ static int snd_card_saa7134_capture_prepare(snd_pcm_substream_t * substream)
462 dev->dmasound.rate = runtime->rate; 403 dev->dmasound.rate = runtime->rate;
463 404
464 return 0; 405 return 0;
465 fail2:
466 saa7134_pgtable_free(dev->pci,&dev->dmasound.pt);
467 fail1:
468 videobuf_dma_pci_unmap(dev->pci,&dev->dmasound.dma);
469 return err;
470
471 406
472} 407}
473 408
@@ -539,15 +474,76 @@ static void snd_card_saa7134_runtime_free(snd_pcm_runtime_t *runtime)
539 * - One of the ALSA capture callbacks. 474 * - One of the ALSA capture callbacks.
540 * 475 *
541 * Called on initialization, right before the PCM preparation 476 * Called on initialization, right before the PCM preparation
542 * Usually used in ALSA to allocate the DMA, but since we don't use the
543 * ALSA DMA it does nothing
544 * 477 *
545 */ 478 */
546 479
547static int snd_card_saa7134_hw_params(snd_pcm_substream_t * substream, 480static int snd_card_saa7134_hw_params(snd_pcm_substream_t * substream,
548 snd_pcm_hw_params_t * hw_params) 481 snd_pcm_hw_params_t * hw_params)
549{ 482{
550 return 0; 483 snd_card_saa7134_t *saa7134 = snd_pcm_substream_chip(substream);
484 struct saa7134_dev *dev;
485 unsigned int period_size, periods;
486 int err;
487
488 period_size = params_period_bytes(hw_params);
489 periods = params_periods(hw_params);
490
491 snd_assert(period_size >= 0x100 && period_size <= 0x10000,
492 return -EINVAL);
493 snd_assert(periods >= 2, return -EINVAL);
494 snd_assert(period_size * periods <= 1024 * 1024, return -EINVAL);
495
496 dev = saa7134->dev;
497
498 if (dev->dmasound.blocks == periods &&
499 dev->dmasound.blksize == period_size)
500 return 0;
501
502 /* release the old buffer */
503 if (substream->runtime->dma_area) {
504 saa7134_pgtable_free(dev->pci, &dev->dmasound.pt);
505 videobuf_dma_pci_unmap(dev->pci, &dev->dmasound.dma);
506 dsp_buffer_free(dev);
507 substream->runtime->dma_area = NULL;
508 }
509 dev->dmasound.blocks = periods;
510 dev->dmasound.blksize = period_size;
511 dev->dmasound.bufsize = period_size * periods;
512
513 err = dsp_buffer_init(dev);
514 if (0 != err) {
515 dev->dmasound.blocks = 0;
516 dev->dmasound.blksize = 0;
517 dev->dmasound.bufsize = 0;
518 return err;
519 }
520
521 if (0 != (err = videobuf_dma_pci_map(dev->pci, &dev->dmasound.dma))) {
522 dsp_buffer_free(dev);
523 return err;
524 }
525 if (0 != (err = saa7134_pgtable_alloc(dev->pci,&dev->dmasound.pt))) {
526 videobuf_dma_pci_unmap(dev->pci, &dev->dmasound.dma);
527 dsp_buffer_free(dev);
528 return err;
529 }
530 if (0 != (err = saa7134_pgtable_build(dev->pci,&dev->dmasound.pt,
531 dev->dmasound.dma.sglist,
532 dev->dmasound.dma.sglen,
533 0))) {
534 saa7134_pgtable_free(dev->pci, &dev->dmasound.pt);
535 videobuf_dma_pci_unmap(dev->pci, &dev->dmasound.dma);
536 dsp_buffer_free(dev);
537 return err;
538 }
539
540 /* I should be able to use runtime->dma_addr in the control
541 byte, but it doesn't work. So I allocate the DMA using the
542 V4L functions, and force ALSA to use that as the DMA area */
543
544 substream->runtime->dma_area = dev->dmasound.dma.vmalloc;
545
546 return 1;
551 547
552} 548}
553 549
@@ -557,33 +553,23 @@ static int snd_card_saa7134_hw_params(snd_pcm_substream_t * substream,
557 * - One of the ALSA capture callbacks. 553 * - One of the ALSA capture callbacks.
558 * 554 *
559 * Called after closing the device, but before snd_card_saa7134_capture_close 555 * Called after closing the device, but before snd_card_saa7134_capture_close
560 * Usually used in ALSA to free the DMA, but since we don't use the 556 * It stops the DMA audio and releases the buffers.
561 * ALSA DMA it does nothing
562 * 557 *
563 */ 558 */
564 559
565static int snd_card_saa7134_hw_free(snd_pcm_substream_t * substream) 560static int snd_card_saa7134_hw_free(snd_pcm_substream_t * substream)
566{ 561{
567 return 0; 562 snd_card_saa7134_t *saa7134 = snd_pcm_substream_chip(substream);
568} 563 struct saa7134_dev *dev;
569
570/*
571 * DMA buffer release
572 *
573 * Called after closing the device, during snd_card_saa7134_capture_close
574 *
575 */
576
577static int dsp_buffer_free(struct saa7134_dev *dev)
578{
579 if (!dev->dmasound.blksize)
580 BUG();
581 564
582 videobuf_dma_free(&dev->dmasound.dma); 565 dev = saa7134->dev;
583 566
584 dev->dmasound.blocks = 0; 567 if (substream->runtime->dma_area) {
585 dev->dmasound.blksize = 0; 568 saa7134_pgtable_free(dev->pci, &dev->dmasound.pt);
586 dev->dmasound.bufsize = 0; 569 videobuf_dma_pci_unmap(dev->pci, &dev->dmasound.dma);
570 dsp_buffer_free(dev);
571 substream->runtime->dma_area = NULL;
572 }
587 573
588 return 0; 574 return 0;
589} 575}
@@ -593,21 +579,12 @@ static int dsp_buffer_free(struct saa7134_dev *dev)
593 * 579 *
594 * - One of the ALSA capture callbacks. 580 * - One of the ALSA capture callbacks.
595 * 581 *
596 * Called after closing the device. It stops the DMA audio and releases 582 * Called after closing the device.
597 * the buffers
598 * 583 *
599 */ 584 */
600 585
601static int snd_card_saa7134_capture_close(snd_pcm_substream_t * substream) 586static int snd_card_saa7134_capture_close(snd_pcm_substream_t * substream)
602{ 587{
603 snd_card_saa7134_t *chip = snd_pcm_substream_chip(substream);
604 struct saa7134_dev *dev = chip->dev;
605
606 /* unlock buffer */
607 saa7134_pgtable_free(dev->pci,&dev->dmasound.pt);
608 videobuf_dma_pci_unmap(dev->pci,&dev->dmasound.dma);
609
610 dsp_buffer_free(dev);
611 return 0; 588 return 0;
612} 589}
613 590
@@ -720,7 +697,6 @@ static int snd_saa7134_volume_get(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_
720static int snd_saa7134_volume_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol) 697static int snd_saa7134_volume_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
721{ 698{
722 snd_card_saa7134_t *chip = snd_kcontrol_chip(kcontrol); 699 snd_card_saa7134_t *chip = snd_kcontrol_chip(kcontrol);
723 unsigned long flags;
724 int change, addr = kcontrol->private_value; 700 int change, addr = kcontrol->private_value;
725 int left, right; 701 int left, right;
726 702
@@ -734,12 +710,12 @@ static int snd_saa7134_volume_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_
734 right = 0; 710 right = 0;
735 if (right > 20) 711 if (right > 20)
736 right = 20; 712 right = 20;
737 spin_lock_irqsave(&chip->mixer_lock, flags); 713 spin_lock_irq(&chip->mixer_lock);
738 change = chip->mixer_volume[addr][0] != left || 714 change = chip->mixer_volume[addr][0] != left ||
739 chip->mixer_volume[addr][1] != right; 715 chip->mixer_volume[addr][1] != right;
740 chip->mixer_volume[addr][0] = left; 716 chip->mixer_volume[addr][0] = left;
741 chip->mixer_volume[addr][1] = right; 717 chip->mixer_volume[addr][1] = right;
742 spin_unlock_irqrestore(&chip->mixer_lock, flags); 718 spin_unlock_irq(&chip->mixer_lock);
743 return change; 719 return change;
744} 720}
745 721
@@ -761,13 +737,12 @@ static int snd_saa7134_capsrc_info(snd_kcontrol_t * kcontrol, snd_ctl_elem_info_
761static int snd_saa7134_capsrc_get(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol) 737static int snd_saa7134_capsrc_get(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
762{ 738{
763 snd_card_saa7134_t *chip = snd_kcontrol_chip(kcontrol); 739 snd_card_saa7134_t *chip = snd_kcontrol_chip(kcontrol);
764 unsigned long flags;
765 int addr = kcontrol->private_value; 740 int addr = kcontrol->private_value;
766 741
767 spin_lock_irqsave(&chip->mixer_lock, flags); 742 spin_lock_irq(&chip->mixer_lock);
768 ucontrol->value.integer.value[0] = chip->capture_source[addr][0]; 743 ucontrol->value.integer.value[0] = chip->capture_source[addr][0];
769 ucontrol->value.integer.value[1] = chip->capture_source[addr][1]; 744 ucontrol->value.integer.value[1] = chip->capture_source[addr][1];
770 spin_unlock_irqrestore(&chip->mixer_lock, flags); 745 spin_unlock_irq(&chip->mixer_lock);
771 746
772 return 0; 747 return 0;
773} 748}
@@ -884,15 +859,10 @@ static int snd_card_saa7134_new_mixer(snd_card_saa7134_t * chip)
884 859
885static void snd_saa7134_free(snd_card_t * card) 860static void snd_saa7134_free(snd_card_t * card)
886{ 861{
887 return; 862 snd_card_saa7134_t *chip = card->private_data;
888}
889
890static int snd_saa7134_dev_free(snd_device_t *device)
891{
892 snd_card_saa7134_t *chip = device->device_data;
893 863
894 if (chip->dev->dmasound.priv_data == NULL) 864 if (chip->dev->dmasound.priv_data == NULL)
895 return 0; 865 return;
896 866
897 if (chip->irq >= 0) { 867 if (chip->irq >= 0) {
898 synchronize_irq(chip->irq); 868 synchronize_irq(chip->irq);
@@ -901,7 +871,6 @@ static int snd_saa7134_dev_free(snd_device_t *device)
901 871
902 chip->dev->dmasound.priv_data = NULL; 872 chip->dev->dmasound.priv_data = NULL;
903 873
904 return 0;
905} 874}
906 875
907/* 876/*
@@ -918,9 +887,6 @@ int alsa_card_saa7134_create(struct saa7134_dev *dev, int devnum)
918 snd_card_t *card; 887 snd_card_t *card;
919 snd_card_saa7134_t *chip; 888 snd_card_saa7134_t *chip;
920 int err; 889 int err;
921 static snd_device_ops_t ops = {
922 .dev_free = snd_saa7134_dev_free,
923 };
924 890
925 891
926 if (devnum >= SNDRV_CARDS) 892 if (devnum >= SNDRV_CARDS)
@@ -948,7 +914,6 @@ int alsa_card_saa7134_create(struct saa7134_dev *dev, int devnum)
948 chip->card = card; 914 chip->card = card;
949 915
950 chip->pci = dev->pci; 916 chip->pci = dev->pci;
951 chip->irq = dev->pci->irq;
952 chip->iobase = pci_resource_start(dev->pci, 0); 917 chip->iobase = pci_resource_start(dev->pci, 0);
953 918
954 919
@@ -962,11 +927,9 @@ int alsa_card_saa7134_create(struct saa7134_dev *dev, int devnum)
962 goto __nodev; 927 goto __nodev;
963 } 928 }
964 929
965 init_MUTEX(&dev->dmasound.lock); 930 chip->irq = dev->pci->irq;
966 931
967 if ((err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops)) < 0) { 932 init_MUTEX(&dev->dmasound.lock);
968 goto __nodev;
969 }
970 933
971 if ((err = snd_card_saa7134_new_mixer(chip)) < 0) 934 if ((err = snd_card_saa7134_new_mixer(chip)) < 0)
972 goto __nodev; 935 goto __nodev;