Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 142712
b: refs/heads/master
c: df16358
h: refs/heads/master
v: v3
  • Loading branch information
Hans-Christian Egtvedt authored and Takashi Iwai committed Apr 6, 2009
1 parent 3d3ff7c commit 2700b58
Show file tree
Hide file tree
Showing 2 changed files with 77 additions and 2 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: c42eec0f193ed408118e20d85ea8c2e69c529993
refs/heads/master: df163587eab15a24cc34cf8434a5657416f8a203
77 changes: 76 additions & 1 deletion trunk/sound/atmel/ac97c.c
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@ struct atmel_ac97c {
/* Serialize access to opened variable */
spinlock_t lock;
void __iomem *regs;
int irq;
int opened;
int reset_pin;
};
Expand Down Expand Up @@ -335,8 +336,16 @@ static int atmel_ac97c_playback_prepare(struct snd_pcm_substream *substream)
return -EINVAL;
}

/* Enable underrun interrupt on channel A */
word |= AC97C_CSR_UNRUN;

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 */
if (runtime->rate != 48000) {
word = ac97c_readl(chip, MR);
Expand Down Expand Up @@ -402,8 +411,16 @@ static int atmel_ac97c_capture_prepare(struct snd_pcm_substream *substream)
return -EINVAL;
}

/* Enable overrun interrupt on channel A */
word |= AC97C_CSR_OVRUN;

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 */
if (runtime->rate != 48000) {
word = ac97c_readl(chip, MR);
Expand Down Expand Up @@ -554,6 +571,43 @@ static struct snd_pcm_ops atmel_ac97_capture_ops = {
.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)
{
struct snd_pcm *pcm;
Expand Down Expand Up @@ -701,6 +755,7 @@ static int __devinit atmel_ac97c_probe(struct platform_device *pdev)
.read = atmel_ac97c_read,
};
int retval;
int irq;

regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (!regs) {
Expand All @@ -714,6 +769,12 @@ static int __devinit atmel_ac97c_probe(struct platform_device *pdev)
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");
if (IS_ERR(pclk)) {
dev_dbg(&pdev->dev, "no peripheral clock\n");
Expand All @@ -730,6 +791,13 @@ static int __devinit atmel_ac97c_probe(struct platform_device *pdev)

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);

strcpy(card->driver, "Atmel AC97C");
Expand Down Expand Up @@ -758,6 +826,10 @@ static int __devinit atmel_ac97c_probe(struct platform_device *pdev)

snd_card_set_dev(card, &pdev->dev);

/* 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);
if (retval) {
dev_dbg(&pdev->dev, "could not register on ac97 bus\n");
Expand Down Expand Up @@ -820,7 +892,7 @@ static int __devinit atmel_ac97c_probe(struct platform_device *pdev)
retval = snd_card_register(card);
if (retval) {
dev_dbg(&pdev->dev, "could not register sound card\n");
goto err_ac97_bus;
goto err_dma;
}

platform_set_drvdata(pdev, card);
Expand All @@ -847,6 +919,8 @@ static int __devinit atmel_ac97c_probe(struct platform_device *pdev)

iounmap(chip->regs);
err_ioremap:
free_irq(irq, chip);
err_request_irq:
snd_card_free(card);
err_snd_card_new:
clk_disable(pclk);
Expand Down Expand Up @@ -898,6 +972,7 @@ static int __devexit atmel_ac97c_remove(struct platform_device *pdev)
clk_disable(chip->pclk);
clk_put(chip->pclk);
iounmap(chip->regs);
free_irq(chip->irq, chip);

if (test_bit(DMA_RX_CHAN_PRESENT, &chip->flags))
dma_release_channel(chip->dma.rx_chan);
Expand Down

0 comments on commit 2700b58

Please sign in to comment.