Loading sound/atmel/abdac.c +2 −2 Original line number Original line Diff line number Diff line Loading @@ -165,7 +165,7 @@ static struct snd_pcm_hardware atmel_abdac_hw = { .buffer_bytes_max = 64 * 4096, .buffer_bytes_max = 64 * 4096, .period_bytes_min = 4096, .period_bytes_min = 4096, .period_bytes_max = 4096, .period_bytes_max = 4096, .periods_min = 4, .periods_min = 6, .periods_max = 64, .periods_max = 64, }; }; Loading Loading @@ -502,7 +502,7 @@ static int __devinit atmel_abdac_probe(struct platform_device *pdev) platform_set_drvdata(pdev, card); platform_set_drvdata(pdev, card); dev_info(&pdev->dev, "Atmel ABDAC at 0x%p using %s\n", dev_info(&pdev->dev, "Atmel ABDAC at 0x%p using %s\n", dac->regs, dac->dma.chan->dev->device.bus_id); dac->regs, dev_name(&dac->dma.chan->dev->device)); return retval; return retval; Loading sound/atmel/ac97c.c +109 −19 Original line number Original line Diff line number Diff line /* /* * Driver for the Atmel AC97C controller * Driver for Atmel AC97C * * * Copyright (C) 2005-2009 Atmel Corporation * Copyright (C) 2005-2009 Atmel Corporation * * Loading @@ -10,6 +10,7 @@ #include <linux/clk.h> #include <linux/clk.h> #include <linux/delay.h> #include <linux/delay.h> #include <linux/bitmap.h> #include <linux/bitmap.h> #include <linux/device.h> #include <linux/dmaengine.h> #include <linux/dmaengine.h> #include <linux/dma-mapping.h> #include <linux/dma-mapping.h> #include <linux/init.h> #include <linux/init.h> Loading Loading @@ -65,6 +66,7 @@ struct atmel_ac97c { /* Serialize access to opened variable */ /* Serialize access to opened variable */ spinlock_t lock; spinlock_t lock; void __iomem *regs; void __iomem *regs; int irq; int opened; int opened; int reset_pin; int reset_pin; }; }; Loading Loading @@ -150,10 +152,10 @@ static struct snd_pcm_hardware atmel_ac97c_hw = { .rate_max = 48000, .rate_max = 48000, .channels_min = 1, .channels_min = 1, .channels_max = 2, .channels_max = 2, .buffer_bytes_max = 64 * 4096, .buffer_bytes_max = 2 * 2 * 64 * 2048, .period_bytes_min = 4096, .period_bytes_min = 4096, .period_bytes_max = 4096, .period_bytes_max = 4096, .periods_min = 4, .periods_min = 6, .periods_max = 64, .periods_max = 64, }; }; Loading Loading @@ -297,9 +299,11 @@ static int atmel_ac97c_playback_prepare(struct snd_pcm_substream *substream) { { struct atmel_ac97c *chip = snd_pcm_substream_chip(substream); struct atmel_ac97c *chip = snd_pcm_substream_chip(substream); struct snd_pcm_runtime *runtime = substream->runtime; struct snd_pcm_runtime *runtime = substream->runtime; unsigned long word = 0; unsigned long word = ac97c_readl(chip, OCA); int retval; int retval; word &= ~(AC97C_CH_MASK(PCM_LEFT) | AC97C_CH_MASK(PCM_RIGHT)); /* assign channels to AC97C channel A */ /* assign channels to AC97C channel A */ switch (runtime->channels) { switch (runtime->channels) { case 1: case 1: Loading @@ -312,7 +316,6 @@ static int atmel_ac97c_playback_prepare(struct snd_pcm_substream *substream) default: default: /* TODO: support more than two channels */ /* TODO: support more than two channels */ return -EINVAL; return -EINVAL; break; } } ac97c_writel(chip, OCA, word); ac97c_writel(chip, OCA, word); Loading @@ -324,13 +327,25 @@ static int atmel_ac97c_playback_prepare(struct snd_pcm_substream *substream) word |= AC97C_CMR_CEM_LITTLE; word |= AC97C_CMR_CEM_LITTLE; break; break; case SNDRV_PCM_FORMAT_S16_BE: /* fall through */ case SNDRV_PCM_FORMAT_S16_BE: /* fall through */ default: word &= ~(AC97C_CMR_CEM_LITTLE); word &= ~(AC97C_CMR_CEM_LITTLE); break; break; default: word = ac97c_readl(chip, OCA); word &= ~(AC97C_CH_MASK(PCM_LEFT) | AC97C_CH_MASK(PCM_RIGHT)); ac97c_writel(chip, OCA, word); return -EINVAL; } } /* Enable underrun interrupt on channel A */ word |= AC97C_CSR_UNRUN; ac97c_writel(chip, CAMR, word); ac97c_writel(chip, CAMR, word); /* Enable channel A event interrupt */ word = ac97c_readl(chip, IMR); word |= AC97C_SR_CAEVT; ac97c_writel(chip, IER, word); /* set variable rate if needed */ /* set variable rate if needed */ if (runtime->rate != 48000) { if (runtime->rate != 48000) { word = ac97c_readl(chip, MR); word = ac97c_readl(chip, MR); Loading Loading @@ -359,9 +374,11 @@ static int atmel_ac97c_capture_prepare(struct snd_pcm_substream *substream) { { struct atmel_ac97c *chip = snd_pcm_substream_chip(substream); struct atmel_ac97c *chip = snd_pcm_substream_chip(substream); struct snd_pcm_runtime *runtime = substream->runtime; struct snd_pcm_runtime *runtime = substream->runtime; unsigned long word = 0; unsigned long word = ac97c_readl(chip, ICA); int retval; int retval; word &= ~(AC97C_CH_MASK(PCM_LEFT) | AC97C_CH_MASK(PCM_RIGHT)); /* assign channels to AC97C channel A */ /* assign channels to AC97C channel A */ switch (runtime->channels) { switch (runtime->channels) { case 1: case 1: Loading @@ -374,7 +391,6 @@ static int atmel_ac97c_capture_prepare(struct snd_pcm_substream *substream) default: default: /* TODO: support more than two channels */ /* TODO: support more than two channels */ return -EINVAL; return -EINVAL; break; } } ac97c_writel(chip, ICA, word); ac97c_writel(chip, ICA, word); Loading @@ -386,13 +402,25 @@ static int atmel_ac97c_capture_prepare(struct snd_pcm_substream *substream) word |= AC97C_CMR_CEM_LITTLE; word |= AC97C_CMR_CEM_LITTLE; break; break; case SNDRV_PCM_FORMAT_S16_BE: /* fall through */ case SNDRV_PCM_FORMAT_S16_BE: /* fall through */ default: word &= ~(AC97C_CMR_CEM_LITTLE); word &= ~(AC97C_CMR_CEM_LITTLE); break; break; default: word = ac97c_readl(chip, ICA); word &= ~(AC97C_CH_MASK(PCM_LEFT) | AC97C_CH_MASK(PCM_RIGHT)); ac97c_writel(chip, ICA, word); return -EINVAL; } } /* Enable overrun interrupt on channel A */ word |= AC97C_CSR_OVRUN; ac97c_writel(chip, CAMR, word); ac97c_writel(chip, CAMR, word); /* Enable channel A event interrupt */ word = ac97c_readl(chip, IMR); word |= AC97C_SR_CAEVT; ac97c_writel(chip, IER, word); /* set variable rate if needed */ /* set variable rate if needed */ if (runtime->rate != 48000) { if (runtime->rate != 48000) { word = ac97c_readl(chip, MR); word = ac97c_readl(chip, MR); Loading Loading @@ -543,6 +571,43 @@ static struct snd_pcm_ops atmel_ac97_capture_ops = { .pointer = atmel_ac97c_capture_pointer, .pointer = atmel_ac97c_capture_pointer, }; }; static irqreturn_t atmel_ac97c_interrupt(int irq, void *dev) { struct atmel_ac97c *chip = (struct atmel_ac97c *)dev; irqreturn_t retval = IRQ_NONE; u32 sr = ac97c_readl(chip, SR); u32 casr = ac97c_readl(chip, CASR); u32 cosr = ac97c_readl(chip, COSR); if (sr & AC97C_SR_CAEVT) { dev_info(&chip->pdev->dev, "channel A event%s%s%s%s%s%s\n", casr & AC97C_CSR_OVRUN ? " OVRUN" : "", casr & AC97C_CSR_RXRDY ? " RXRDY" : "", casr & AC97C_CSR_UNRUN ? " UNRUN" : "", casr & AC97C_CSR_TXEMPTY ? " TXEMPTY" : "", casr & AC97C_CSR_TXRDY ? " TXRDY" : "", !casr ? " NONE" : ""); retval = IRQ_HANDLED; } if (sr & AC97C_SR_COEVT) { dev_info(&chip->pdev->dev, "codec channel event%s%s%s%s%s\n", cosr & AC97C_CSR_OVRUN ? " OVRUN" : "", cosr & AC97C_CSR_RXRDY ? " RXRDY" : "", cosr & AC97C_CSR_TXEMPTY ? " TXEMPTY" : "", cosr & AC97C_CSR_TXRDY ? " TXRDY" : "", !cosr ? " NONE" : ""); retval = IRQ_HANDLED; } if (retval == IRQ_NONE) { dev_err(&chip->pdev->dev, "spurious interrupt sr 0x%08x " "casr 0x%08x cosr 0x%08x\n", sr, casr, cosr); } return retval; } static int __devinit atmel_ac97c_pcm_new(struct atmel_ac97c *chip) static int __devinit atmel_ac97c_pcm_new(struct atmel_ac97c *chip) { { struct snd_pcm *pcm; struct snd_pcm *pcm; Loading Loading @@ -665,17 +730,17 @@ static bool filter(struct dma_chan *chan, void *slave) static void atmel_ac97c_reset(struct atmel_ac97c *chip) static void atmel_ac97c_reset(struct atmel_ac97c *chip) { { ac97c_writel(chip, MR, AC97C_MR_WRST); ac97c_writel(chip, MR, 0); ac97c_writel(chip, MR, AC97C_MR_ENA); ac97c_writel(chip, CAMR, 0); ac97c_writel(chip, COMR, 0); if (gpio_is_valid(chip->reset_pin)) { if (gpio_is_valid(chip->reset_pin)) { gpio_set_value(chip->reset_pin, 0); gpio_set_value(chip->reset_pin, 0); /* AC97 v2.2 specifications says minimum 1 us. */ /* AC97 v2.2 specifications says minimum 1 us. */ udelay(10); udelay(2); gpio_set_value(chip->reset_pin, 1); gpio_set_value(chip->reset_pin, 1); } } udelay(1); ac97c_writel(chip, MR, AC97C_MR_ENA); } } static int __devinit atmel_ac97c_probe(struct platform_device *pdev) static int __devinit atmel_ac97c_probe(struct platform_device *pdev) Loading @@ -690,6 +755,7 @@ static int __devinit atmel_ac97c_probe(struct platform_device *pdev) .read = atmel_ac97c_read, .read = atmel_ac97c_read, }; }; int retval; int retval; int irq; regs = platform_get_resource(pdev, IORESOURCE_MEM, 0); regs = platform_get_resource(pdev, IORESOURCE_MEM, 0); if (!regs) { if (!regs) { Loading @@ -703,6 +769,12 @@ static int __devinit atmel_ac97c_probe(struct platform_device *pdev) return -ENXIO; return -ENXIO; } } irq = platform_get_irq(pdev, 0); if (irq < 0) { dev_dbg(&pdev->dev, "could not get irq\n"); return -ENXIO; } pclk = clk_get(&pdev->dev, "pclk"); pclk = clk_get(&pdev->dev, "pclk"); if (IS_ERR(pclk)) { if (IS_ERR(pclk)) { dev_dbg(&pdev->dev, "no peripheral clock\n"); dev_dbg(&pdev->dev, "no peripheral clock\n"); Loading @@ -719,6 +791,13 @@ static int __devinit atmel_ac97c_probe(struct platform_device *pdev) chip = get_chip(card); chip = get_chip(card); retval = request_irq(irq, atmel_ac97c_interrupt, 0, "AC97C", chip); if (retval) { dev_dbg(&pdev->dev, "unable to request irq %d\n", irq); goto err_request_irq; } chip->irq = irq; spin_lock_init(&chip->lock); spin_lock_init(&chip->lock); strcpy(card->driver, "Atmel AC97C"); strcpy(card->driver, "Atmel AC97C"); Loading Loading @@ -747,14 +826,18 @@ static int __devinit atmel_ac97c_probe(struct platform_device *pdev) snd_card_set_dev(card, &pdev->dev); snd_card_set_dev(card, &pdev->dev); atmel_ac97c_reset(chip); /* Enable overrun interrupt from codec channel */ ac97c_writel(chip, COMR, AC97C_CSR_OVRUN); ac97c_writel(chip, IER, ac97c_readl(chip, IMR) | AC97C_SR_COEVT); retval = snd_ac97_bus(card, 0, &ops, chip, &chip->ac97_bus); retval = snd_ac97_bus(card, 0, &ops, chip, &chip->ac97_bus); if (retval) { if (retval) { dev_dbg(&pdev->dev, "could not register on ac97 bus\n"); dev_dbg(&pdev->dev, "could not register on ac97 bus\n"); goto err_ac97_bus; goto err_ac97_bus; } } atmel_ac97c_reset(chip); retval = atmel_ac97c_mixer_new(chip); retval = atmel_ac97c_mixer_new(chip); if (retval) { if (retval) { dev_dbg(&pdev->dev, "could not register ac97 mixer\n"); dev_dbg(&pdev->dev, "could not register ac97 mixer\n"); Loading @@ -773,7 +856,7 @@ static int __devinit atmel_ac97c_probe(struct platform_device *pdev) chip->dma.rx_chan = dma_request_channel(mask, filter, dws); chip->dma.rx_chan = dma_request_channel(mask, filter, dws); dev_info(&chip->pdev->dev, "using %s for DMA RX\n", dev_info(&chip->pdev->dev, "using %s for DMA RX\n", chip->dma.rx_chan->dev->device.bus_id); dev_name(&chip->dma.rx_chan->dev->device)); set_bit(DMA_RX_CHAN_PRESENT, &chip->flags); set_bit(DMA_RX_CHAN_PRESENT, &chip->flags); } } Loading @@ -789,7 +872,7 @@ static int __devinit atmel_ac97c_probe(struct platform_device *pdev) chip->dma.tx_chan = dma_request_channel(mask, filter, dws); chip->dma.tx_chan = dma_request_channel(mask, filter, dws); dev_info(&chip->pdev->dev, "using %s for DMA TX\n", dev_info(&chip->pdev->dev, "using %s for DMA TX\n", chip->dma.tx_chan->dev->device.bus_id); dev_name(&chip->dma.tx_chan->dev->device)); set_bit(DMA_TX_CHAN_PRESENT, &chip->flags); set_bit(DMA_TX_CHAN_PRESENT, &chip->flags); } } Loading @@ -809,7 +892,7 @@ static int __devinit atmel_ac97c_probe(struct platform_device *pdev) retval = snd_card_register(card); retval = snd_card_register(card); if (retval) { if (retval) { dev_dbg(&pdev->dev, "could not register sound card\n"); dev_dbg(&pdev->dev, "could not register sound card\n"); goto err_ac97_bus; goto err_dma; } } platform_set_drvdata(pdev, card); platform_set_drvdata(pdev, card); Loading @@ -836,6 +919,8 @@ static int __devinit atmel_ac97c_probe(struct platform_device *pdev) iounmap(chip->regs); iounmap(chip->regs); err_ioremap: err_ioremap: free_irq(irq, chip); err_request_irq: snd_card_free(card); snd_card_free(card); err_snd_card_new: err_snd_card_new: clk_disable(pclk); clk_disable(pclk); Loading Loading @@ -884,9 +969,14 @@ static int __devexit atmel_ac97c_remove(struct platform_device *pdev) if (gpio_is_valid(chip->reset_pin)) if (gpio_is_valid(chip->reset_pin)) gpio_free(chip->reset_pin); gpio_free(chip->reset_pin); ac97c_writel(chip, CAMR, 0); ac97c_writel(chip, COMR, 0); ac97c_writel(chip, MR, 0); clk_disable(chip->pclk); clk_disable(chip->pclk); clk_put(chip->pclk); clk_put(chip->pclk); iounmap(chip->regs); iounmap(chip->regs); free_irq(chip->irq, chip); if (test_bit(DMA_RX_CHAN_PRESENT, &chip->flags)) if (test_bit(DMA_RX_CHAN_PRESENT, &chip->flags)) dma_release_channel(chip->dma.rx_chan); dma_release_channel(chip->dma.rx_chan); Loading sound/atmel/ac97c.h +8 −6 Original line number Original line Diff line number Diff line /* /* * Register definitions for the Atmel AC97C controller * Register definitions for Atmel AC97C * * * Copyright (C) 2005-2009 Atmel Corporation * Copyright (C) 2005-2009 Atmel Corporation * * Loading @@ -17,10 +17,6 @@ #define AC97C_CATHR 0x24 #define AC97C_CATHR 0x24 #define AC97C_CASR 0x28 #define AC97C_CASR 0x28 #define AC97C_CAMR 0x2c #define AC97C_CAMR 0x2c #define AC97C_CBRHR 0x30 #define AC97C_CBTHR 0x34 #define AC97C_CBSR 0x38 #define AC97C_CBMR 0x3c #define AC97C_CORHR 0x40 #define AC97C_CORHR 0x40 #define AC97C_COTHR 0x44 #define AC97C_COTHR 0x44 #define AC97C_COSR 0x48 #define AC97C_COSR 0x48 Loading @@ -46,8 +42,10 @@ #define AC97C_MR_VRA (1 << 2) #define AC97C_MR_VRA (1 << 2) #define AC97C_CSR_TXRDY (1 << 0) #define AC97C_CSR_TXRDY (1 << 0) #define AC97C_CSR_TXEMPTY (1 << 1) #define AC97C_CSR_UNRUN (1 << 2) #define AC97C_CSR_UNRUN (1 << 2) #define AC97C_CSR_RXRDY (1 << 4) #define AC97C_CSR_RXRDY (1 << 4) #define AC97C_CSR_OVRUN (1 << 5) #define AC97C_CSR_ENDTX (1 << 10) #define AC97C_CSR_ENDTX (1 << 10) #define AC97C_CSR_ENDRX (1 << 14) #define AC97C_CSR_ENDRX (1 << 14) Loading @@ -61,11 +59,15 @@ #define AC97C_CMR_DMAEN (1 << 22) #define AC97C_CMR_DMAEN (1 << 22) #define AC97C_SR_CAEVT (1 << 3) #define AC97C_SR_CAEVT (1 << 3) #define AC97C_SR_COEVT (1 << 2) #define AC97C_SR_WKUP (1 << 1) #define AC97C_SR_SOF (1 << 0) #define AC97C_CH_MASK(slot) \ (0x7 << (3 * (AC97_SLOT_##slot - 3))) #define AC97C_CH_ASSIGN(slot, channel) \ #define AC97C_CH_ASSIGN(slot, channel) \ (AC97C_CHANNEL_##channel << (3 * (AC97_SLOT_##slot - 3))) (AC97C_CHANNEL_##channel << (3 * (AC97_SLOT_##slot - 3))) #define AC97C_CHANNEL_NONE 0x0 #define AC97C_CHANNEL_NONE 0x0 #define AC97C_CHANNEL_A 0x1 #define AC97C_CHANNEL_A 0x1 #define AC97C_CHANNEL_B 0x2 #endif /* __SOUND_ATMEL_AC97C_H */ #endif /* __SOUND_ATMEL_AC97C_H */ Loading
sound/atmel/abdac.c +2 −2 Original line number Original line Diff line number Diff line Loading @@ -165,7 +165,7 @@ static struct snd_pcm_hardware atmel_abdac_hw = { .buffer_bytes_max = 64 * 4096, .buffer_bytes_max = 64 * 4096, .period_bytes_min = 4096, .period_bytes_min = 4096, .period_bytes_max = 4096, .period_bytes_max = 4096, .periods_min = 4, .periods_min = 6, .periods_max = 64, .periods_max = 64, }; }; Loading Loading @@ -502,7 +502,7 @@ static int __devinit atmel_abdac_probe(struct platform_device *pdev) platform_set_drvdata(pdev, card); platform_set_drvdata(pdev, card); dev_info(&pdev->dev, "Atmel ABDAC at 0x%p using %s\n", dev_info(&pdev->dev, "Atmel ABDAC at 0x%p using %s\n", dac->regs, dac->dma.chan->dev->device.bus_id); dac->regs, dev_name(&dac->dma.chan->dev->device)); return retval; return retval; Loading
sound/atmel/ac97c.c +109 −19 Original line number Original line Diff line number Diff line /* /* * Driver for the Atmel AC97C controller * Driver for Atmel AC97C * * * Copyright (C) 2005-2009 Atmel Corporation * Copyright (C) 2005-2009 Atmel Corporation * * Loading @@ -10,6 +10,7 @@ #include <linux/clk.h> #include <linux/clk.h> #include <linux/delay.h> #include <linux/delay.h> #include <linux/bitmap.h> #include <linux/bitmap.h> #include <linux/device.h> #include <linux/dmaengine.h> #include <linux/dmaengine.h> #include <linux/dma-mapping.h> #include <linux/dma-mapping.h> #include <linux/init.h> #include <linux/init.h> Loading Loading @@ -65,6 +66,7 @@ struct atmel_ac97c { /* Serialize access to opened variable */ /* Serialize access to opened variable */ spinlock_t lock; spinlock_t lock; void __iomem *regs; void __iomem *regs; int irq; int opened; int opened; int reset_pin; int reset_pin; }; }; Loading Loading @@ -150,10 +152,10 @@ static struct snd_pcm_hardware atmel_ac97c_hw = { .rate_max = 48000, .rate_max = 48000, .channels_min = 1, .channels_min = 1, .channels_max = 2, .channels_max = 2, .buffer_bytes_max = 64 * 4096, .buffer_bytes_max = 2 * 2 * 64 * 2048, .period_bytes_min = 4096, .period_bytes_min = 4096, .period_bytes_max = 4096, .period_bytes_max = 4096, .periods_min = 4, .periods_min = 6, .periods_max = 64, .periods_max = 64, }; }; Loading Loading @@ -297,9 +299,11 @@ static int atmel_ac97c_playback_prepare(struct snd_pcm_substream *substream) { { struct atmel_ac97c *chip = snd_pcm_substream_chip(substream); struct atmel_ac97c *chip = snd_pcm_substream_chip(substream); struct snd_pcm_runtime *runtime = substream->runtime; struct snd_pcm_runtime *runtime = substream->runtime; unsigned long word = 0; unsigned long word = ac97c_readl(chip, OCA); int retval; int retval; word &= ~(AC97C_CH_MASK(PCM_LEFT) | AC97C_CH_MASK(PCM_RIGHT)); /* assign channels to AC97C channel A */ /* assign channels to AC97C channel A */ switch (runtime->channels) { switch (runtime->channels) { case 1: case 1: Loading @@ -312,7 +316,6 @@ static int atmel_ac97c_playback_prepare(struct snd_pcm_substream *substream) default: default: /* TODO: support more than two channels */ /* TODO: support more than two channels */ return -EINVAL; return -EINVAL; break; } } ac97c_writel(chip, OCA, word); ac97c_writel(chip, OCA, word); Loading @@ -324,13 +327,25 @@ static int atmel_ac97c_playback_prepare(struct snd_pcm_substream *substream) word |= AC97C_CMR_CEM_LITTLE; word |= AC97C_CMR_CEM_LITTLE; break; break; case SNDRV_PCM_FORMAT_S16_BE: /* fall through */ case SNDRV_PCM_FORMAT_S16_BE: /* fall through */ default: word &= ~(AC97C_CMR_CEM_LITTLE); word &= ~(AC97C_CMR_CEM_LITTLE); break; break; default: word = ac97c_readl(chip, OCA); word &= ~(AC97C_CH_MASK(PCM_LEFT) | AC97C_CH_MASK(PCM_RIGHT)); ac97c_writel(chip, OCA, word); return -EINVAL; } } /* Enable underrun interrupt on channel A */ word |= AC97C_CSR_UNRUN; ac97c_writel(chip, CAMR, word); ac97c_writel(chip, CAMR, word); /* Enable channel A event interrupt */ word = ac97c_readl(chip, IMR); word |= AC97C_SR_CAEVT; ac97c_writel(chip, IER, word); /* set variable rate if needed */ /* set variable rate if needed */ if (runtime->rate != 48000) { if (runtime->rate != 48000) { word = ac97c_readl(chip, MR); word = ac97c_readl(chip, MR); Loading Loading @@ -359,9 +374,11 @@ static int atmel_ac97c_capture_prepare(struct snd_pcm_substream *substream) { { struct atmel_ac97c *chip = snd_pcm_substream_chip(substream); struct atmel_ac97c *chip = snd_pcm_substream_chip(substream); struct snd_pcm_runtime *runtime = substream->runtime; struct snd_pcm_runtime *runtime = substream->runtime; unsigned long word = 0; unsigned long word = ac97c_readl(chip, ICA); int retval; int retval; word &= ~(AC97C_CH_MASK(PCM_LEFT) | AC97C_CH_MASK(PCM_RIGHT)); /* assign channels to AC97C channel A */ /* assign channels to AC97C channel A */ switch (runtime->channels) { switch (runtime->channels) { case 1: case 1: Loading @@ -374,7 +391,6 @@ static int atmel_ac97c_capture_prepare(struct snd_pcm_substream *substream) default: default: /* TODO: support more than two channels */ /* TODO: support more than two channels */ return -EINVAL; return -EINVAL; break; } } ac97c_writel(chip, ICA, word); ac97c_writel(chip, ICA, word); Loading @@ -386,13 +402,25 @@ static int atmel_ac97c_capture_prepare(struct snd_pcm_substream *substream) word |= AC97C_CMR_CEM_LITTLE; word |= AC97C_CMR_CEM_LITTLE; break; break; case SNDRV_PCM_FORMAT_S16_BE: /* fall through */ case SNDRV_PCM_FORMAT_S16_BE: /* fall through */ default: word &= ~(AC97C_CMR_CEM_LITTLE); word &= ~(AC97C_CMR_CEM_LITTLE); break; break; default: word = ac97c_readl(chip, ICA); word &= ~(AC97C_CH_MASK(PCM_LEFT) | AC97C_CH_MASK(PCM_RIGHT)); ac97c_writel(chip, ICA, word); return -EINVAL; } } /* Enable overrun interrupt on channel A */ word |= AC97C_CSR_OVRUN; ac97c_writel(chip, CAMR, word); ac97c_writel(chip, CAMR, word); /* Enable channel A event interrupt */ word = ac97c_readl(chip, IMR); word |= AC97C_SR_CAEVT; ac97c_writel(chip, IER, word); /* set variable rate if needed */ /* set variable rate if needed */ if (runtime->rate != 48000) { if (runtime->rate != 48000) { word = ac97c_readl(chip, MR); word = ac97c_readl(chip, MR); Loading Loading @@ -543,6 +571,43 @@ static struct snd_pcm_ops atmel_ac97_capture_ops = { .pointer = atmel_ac97c_capture_pointer, .pointer = atmel_ac97c_capture_pointer, }; }; static irqreturn_t atmel_ac97c_interrupt(int irq, void *dev) { struct atmel_ac97c *chip = (struct atmel_ac97c *)dev; irqreturn_t retval = IRQ_NONE; u32 sr = ac97c_readl(chip, SR); u32 casr = ac97c_readl(chip, CASR); u32 cosr = ac97c_readl(chip, COSR); if (sr & AC97C_SR_CAEVT) { dev_info(&chip->pdev->dev, "channel A event%s%s%s%s%s%s\n", casr & AC97C_CSR_OVRUN ? " OVRUN" : "", casr & AC97C_CSR_RXRDY ? " RXRDY" : "", casr & AC97C_CSR_UNRUN ? " UNRUN" : "", casr & AC97C_CSR_TXEMPTY ? " TXEMPTY" : "", casr & AC97C_CSR_TXRDY ? " TXRDY" : "", !casr ? " NONE" : ""); retval = IRQ_HANDLED; } if (sr & AC97C_SR_COEVT) { dev_info(&chip->pdev->dev, "codec channel event%s%s%s%s%s\n", cosr & AC97C_CSR_OVRUN ? " OVRUN" : "", cosr & AC97C_CSR_RXRDY ? " RXRDY" : "", cosr & AC97C_CSR_TXEMPTY ? " TXEMPTY" : "", cosr & AC97C_CSR_TXRDY ? " TXRDY" : "", !cosr ? " NONE" : ""); retval = IRQ_HANDLED; } if (retval == IRQ_NONE) { dev_err(&chip->pdev->dev, "spurious interrupt sr 0x%08x " "casr 0x%08x cosr 0x%08x\n", sr, casr, cosr); } return retval; } static int __devinit atmel_ac97c_pcm_new(struct atmel_ac97c *chip) static int __devinit atmel_ac97c_pcm_new(struct atmel_ac97c *chip) { { struct snd_pcm *pcm; struct snd_pcm *pcm; Loading Loading @@ -665,17 +730,17 @@ static bool filter(struct dma_chan *chan, void *slave) static void atmel_ac97c_reset(struct atmel_ac97c *chip) static void atmel_ac97c_reset(struct atmel_ac97c *chip) { { ac97c_writel(chip, MR, AC97C_MR_WRST); ac97c_writel(chip, MR, 0); ac97c_writel(chip, MR, AC97C_MR_ENA); ac97c_writel(chip, CAMR, 0); ac97c_writel(chip, COMR, 0); if (gpio_is_valid(chip->reset_pin)) { if (gpio_is_valid(chip->reset_pin)) { gpio_set_value(chip->reset_pin, 0); gpio_set_value(chip->reset_pin, 0); /* AC97 v2.2 specifications says minimum 1 us. */ /* AC97 v2.2 specifications says minimum 1 us. */ udelay(10); udelay(2); gpio_set_value(chip->reset_pin, 1); gpio_set_value(chip->reset_pin, 1); } } udelay(1); ac97c_writel(chip, MR, AC97C_MR_ENA); } } static int __devinit atmel_ac97c_probe(struct platform_device *pdev) static int __devinit atmel_ac97c_probe(struct platform_device *pdev) Loading @@ -690,6 +755,7 @@ static int __devinit atmel_ac97c_probe(struct platform_device *pdev) .read = atmel_ac97c_read, .read = atmel_ac97c_read, }; }; int retval; int retval; int irq; regs = platform_get_resource(pdev, IORESOURCE_MEM, 0); regs = platform_get_resource(pdev, IORESOURCE_MEM, 0); if (!regs) { if (!regs) { Loading @@ -703,6 +769,12 @@ static int __devinit atmel_ac97c_probe(struct platform_device *pdev) return -ENXIO; return -ENXIO; } } irq = platform_get_irq(pdev, 0); if (irq < 0) { dev_dbg(&pdev->dev, "could not get irq\n"); return -ENXIO; } pclk = clk_get(&pdev->dev, "pclk"); pclk = clk_get(&pdev->dev, "pclk"); if (IS_ERR(pclk)) { if (IS_ERR(pclk)) { dev_dbg(&pdev->dev, "no peripheral clock\n"); dev_dbg(&pdev->dev, "no peripheral clock\n"); Loading @@ -719,6 +791,13 @@ static int __devinit atmel_ac97c_probe(struct platform_device *pdev) chip = get_chip(card); chip = get_chip(card); retval = request_irq(irq, atmel_ac97c_interrupt, 0, "AC97C", chip); if (retval) { dev_dbg(&pdev->dev, "unable to request irq %d\n", irq); goto err_request_irq; } chip->irq = irq; spin_lock_init(&chip->lock); spin_lock_init(&chip->lock); strcpy(card->driver, "Atmel AC97C"); strcpy(card->driver, "Atmel AC97C"); Loading Loading @@ -747,14 +826,18 @@ static int __devinit atmel_ac97c_probe(struct platform_device *pdev) snd_card_set_dev(card, &pdev->dev); snd_card_set_dev(card, &pdev->dev); atmel_ac97c_reset(chip); /* Enable overrun interrupt from codec channel */ ac97c_writel(chip, COMR, AC97C_CSR_OVRUN); ac97c_writel(chip, IER, ac97c_readl(chip, IMR) | AC97C_SR_COEVT); retval = snd_ac97_bus(card, 0, &ops, chip, &chip->ac97_bus); retval = snd_ac97_bus(card, 0, &ops, chip, &chip->ac97_bus); if (retval) { if (retval) { dev_dbg(&pdev->dev, "could not register on ac97 bus\n"); dev_dbg(&pdev->dev, "could not register on ac97 bus\n"); goto err_ac97_bus; goto err_ac97_bus; } } atmel_ac97c_reset(chip); retval = atmel_ac97c_mixer_new(chip); retval = atmel_ac97c_mixer_new(chip); if (retval) { if (retval) { dev_dbg(&pdev->dev, "could not register ac97 mixer\n"); dev_dbg(&pdev->dev, "could not register ac97 mixer\n"); Loading @@ -773,7 +856,7 @@ static int __devinit atmel_ac97c_probe(struct platform_device *pdev) chip->dma.rx_chan = dma_request_channel(mask, filter, dws); chip->dma.rx_chan = dma_request_channel(mask, filter, dws); dev_info(&chip->pdev->dev, "using %s for DMA RX\n", dev_info(&chip->pdev->dev, "using %s for DMA RX\n", chip->dma.rx_chan->dev->device.bus_id); dev_name(&chip->dma.rx_chan->dev->device)); set_bit(DMA_RX_CHAN_PRESENT, &chip->flags); set_bit(DMA_RX_CHAN_PRESENT, &chip->flags); } } Loading @@ -789,7 +872,7 @@ static int __devinit atmel_ac97c_probe(struct platform_device *pdev) chip->dma.tx_chan = dma_request_channel(mask, filter, dws); chip->dma.tx_chan = dma_request_channel(mask, filter, dws); dev_info(&chip->pdev->dev, "using %s for DMA TX\n", dev_info(&chip->pdev->dev, "using %s for DMA TX\n", chip->dma.tx_chan->dev->device.bus_id); dev_name(&chip->dma.tx_chan->dev->device)); set_bit(DMA_TX_CHAN_PRESENT, &chip->flags); set_bit(DMA_TX_CHAN_PRESENT, &chip->flags); } } Loading @@ -809,7 +892,7 @@ static int __devinit atmel_ac97c_probe(struct platform_device *pdev) retval = snd_card_register(card); retval = snd_card_register(card); if (retval) { if (retval) { dev_dbg(&pdev->dev, "could not register sound card\n"); dev_dbg(&pdev->dev, "could not register sound card\n"); goto err_ac97_bus; goto err_dma; } } platform_set_drvdata(pdev, card); platform_set_drvdata(pdev, card); Loading @@ -836,6 +919,8 @@ static int __devinit atmel_ac97c_probe(struct platform_device *pdev) iounmap(chip->regs); iounmap(chip->regs); err_ioremap: err_ioremap: free_irq(irq, chip); err_request_irq: snd_card_free(card); snd_card_free(card); err_snd_card_new: err_snd_card_new: clk_disable(pclk); clk_disable(pclk); Loading Loading @@ -884,9 +969,14 @@ static int __devexit atmel_ac97c_remove(struct platform_device *pdev) if (gpio_is_valid(chip->reset_pin)) if (gpio_is_valid(chip->reset_pin)) gpio_free(chip->reset_pin); gpio_free(chip->reset_pin); ac97c_writel(chip, CAMR, 0); ac97c_writel(chip, COMR, 0); ac97c_writel(chip, MR, 0); clk_disable(chip->pclk); clk_disable(chip->pclk); clk_put(chip->pclk); clk_put(chip->pclk); iounmap(chip->regs); iounmap(chip->regs); free_irq(chip->irq, chip); if (test_bit(DMA_RX_CHAN_PRESENT, &chip->flags)) if (test_bit(DMA_RX_CHAN_PRESENT, &chip->flags)) dma_release_channel(chip->dma.rx_chan); dma_release_channel(chip->dma.rx_chan); Loading
sound/atmel/ac97c.h +8 −6 Original line number Original line Diff line number Diff line /* /* * Register definitions for the Atmel AC97C controller * Register definitions for Atmel AC97C * * * Copyright (C) 2005-2009 Atmel Corporation * Copyright (C) 2005-2009 Atmel Corporation * * Loading @@ -17,10 +17,6 @@ #define AC97C_CATHR 0x24 #define AC97C_CATHR 0x24 #define AC97C_CASR 0x28 #define AC97C_CASR 0x28 #define AC97C_CAMR 0x2c #define AC97C_CAMR 0x2c #define AC97C_CBRHR 0x30 #define AC97C_CBTHR 0x34 #define AC97C_CBSR 0x38 #define AC97C_CBMR 0x3c #define AC97C_CORHR 0x40 #define AC97C_CORHR 0x40 #define AC97C_COTHR 0x44 #define AC97C_COTHR 0x44 #define AC97C_COSR 0x48 #define AC97C_COSR 0x48 Loading @@ -46,8 +42,10 @@ #define AC97C_MR_VRA (1 << 2) #define AC97C_MR_VRA (1 << 2) #define AC97C_CSR_TXRDY (1 << 0) #define AC97C_CSR_TXRDY (1 << 0) #define AC97C_CSR_TXEMPTY (1 << 1) #define AC97C_CSR_UNRUN (1 << 2) #define AC97C_CSR_UNRUN (1 << 2) #define AC97C_CSR_RXRDY (1 << 4) #define AC97C_CSR_RXRDY (1 << 4) #define AC97C_CSR_OVRUN (1 << 5) #define AC97C_CSR_ENDTX (1 << 10) #define AC97C_CSR_ENDTX (1 << 10) #define AC97C_CSR_ENDRX (1 << 14) #define AC97C_CSR_ENDRX (1 << 14) Loading @@ -61,11 +59,15 @@ #define AC97C_CMR_DMAEN (1 << 22) #define AC97C_CMR_DMAEN (1 << 22) #define AC97C_SR_CAEVT (1 << 3) #define AC97C_SR_CAEVT (1 << 3) #define AC97C_SR_COEVT (1 << 2) #define AC97C_SR_WKUP (1 << 1) #define AC97C_SR_SOF (1 << 0) #define AC97C_CH_MASK(slot) \ (0x7 << (3 * (AC97_SLOT_##slot - 3))) #define AC97C_CH_ASSIGN(slot, channel) \ #define AC97C_CH_ASSIGN(slot, channel) \ (AC97C_CHANNEL_##channel << (3 * (AC97_SLOT_##slot - 3))) (AC97C_CHANNEL_##channel << (3 * (AC97_SLOT_##slot - 3))) #define AC97C_CHANNEL_NONE 0x0 #define AC97C_CHANNEL_NONE 0x0 #define AC97C_CHANNEL_A 0x1 #define AC97C_CHANNEL_A 0x1 #define AC97C_CHANNEL_B 0x2 #endif /* __SOUND_ATMEL_AC97C_H */ #endif /* __SOUND_ATMEL_AC97C_H */