diff options
Diffstat (limited to 'sound/atmel/ac97c.c')
-rw-r--r-- | sound/atmel/ac97c.c | 128 |
1 files changed, 109 insertions, 19 deletions
diff --git a/sound/atmel/ac97c.c b/sound/atmel/ac97c.c index dd72e00e5ae1..0c0f8771656a 100644 --- a/sound/atmel/ac97c.c +++ b/sound/atmel/ac97c.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * Driver for the Atmel AC97C controller | 2 | * Driver for Atmel AC97C |
3 | * | 3 | * |
4 | * Copyright (C) 2005-2009 Atmel Corporation | 4 | * Copyright (C) 2005-2009 Atmel Corporation |
5 | * | 5 | * |
@@ -10,6 +10,7 @@ | |||
10 | #include <linux/clk.h> | 10 | #include <linux/clk.h> |
11 | #include <linux/delay.h> | 11 | #include <linux/delay.h> |
12 | #include <linux/bitmap.h> | 12 | #include <linux/bitmap.h> |
13 | #include <linux/device.h> | ||
13 | #include <linux/dmaengine.h> | 14 | #include <linux/dmaengine.h> |
14 | #include <linux/dma-mapping.h> | 15 | #include <linux/dma-mapping.h> |
15 | #include <linux/init.h> | 16 | #include <linux/init.h> |
@@ -65,6 +66,7 @@ struct atmel_ac97c { | |||
65 | /* Serialize access to opened variable */ | 66 | /* Serialize access to opened variable */ |
66 | spinlock_t lock; | 67 | spinlock_t lock; |
67 | void __iomem *regs; | 68 | void __iomem *regs; |
69 | int irq; | ||
68 | int opened; | 70 | int opened; |
69 | int reset_pin; | 71 | int reset_pin; |
70 | }; | 72 | }; |
@@ -150,10 +152,10 @@ static struct snd_pcm_hardware atmel_ac97c_hw = { | |||
150 | .rate_max = 48000, | 152 | .rate_max = 48000, |
151 | .channels_min = 1, | 153 | .channels_min = 1, |
152 | .channels_max = 2, | 154 | .channels_max = 2, |
153 | .buffer_bytes_max = 64 * 4096, | 155 | .buffer_bytes_max = 2 * 2 * 64 * 2048, |
154 | .period_bytes_min = 4096, | 156 | .period_bytes_min = 4096, |
155 | .period_bytes_max = 4096, | 157 | .period_bytes_max = 4096, |
156 | .periods_min = 4, | 158 | .periods_min = 6, |
157 | .periods_max = 64, | 159 | .periods_max = 64, |
158 | }; | 160 | }; |
159 | 161 | ||
@@ -297,9 +299,11 @@ static int atmel_ac97c_playback_prepare(struct snd_pcm_substream *substream) | |||
297 | { | 299 | { |
298 | struct atmel_ac97c *chip = snd_pcm_substream_chip(substream); | 300 | struct atmel_ac97c *chip = snd_pcm_substream_chip(substream); |
299 | struct snd_pcm_runtime *runtime = substream->runtime; | 301 | struct snd_pcm_runtime *runtime = substream->runtime; |
300 | unsigned long word = 0; | 302 | unsigned long word = ac97c_readl(chip, OCA); |
301 | int retval; | 303 | int retval; |
302 | 304 | ||
305 | word &= ~(AC97C_CH_MASK(PCM_LEFT) | AC97C_CH_MASK(PCM_RIGHT)); | ||
306 | |||
303 | /* assign channels to AC97C channel A */ | 307 | /* assign channels to AC97C channel A */ |
304 | switch (runtime->channels) { | 308 | switch (runtime->channels) { |
305 | case 1: | 309 | case 1: |
@@ -312,7 +316,6 @@ static int atmel_ac97c_playback_prepare(struct snd_pcm_substream *substream) | |||
312 | default: | 316 | default: |
313 | /* TODO: support more than two channels */ | 317 | /* TODO: support more than two channels */ |
314 | return -EINVAL; | 318 | return -EINVAL; |
315 | break; | ||
316 | } | 319 | } |
317 | ac97c_writel(chip, OCA, word); | 320 | ac97c_writel(chip, OCA, word); |
318 | 321 | ||
@@ -324,13 +327,25 @@ static int atmel_ac97c_playback_prepare(struct snd_pcm_substream *substream) | |||
324 | word |= AC97C_CMR_CEM_LITTLE; | 327 | word |= AC97C_CMR_CEM_LITTLE; |
325 | break; | 328 | break; |
326 | case SNDRV_PCM_FORMAT_S16_BE: /* fall through */ | 329 | case SNDRV_PCM_FORMAT_S16_BE: /* fall through */ |
327 | default: | ||
328 | word &= ~(AC97C_CMR_CEM_LITTLE); | 330 | word &= ~(AC97C_CMR_CEM_LITTLE); |
329 | break; | 331 | break; |
332 | default: | ||
333 | word = ac97c_readl(chip, OCA); | ||
334 | word &= ~(AC97C_CH_MASK(PCM_LEFT) | AC97C_CH_MASK(PCM_RIGHT)); | ||
335 | ac97c_writel(chip, OCA, word); | ||
336 | return -EINVAL; | ||
330 | } | 337 | } |
331 | 338 | ||
339 | /* Enable underrun interrupt on channel A */ | ||
340 | word |= AC97C_CSR_UNRUN; | ||
341 | |||
332 | ac97c_writel(chip, CAMR, word); | 342 | ac97c_writel(chip, CAMR, word); |
333 | 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 | |||
334 | /* set variable rate if needed */ | 349 | /* set variable rate if needed */ |
335 | if (runtime->rate != 48000) { | 350 | if (runtime->rate != 48000) { |
336 | word = ac97c_readl(chip, MR); | 351 | word = ac97c_readl(chip, MR); |
@@ -359,9 +374,11 @@ static int atmel_ac97c_capture_prepare(struct snd_pcm_substream *substream) | |||
359 | { | 374 | { |
360 | struct atmel_ac97c *chip = snd_pcm_substream_chip(substream); | 375 | struct atmel_ac97c *chip = snd_pcm_substream_chip(substream); |
361 | struct snd_pcm_runtime *runtime = substream->runtime; | 376 | struct snd_pcm_runtime *runtime = substream->runtime; |
362 | unsigned long word = 0; | 377 | unsigned long word = ac97c_readl(chip, ICA); |
363 | int retval; | 378 | int retval; |
364 | 379 | ||
380 | word &= ~(AC97C_CH_MASK(PCM_LEFT) | AC97C_CH_MASK(PCM_RIGHT)); | ||
381 | |||
365 | /* assign channels to AC97C channel A */ | 382 | /* assign channels to AC97C channel A */ |
366 | switch (runtime->channels) { | 383 | switch (runtime->channels) { |
367 | case 1: | 384 | case 1: |
@@ -374,7 +391,6 @@ static int atmel_ac97c_capture_prepare(struct snd_pcm_substream *substream) | |||
374 | default: | 391 | default: |
375 | /* TODO: support more than two channels */ | 392 | /* TODO: support more than two channels */ |
376 | return -EINVAL; | 393 | return -EINVAL; |
377 | break; | ||
378 | } | 394 | } |
379 | ac97c_writel(chip, ICA, word); | 395 | ac97c_writel(chip, ICA, word); |
380 | 396 | ||
@@ -386,13 +402,25 @@ static int atmel_ac97c_capture_prepare(struct snd_pcm_substream *substream) | |||
386 | word |= AC97C_CMR_CEM_LITTLE; | 402 | word |= AC97C_CMR_CEM_LITTLE; |
387 | break; | 403 | break; |
388 | case SNDRV_PCM_FORMAT_S16_BE: /* fall through */ | 404 | case SNDRV_PCM_FORMAT_S16_BE: /* fall through */ |
389 | default: | ||
390 | word &= ~(AC97C_CMR_CEM_LITTLE); | 405 | word &= ~(AC97C_CMR_CEM_LITTLE); |
391 | break; | 406 | break; |
407 | default: | ||
408 | word = ac97c_readl(chip, ICA); | ||
409 | word &= ~(AC97C_CH_MASK(PCM_LEFT) | AC97C_CH_MASK(PCM_RIGHT)); | ||
410 | ac97c_writel(chip, ICA, word); | ||
411 | return -EINVAL; | ||
392 | } | 412 | } |
393 | 413 | ||
414 | /* Enable overrun interrupt on channel A */ | ||
415 | word |= AC97C_CSR_OVRUN; | ||
416 | |||
394 | ac97c_writel(chip, CAMR, word); | 417 | ac97c_writel(chip, CAMR, word); |
395 | 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 | |||
396 | /* set variable rate if needed */ | 424 | /* set variable rate if needed */ |
397 | if (runtime->rate != 48000) { | 425 | if (runtime->rate != 48000) { |
398 | word = ac97c_readl(chip, MR); | 426 | word = ac97c_readl(chip, MR); |
@@ -543,6 +571,43 @@ static struct snd_pcm_ops atmel_ac97_capture_ops = { | |||
543 | .pointer = atmel_ac97c_capture_pointer, | 571 | .pointer = atmel_ac97c_capture_pointer, |
544 | }; | 572 | }; |
545 | 573 | ||
574 | static 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 | |||
546 | static int __devinit atmel_ac97c_pcm_new(struct atmel_ac97c *chip) | 611 | static int __devinit atmel_ac97c_pcm_new(struct atmel_ac97c *chip) |
547 | { | 612 | { |
548 | struct snd_pcm *pcm; | 613 | struct snd_pcm *pcm; |
@@ -665,17 +730,17 @@ static bool filter(struct dma_chan *chan, void *slave) | |||
665 | 730 | ||
666 | static void atmel_ac97c_reset(struct atmel_ac97c *chip) | 731 | static void atmel_ac97c_reset(struct atmel_ac97c *chip) |
667 | { | 732 | { |
668 | ac97c_writel(chip, MR, AC97C_MR_WRST); | 733 | ac97c_writel(chip, MR, 0); |
734 | ac97c_writel(chip, MR, AC97C_MR_ENA); | ||
735 | ac97c_writel(chip, CAMR, 0); | ||
736 | ac97c_writel(chip, COMR, 0); | ||
669 | 737 | ||
670 | if (gpio_is_valid(chip->reset_pin)) { | 738 | if (gpio_is_valid(chip->reset_pin)) { |
671 | gpio_set_value(chip->reset_pin, 0); | 739 | gpio_set_value(chip->reset_pin, 0); |
672 | /* AC97 v2.2 specifications says minimum 1 us. */ | 740 | /* AC97 v2.2 specifications says minimum 1 us. */ |
673 | udelay(10); | 741 | udelay(2); |
674 | gpio_set_value(chip->reset_pin, 1); | 742 | gpio_set_value(chip->reset_pin, 1); |
675 | } | 743 | } |
676 | |||
677 | udelay(1); | ||
678 | ac97c_writel(chip, MR, AC97C_MR_ENA); | ||
679 | } | 744 | } |
680 | 745 | ||
681 | static int __devinit atmel_ac97c_probe(struct platform_device *pdev) | 746 | static int __devinit atmel_ac97c_probe(struct platform_device *pdev) |
@@ -690,6 +755,7 @@ static int __devinit atmel_ac97c_probe(struct platform_device *pdev) | |||
690 | .read = atmel_ac97c_read, | 755 | .read = atmel_ac97c_read, |
691 | }; | 756 | }; |
692 | int retval; | 757 | int retval; |
758 | int irq; | ||
693 | 759 | ||
694 | regs = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 760 | regs = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
695 | if (!regs) { | 761 | if (!regs) { |
@@ -703,6 +769,12 @@ static int __devinit atmel_ac97c_probe(struct platform_device *pdev) | |||
703 | return -ENXIO; | 769 | return -ENXIO; |
704 | } | 770 | } |
705 | 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 | |||
706 | pclk = clk_get(&pdev->dev, "pclk"); | 778 | pclk = clk_get(&pdev->dev, "pclk"); |
707 | if (IS_ERR(pclk)) { | 779 | if (IS_ERR(pclk)) { |
708 | dev_dbg(&pdev->dev, "no peripheral clock\n"); | 780 | dev_dbg(&pdev->dev, "no peripheral clock\n"); |
@@ -719,6 +791,13 @@ static int __devinit atmel_ac97c_probe(struct platform_device *pdev) | |||
719 | 791 | ||
720 | chip = get_chip(card); | 792 | chip = get_chip(card); |
721 | 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 | |||
722 | spin_lock_init(&chip->lock); | 801 | spin_lock_init(&chip->lock); |
723 | 802 | ||
724 | strcpy(card->driver, "Atmel AC97C"); | 803 | strcpy(card->driver, "Atmel AC97C"); |
@@ -747,14 +826,18 @@ static int __devinit atmel_ac97c_probe(struct platform_device *pdev) | |||
747 | 826 | ||
748 | snd_card_set_dev(card, &pdev->dev); | 827 | snd_card_set_dev(card, &pdev->dev); |
749 | 828 | ||
829 | atmel_ac97c_reset(chip); | ||
830 | |||
831 | /* Enable overrun interrupt from codec channel */ | ||
832 | ac97c_writel(chip, COMR, AC97C_CSR_OVRUN); | ||
833 | ac97c_writel(chip, IER, ac97c_readl(chip, IMR) | AC97C_SR_COEVT); | ||
834 | |||
750 | retval = snd_ac97_bus(card, 0, &ops, chip, &chip->ac97_bus); | 835 | retval = snd_ac97_bus(card, 0, &ops, chip, &chip->ac97_bus); |
751 | if (retval) { | 836 | if (retval) { |
752 | dev_dbg(&pdev->dev, "could not register on ac97 bus\n"); | 837 | dev_dbg(&pdev->dev, "could not register on ac97 bus\n"); |
753 | goto err_ac97_bus; | 838 | goto err_ac97_bus; |
754 | } | 839 | } |
755 | 840 | ||
756 | atmel_ac97c_reset(chip); | ||
757 | |||
758 | retval = atmel_ac97c_mixer_new(chip); | 841 | retval = atmel_ac97c_mixer_new(chip); |
759 | if (retval) { | 842 | if (retval) { |
760 | dev_dbg(&pdev->dev, "could not register ac97 mixer\n"); | 843 | dev_dbg(&pdev->dev, "could not register ac97 mixer\n"); |
@@ -773,7 +856,7 @@ static int __devinit atmel_ac97c_probe(struct platform_device *pdev) | |||
773 | chip->dma.rx_chan = dma_request_channel(mask, filter, dws); | 856 | chip->dma.rx_chan = dma_request_channel(mask, filter, dws); |
774 | 857 | ||
775 | dev_info(&chip->pdev->dev, "using %s for DMA RX\n", | 858 | dev_info(&chip->pdev->dev, "using %s for DMA RX\n", |
776 | chip->dma.rx_chan->dev->device.bus_id); | 859 | dev_name(&chip->dma.rx_chan->dev->device)); |
777 | set_bit(DMA_RX_CHAN_PRESENT, &chip->flags); | 860 | set_bit(DMA_RX_CHAN_PRESENT, &chip->flags); |
778 | } | 861 | } |
779 | 862 | ||
@@ -789,7 +872,7 @@ static int __devinit atmel_ac97c_probe(struct platform_device *pdev) | |||
789 | chip->dma.tx_chan = dma_request_channel(mask, filter, dws); | 872 | chip->dma.tx_chan = dma_request_channel(mask, filter, dws); |
790 | 873 | ||
791 | dev_info(&chip->pdev->dev, "using %s for DMA TX\n", | 874 | dev_info(&chip->pdev->dev, "using %s for DMA TX\n", |
792 | chip->dma.tx_chan->dev->device.bus_id); | 875 | dev_name(&chip->dma.tx_chan->dev->device)); |
793 | set_bit(DMA_TX_CHAN_PRESENT, &chip->flags); | 876 | set_bit(DMA_TX_CHAN_PRESENT, &chip->flags); |
794 | } | 877 | } |
795 | 878 | ||
@@ -809,7 +892,7 @@ static int __devinit atmel_ac97c_probe(struct platform_device *pdev) | |||
809 | retval = snd_card_register(card); | 892 | retval = snd_card_register(card); |
810 | if (retval) { | 893 | if (retval) { |
811 | dev_dbg(&pdev->dev, "could not register sound card\n"); | 894 | dev_dbg(&pdev->dev, "could not register sound card\n"); |
812 | goto err_ac97_bus; | 895 | goto err_dma; |
813 | } | 896 | } |
814 | 897 | ||
815 | platform_set_drvdata(pdev, card); | 898 | platform_set_drvdata(pdev, card); |
@@ -836,6 +919,8 @@ err_ac97_bus: | |||
836 | 919 | ||
837 | iounmap(chip->regs); | 920 | iounmap(chip->regs); |
838 | err_ioremap: | 921 | err_ioremap: |
922 | free_irq(irq, chip); | ||
923 | err_request_irq: | ||
839 | snd_card_free(card); | 924 | snd_card_free(card); |
840 | err_snd_card_new: | 925 | err_snd_card_new: |
841 | clk_disable(pclk); | 926 | clk_disable(pclk); |
@@ -884,9 +969,14 @@ static int __devexit atmel_ac97c_remove(struct platform_device *pdev) | |||
884 | if (gpio_is_valid(chip->reset_pin)) | 969 | if (gpio_is_valid(chip->reset_pin)) |
885 | gpio_free(chip->reset_pin); | 970 | gpio_free(chip->reset_pin); |
886 | 971 | ||
972 | ac97c_writel(chip, CAMR, 0); | ||
973 | ac97c_writel(chip, COMR, 0); | ||
974 | ac97c_writel(chip, MR, 0); | ||
975 | |||
887 | clk_disable(chip->pclk); | 976 | clk_disable(chip->pclk); |
888 | clk_put(chip->pclk); | 977 | clk_put(chip->pclk); |
889 | iounmap(chip->regs); | 978 | iounmap(chip->regs); |
979 | free_irq(chip->irq, chip); | ||
890 | 980 | ||
891 | if (test_bit(DMA_RX_CHAN_PRESENT, &chip->flags)) | 981 | if (test_bit(DMA_RX_CHAN_PRESENT, &chip->flags)) |
892 | dma_release_channel(chip->dma.rx_chan); | 982 | dma_release_channel(chip->dma.rx_chan); |