aboutsummaryrefslogtreecommitdiffstats
path: root/sound
diff options
context:
space:
mode:
authorHans-Christian Egtvedt <hans-christian.egtvedt@atmel.com>2009-04-02 02:21:14 -0400
committerTakashi Iwai <tiwai@suse.de>2009-04-05 21:55:33 -0400
commitdf163587eab15a24cc34cf8434a5657416f8a203 (patch)
tree6c9eeebc72fd8bca19cc6c5f8500e3c505e7c871 /sound
parentc42eec0f193ed408118e20d85ea8c2e69c529993 (diff)
ALSA: snd-atmel-ac97c: enable interrupts to catch events for error reporting
This patch will enable interrupts from AC97C and report about error conditions that occurs. On channel A both overrun and underrun will be enabled depending if playback and/or capture are enabled. On the control channel the overrun interrupt is enabled. Signed-off-by: Hans-Christian Egtvedt <hans-christian.egtvedt@atmel.com> Signed-off-by: Takashi Iwai <tiwai@suse.de>
Diffstat (limited to 'sound')
-rw-r--r--sound/atmel/ac97c.c77
1 files changed, 76 insertions, 1 deletions
diff --git a/sound/atmel/ac97c.c b/sound/atmel/ac97c.c
index c9bc3458fa2d..e8484cb9ac62 100644
--- a/sound/atmel/ac97c.c
+++ b/sound/atmel/ac97c.c
@@ -66,6 +66,7 @@ struct atmel_ac97c {
66 /* Serialize access to opened variable */ 66 /* Serialize access to opened variable */
67 spinlock_t lock; 67 spinlock_t lock;
68 void __iomem *regs; 68 void __iomem *regs;
69 int irq;
69 int opened; 70 int opened;
70 int reset_pin; 71 int reset_pin;
71}; 72};
@@ -335,8 +336,16 @@ static int atmel_ac97c_playback_prepare(struct snd_pcm_substream *substream)
335 return -EINVAL; 336 return -EINVAL;
336 } 337 }
337 338
339 /* Enable underrun interrupt on channel A */
340 word |= AC97C_CSR_UNRUN;
341
338 ac97c_writel(chip, CAMR, word); 342 ac97c_writel(chip, CAMR, word);
339 343
344 /* Enable channel A event interrupt */
345 word = ac97c_readl(chip, IMR);
346 word |= AC97C_SR_CAEVT;
347 ac97c_writel(chip, IER, word);
348
340 /* set variable rate if needed */ 349 /* set variable rate if needed */
341 if (runtime->rate != 48000) { 350 if (runtime->rate != 48000) {
342 word = ac97c_readl(chip, MR); 351 word = ac97c_readl(chip, MR);
@@ -402,8 +411,16 @@ static int atmel_ac97c_capture_prepare(struct snd_pcm_substream *substream)
402 return -EINVAL; 411 return -EINVAL;
403 } 412 }
404 413
414 /* Enable overrun interrupt on channel A */
415 word |= AC97C_CSR_OVRUN;
416
405 ac97c_writel(chip, CAMR, word); 417 ac97c_writel(chip, CAMR, word);
406 418
419 /* Enable channel A event interrupt */
420 word = ac97c_readl(chip, IMR);
421 word |= AC97C_SR_CAEVT;
422 ac97c_writel(chip, IER, word);
423
407 /* set variable rate if needed */ 424 /* set variable rate if needed */
408 if (runtime->rate != 48000) { 425 if (runtime->rate != 48000) {
409 word = ac97c_readl(chip, MR); 426 word = ac97c_readl(chip, MR);
@@ -554,6 +571,43 @@ static struct snd_pcm_ops atmel_ac97_capture_ops = {
554 .pointer = atmel_ac97c_capture_pointer, 571 .pointer = atmel_ac97c_capture_pointer,
555}; 572};
556 573
574static irqreturn_t atmel_ac97c_interrupt(int irq, void *dev)
575{
576 struct atmel_ac97c *chip = (struct atmel_ac97c *)dev;
577 irqreturn_t retval = IRQ_NONE;
578 u32 sr = ac97c_readl(chip, SR);
579 u32 casr = ac97c_readl(chip, CASR);
580 u32 cosr = ac97c_readl(chip, COSR);
581
582 if (sr & AC97C_SR_CAEVT) {
583 dev_info(&chip->pdev->dev, "channel A event%s%s%s%s%s%s\n",
584 casr & AC97C_CSR_OVRUN ? " OVRUN" : "",
585 casr & AC97C_CSR_RXRDY ? " RXRDY" : "",
586 casr & AC97C_CSR_UNRUN ? " UNRUN" : "",
587 casr & AC97C_CSR_TXEMPTY ? " TXEMPTY" : "",
588 casr & AC97C_CSR_TXRDY ? " TXRDY" : "",
589 !casr ? " NONE" : "");
590 retval = IRQ_HANDLED;
591 }
592
593 if (sr & AC97C_SR_COEVT) {
594 dev_info(&chip->pdev->dev, "codec channel event%s%s%s%s%s\n",
595 cosr & AC97C_CSR_OVRUN ? " OVRUN" : "",
596 cosr & AC97C_CSR_RXRDY ? " RXRDY" : "",
597 cosr & AC97C_CSR_TXEMPTY ? " TXEMPTY" : "",
598 cosr & AC97C_CSR_TXRDY ? " TXRDY" : "",
599 !cosr ? " NONE" : "");
600 retval = IRQ_HANDLED;
601 }
602
603 if (retval == IRQ_NONE) {
604 dev_err(&chip->pdev->dev, "spurious interrupt sr 0x%08x "
605 "casr 0x%08x cosr 0x%08x\n", sr, casr, cosr);
606 }
607
608 return retval;
609}
610
557static int __devinit atmel_ac97c_pcm_new(struct atmel_ac97c *chip) 611static int __devinit atmel_ac97c_pcm_new(struct atmel_ac97c *chip)
558{ 612{
559 struct snd_pcm *pcm; 613 struct snd_pcm *pcm;
@@ -701,6 +755,7 @@ static int __devinit atmel_ac97c_probe(struct platform_device *pdev)
701 .read = atmel_ac97c_read, 755 .read = atmel_ac97c_read,
702 }; 756 };
703 int retval; 757 int retval;
758 int irq;
704 759
705 regs = platform_get_resource(pdev, IORESOURCE_MEM, 0); 760 regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);
706 if (!regs) { 761 if (!regs) {
@@ -714,6 +769,12 @@ static int __devinit atmel_ac97c_probe(struct platform_device *pdev)
714 return -ENXIO; 769 return -ENXIO;
715 } 770 }
716 771
772 irq = platform_get_irq(pdev, 0);
773 if (irq < 0) {
774 dev_dbg(&pdev->dev, "could not get irq\n");
775 return -ENXIO;
776 }
777
717 pclk = clk_get(&pdev->dev, "pclk"); 778 pclk = clk_get(&pdev->dev, "pclk");
718 if (IS_ERR(pclk)) { 779 if (IS_ERR(pclk)) {
719 dev_dbg(&pdev->dev, "no peripheral clock\n"); 780 dev_dbg(&pdev->dev, "no peripheral clock\n");
@@ -730,6 +791,13 @@ static int __devinit atmel_ac97c_probe(struct platform_device *pdev)
730 791
731 chip = get_chip(card); 792 chip = get_chip(card);
732 793
794 retval = request_irq(irq, atmel_ac97c_interrupt, 0, "AC97C", chip);
795 if (retval) {
796 dev_dbg(&pdev->dev, "unable to request irq %d\n", irq);
797 goto err_request_irq;
798 }
799 chip->irq = irq;
800
733 spin_lock_init(&chip->lock); 801 spin_lock_init(&chip->lock);
734 802
735 strcpy(card->driver, "Atmel AC97C"); 803 strcpy(card->driver, "Atmel AC97C");
@@ -758,6 +826,10 @@ static int __devinit atmel_ac97c_probe(struct platform_device *pdev)
758 826
759 snd_card_set_dev(card, &pdev->dev); 827 snd_card_set_dev(card, &pdev->dev);
760 828
829 /* Enable overrun interrupt from codec channel */
830 ac97c_writel(chip, COMR, AC97C_CSR_OVRUN);
831 ac97c_writel(chip, IER, ac97c_readl(chip, IMR) | AC97C_SR_COEVT);
832
761 retval = snd_ac97_bus(card, 0, &ops, chip, &chip->ac97_bus); 833 retval = snd_ac97_bus(card, 0, &ops, chip, &chip->ac97_bus);
762 if (retval) { 834 if (retval) {
763 dev_dbg(&pdev->dev, "could not register on ac97 bus\n"); 835 dev_dbg(&pdev->dev, "could not register on ac97 bus\n");
@@ -820,7 +892,7 @@ static int __devinit atmel_ac97c_probe(struct platform_device *pdev)
820 retval = snd_card_register(card); 892 retval = snd_card_register(card);
821 if (retval) { 893 if (retval) {
822 dev_dbg(&pdev->dev, "could not register sound card\n"); 894 dev_dbg(&pdev->dev, "could not register sound card\n");
823 goto err_ac97_bus; 895 goto err_dma;
824 } 896 }
825 897
826 platform_set_drvdata(pdev, card); 898 platform_set_drvdata(pdev, card);
@@ -847,6 +919,8 @@ err_ac97_bus:
847 919
848 iounmap(chip->regs); 920 iounmap(chip->regs);
849err_ioremap: 921err_ioremap:
922 free_irq(irq, chip);
923err_request_irq:
850 snd_card_free(card); 924 snd_card_free(card);
851err_snd_card_new: 925err_snd_card_new:
852 clk_disable(pclk); 926 clk_disable(pclk);
@@ -898,6 +972,7 @@ static int __devexit atmel_ac97c_remove(struct platform_device *pdev)
898 clk_disable(chip->pclk); 972 clk_disable(chip->pclk);
899 clk_put(chip->pclk); 973 clk_put(chip->pclk);
900 iounmap(chip->regs); 974 iounmap(chip->regs);
975 free_irq(chip->irq, chip);
901 976
902 if (test_bit(DMA_RX_CHAN_PRESENT, &chip->flags)) 977 if (test_bit(DMA_RX_CHAN_PRESENT, &chip->flags))
903 dma_release_channel(chip->dma.rx_chan); 978 dma_release_channel(chip->dma.rx_chan);