diff options
author | Sedji Gaouaou <sedji.gaouaou@atmel.com> | 2010-03-01 06:19:18 -0500 |
---|---|---|
committer | Takashi Iwai <tiwai@suse.de> | 2010-03-25 15:22:15 -0400 |
commit | 7177395fdd919e561544a7d1c0ac196098a2ae2d (patch) | |
tree | d8b6f27a3c10cf6d575101bdd22991a211d5e504 /sound/atmel | |
parent | ae76148114aa2457baa0d340fc506bb7d114cb12 (diff) |
ALSA: AC97: add AC97 support for AT91.
This patch add AC97 support for ATMEL AT91, using the AVR32 code.
While AVR is using a DMA, the AT91 chips are using a Peripheral Data
Controller.
Signed-off-by: Sedji Gaouaou <sedji.gaouaou@atmel.com>
Acked-by: Liam Girdwood <lrg@slimlogic.co.uk>
Acked-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
Diffstat (limited to 'sound/atmel')
-rw-r--r-- | sound/atmel/Kconfig | 2 | ||||
-rw-r--r-- | sound/atmel/ac97c.c | 339 |
2 files changed, 255 insertions, 86 deletions
diff --git a/sound/atmel/Kconfig b/sound/atmel/Kconfig index 6c228a91940d..94de43a096f1 100644 --- a/sound/atmel/Kconfig +++ b/sound/atmel/Kconfig | |||
@@ -12,7 +12,7 @@ config SND_ATMEL_AC97C | |||
12 | tristate "Atmel AC97 Controller (AC97C) driver" | 12 | tristate "Atmel AC97 Controller (AC97C) driver" |
13 | select SND_PCM | 13 | select SND_PCM |
14 | select SND_AC97_CODEC | 14 | select SND_AC97_CODEC |
15 | depends on DW_DMAC && AVR32 | 15 | depends on (DW_DMAC && AVR32) || ARCH_AT91 |
16 | help | 16 | help |
17 | ALSA sound driver for the Atmel AC97 controller. | 17 | ALSA sound driver for the Atmel AC97 controller. |
18 | 18 | ||
diff --git a/sound/atmel/ac97c.c b/sound/atmel/ac97c.c index 0c0f8771656a..3c0a6f4e3585 100644 --- a/sound/atmel/ac97c.c +++ b/sound/atmel/ac97c.c | |||
@@ -13,6 +13,7 @@ | |||
13 | #include <linux/device.h> | 13 | #include <linux/device.h> |
14 | #include <linux/dmaengine.h> | 14 | #include <linux/dmaengine.h> |
15 | #include <linux/dma-mapping.h> | 15 | #include <linux/dma-mapping.h> |
16 | #include <linux/atmel_pdc.h> | ||
16 | #include <linux/init.h> | 17 | #include <linux/init.h> |
17 | #include <linux/interrupt.h> | 18 | #include <linux/interrupt.h> |
18 | #include <linux/module.h> | 19 | #include <linux/module.h> |
@@ -31,6 +32,10 @@ | |||
31 | 32 | ||
32 | #include <linux/dw_dmac.h> | 33 | #include <linux/dw_dmac.h> |
33 | 34 | ||
35 | #include <mach/cpu.h> | ||
36 | #include <mach/hardware.h> | ||
37 | #include <mach/gpio.h> | ||
38 | |||
34 | #include "ac97c.h" | 39 | #include "ac97c.h" |
35 | 40 | ||
36 | enum { | 41 | enum { |
@@ -63,6 +68,7 @@ struct atmel_ac97c { | |||
63 | u64 cur_format; | 68 | u64 cur_format; |
64 | unsigned int cur_rate; | 69 | unsigned int cur_rate; |
65 | unsigned long flags; | 70 | unsigned long flags; |
71 | int playback_period, capture_period; | ||
66 | /* Serialize access to opened variable */ | 72 | /* Serialize access to opened variable */ |
67 | spinlock_t lock; | 73 | spinlock_t lock; |
68 | void __iomem *regs; | 74 | void __iomem *regs; |
@@ -242,10 +248,12 @@ static int atmel_ac97c_playback_hw_params(struct snd_pcm_substream *substream, | |||
242 | if (retval < 0) | 248 | if (retval < 0) |
243 | return retval; | 249 | return retval; |
244 | /* snd_pcm_lib_malloc_pages returns 1 if buffer is changed. */ | 250 | /* snd_pcm_lib_malloc_pages returns 1 if buffer is changed. */ |
245 | if (retval == 1) | 251 | if (cpu_is_at32ap7000()) { |
246 | if (test_and_clear_bit(DMA_TX_READY, &chip->flags)) | 252 | /* snd_pcm_lib_malloc_pages returns 1 if buffer is changed. */ |
247 | dw_dma_cyclic_free(chip->dma.tx_chan); | 253 | if (retval == 1) |
248 | 254 | if (test_and_clear_bit(DMA_TX_READY, &chip->flags)) | |
255 | dw_dma_cyclic_free(chip->dma.tx_chan); | ||
256 | } | ||
249 | /* Set restrictions to params. */ | 257 | /* Set restrictions to params. */ |
250 | mutex_lock(&opened_mutex); | 258 | mutex_lock(&opened_mutex); |
251 | chip->cur_rate = params_rate(hw_params); | 259 | chip->cur_rate = params_rate(hw_params); |
@@ -266,9 +274,14 @@ static int atmel_ac97c_capture_hw_params(struct snd_pcm_substream *substream, | |||
266 | if (retval < 0) | 274 | if (retval < 0) |
267 | return retval; | 275 | return retval; |
268 | /* snd_pcm_lib_malloc_pages returns 1 if buffer is changed. */ | 276 | /* snd_pcm_lib_malloc_pages returns 1 if buffer is changed. */ |
269 | if (retval == 1) | 277 | if (cpu_is_at32ap7000()) { |
270 | if (test_and_clear_bit(DMA_RX_READY, &chip->flags)) | 278 | if (retval < 0) |
271 | dw_dma_cyclic_free(chip->dma.rx_chan); | 279 | return retval; |
280 | /* snd_pcm_lib_malloc_pages returns 1 if buffer is changed. */ | ||
281 | if (retval == 1) | ||
282 | if (test_and_clear_bit(DMA_RX_READY, &chip->flags)) | ||
283 | dw_dma_cyclic_free(chip->dma.rx_chan); | ||
284 | } | ||
272 | 285 | ||
273 | /* Set restrictions to params. */ | 286 | /* Set restrictions to params. */ |
274 | mutex_lock(&opened_mutex); | 287 | mutex_lock(&opened_mutex); |
@@ -282,16 +295,20 @@ static int atmel_ac97c_capture_hw_params(struct snd_pcm_substream *substream, | |||
282 | static int atmel_ac97c_playback_hw_free(struct snd_pcm_substream *substream) | 295 | static int atmel_ac97c_playback_hw_free(struct snd_pcm_substream *substream) |
283 | { | 296 | { |
284 | struct atmel_ac97c *chip = snd_pcm_substream_chip(substream); | 297 | struct atmel_ac97c *chip = snd_pcm_substream_chip(substream); |
285 | if (test_and_clear_bit(DMA_TX_READY, &chip->flags)) | 298 | if (cpu_is_at32ap7000()) { |
286 | dw_dma_cyclic_free(chip->dma.tx_chan); | 299 | if (test_and_clear_bit(DMA_TX_READY, &chip->flags)) |
300 | dw_dma_cyclic_free(chip->dma.tx_chan); | ||
301 | } | ||
287 | return snd_pcm_lib_free_pages(substream); | 302 | return snd_pcm_lib_free_pages(substream); |
288 | } | 303 | } |
289 | 304 | ||
290 | static int atmel_ac97c_capture_hw_free(struct snd_pcm_substream *substream) | 305 | static int atmel_ac97c_capture_hw_free(struct snd_pcm_substream *substream) |
291 | { | 306 | { |
292 | struct atmel_ac97c *chip = snd_pcm_substream_chip(substream); | 307 | struct atmel_ac97c *chip = snd_pcm_substream_chip(substream); |
293 | if (test_and_clear_bit(DMA_RX_READY, &chip->flags)) | 308 | if (cpu_is_at32ap7000()) { |
294 | dw_dma_cyclic_free(chip->dma.rx_chan); | 309 | if (test_and_clear_bit(DMA_RX_READY, &chip->flags)) |
310 | dw_dma_cyclic_free(chip->dma.rx_chan); | ||
311 | } | ||
295 | return snd_pcm_lib_free_pages(substream); | 312 | return snd_pcm_lib_free_pages(substream); |
296 | } | 313 | } |
297 | 314 | ||
@@ -299,9 +316,11 @@ static int atmel_ac97c_playback_prepare(struct snd_pcm_substream *substream) | |||
299 | { | 316 | { |
300 | struct atmel_ac97c *chip = snd_pcm_substream_chip(substream); | 317 | struct atmel_ac97c *chip = snd_pcm_substream_chip(substream); |
301 | struct snd_pcm_runtime *runtime = substream->runtime; | 318 | struct snd_pcm_runtime *runtime = substream->runtime; |
319 | int block_size = frames_to_bytes(runtime, runtime->period_size); | ||
302 | unsigned long word = ac97c_readl(chip, OCA); | 320 | unsigned long word = ac97c_readl(chip, OCA); |
303 | int retval; | 321 | int retval; |
304 | 322 | ||
323 | chip->playback_period = 0; | ||
305 | word &= ~(AC97C_CH_MASK(PCM_LEFT) | AC97C_CH_MASK(PCM_RIGHT)); | 324 | word &= ~(AC97C_CH_MASK(PCM_LEFT) | AC97C_CH_MASK(PCM_RIGHT)); |
306 | 325 | ||
307 | /* assign channels to AC97C channel A */ | 326 | /* assign channels to AC97C channel A */ |
@@ -324,7 +343,8 @@ static int atmel_ac97c_playback_prepare(struct snd_pcm_substream *substream) | |||
324 | 343 | ||
325 | switch (runtime->format) { | 344 | switch (runtime->format) { |
326 | case SNDRV_PCM_FORMAT_S16_LE: | 345 | case SNDRV_PCM_FORMAT_S16_LE: |
327 | word |= AC97C_CMR_CEM_LITTLE; | 346 | if (cpu_is_at32ap7000()) |
347 | word |= AC97C_CMR_CEM_LITTLE; | ||
328 | break; | 348 | break; |
329 | case SNDRV_PCM_FORMAT_S16_BE: /* fall through */ | 349 | case SNDRV_PCM_FORMAT_S16_BE: /* fall through */ |
330 | word &= ~(AC97C_CMR_CEM_LITTLE); | 350 | word &= ~(AC97C_CMR_CEM_LITTLE); |
@@ -363,9 +383,18 @@ static int atmel_ac97c_playback_prepare(struct snd_pcm_substream *substream) | |||
363 | dev_dbg(&chip->pdev->dev, "could not set rate %d Hz\n", | 383 | dev_dbg(&chip->pdev->dev, "could not set rate %d Hz\n", |
364 | runtime->rate); | 384 | runtime->rate); |
365 | 385 | ||
366 | if (!test_bit(DMA_TX_READY, &chip->flags)) | 386 | if (cpu_is_at32ap7000()) { |
367 | retval = atmel_ac97c_prepare_dma(chip, substream, | 387 | if (!test_bit(DMA_TX_READY, &chip->flags)) |
368 | DMA_TO_DEVICE); | 388 | retval = atmel_ac97c_prepare_dma(chip, substream, |
389 | DMA_TO_DEVICE); | ||
390 | } else { | ||
391 | /* Initialize and start the PDC */ | ||
392 | writel(runtime->dma_addr, chip->regs + ATMEL_PDC_TPR); | ||
393 | writel(block_size / 2, chip->regs + ATMEL_PDC_TCR); | ||
394 | writel(runtime->dma_addr + block_size, | ||
395 | chip->regs + ATMEL_PDC_TNPR); | ||
396 | writel(block_size / 2, chip->regs + ATMEL_PDC_TNCR); | ||
397 | } | ||
369 | 398 | ||
370 | return retval; | 399 | return retval; |
371 | } | 400 | } |
@@ -374,9 +403,11 @@ static int atmel_ac97c_capture_prepare(struct snd_pcm_substream *substream) | |||
374 | { | 403 | { |
375 | struct atmel_ac97c *chip = snd_pcm_substream_chip(substream); | 404 | struct atmel_ac97c *chip = snd_pcm_substream_chip(substream); |
376 | struct snd_pcm_runtime *runtime = substream->runtime; | 405 | struct snd_pcm_runtime *runtime = substream->runtime; |
406 | int block_size = frames_to_bytes(runtime, runtime->period_size); | ||
377 | unsigned long word = ac97c_readl(chip, ICA); | 407 | unsigned long word = ac97c_readl(chip, ICA); |
378 | int retval; | 408 | int retval; |
379 | 409 | ||
410 | chip->capture_period = 0; | ||
380 | word &= ~(AC97C_CH_MASK(PCM_LEFT) | AC97C_CH_MASK(PCM_RIGHT)); | 411 | word &= ~(AC97C_CH_MASK(PCM_LEFT) | AC97C_CH_MASK(PCM_RIGHT)); |
381 | 412 | ||
382 | /* assign channels to AC97C channel A */ | 413 | /* assign channels to AC97C channel A */ |
@@ -399,7 +430,8 @@ static int atmel_ac97c_capture_prepare(struct snd_pcm_substream *substream) | |||
399 | 430 | ||
400 | switch (runtime->format) { | 431 | switch (runtime->format) { |
401 | case SNDRV_PCM_FORMAT_S16_LE: | 432 | case SNDRV_PCM_FORMAT_S16_LE: |
402 | word |= AC97C_CMR_CEM_LITTLE; | 433 | if (cpu_is_at32ap7000()) |
434 | word |= AC97C_CMR_CEM_LITTLE; | ||
403 | break; | 435 | break; |
404 | case SNDRV_PCM_FORMAT_S16_BE: /* fall through */ | 436 | case SNDRV_PCM_FORMAT_S16_BE: /* fall through */ |
405 | word &= ~(AC97C_CMR_CEM_LITTLE); | 437 | word &= ~(AC97C_CMR_CEM_LITTLE); |
@@ -438,9 +470,18 @@ static int atmel_ac97c_capture_prepare(struct snd_pcm_substream *substream) | |||
438 | dev_dbg(&chip->pdev->dev, "could not set rate %d Hz\n", | 470 | dev_dbg(&chip->pdev->dev, "could not set rate %d Hz\n", |
439 | runtime->rate); | 471 | runtime->rate); |
440 | 472 | ||
441 | if (!test_bit(DMA_RX_READY, &chip->flags)) | 473 | if (cpu_is_at32ap7000()) { |
442 | retval = atmel_ac97c_prepare_dma(chip, substream, | 474 | if (!test_bit(DMA_RX_READY, &chip->flags)) |
443 | DMA_FROM_DEVICE); | 475 | retval = atmel_ac97c_prepare_dma(chip, substream, |
476 | DMA_FROM_DEVICE); | ||
477 | } else { | ||
478 | /* Initialize and start the PDC */ | ||
479 | writel(runtime->dma_addr, chip->regs + ATMEL_PDC_RPR); | ||
480 | writel(block_size / 2, chip->regs + ATMEL_PDC_RCR); | ||
481 | writel(runtime->dma_addr + block_size, | ||
482 | chip->regs + ATMEL_PDC_RNPR); | ||
483 | writel(block_size / 2, chip->regs + ATMEL_PDC_RNCR); | ||
484 | } | ||
444 | 485 | ||
445 | return retval; | 486 | return retval; |
446 | } | 487 | } |
@@ -449,7 +490,7 @@ static int | |||
449 | atmel_ac97c_playback_trigger(struct snd_pcm_substream *substream, int cmd) | 490 | atmel_ac97c_playback_trigger(struct snd_pcm_substream *substream, int cmd) |
450 | { | 491 | { |
451 | struct atmel_ac97c *chip = snd_pcm_substream_chip(substream); | 492 | struct atmel_ac97c *chip = snd_pcm_substream_chip(substream); |
452 | unsigned long camr; | 493 | unsigned long camr, ptcr = 0; |
453 | int retval = 0; | 494 | int retval = 0; |
454 | 495 | ||
455 | camr = ac97c_readl(chip, CAMR); | 496 | camr = ac97c_readl(chip, CAMR); |
@@ -458,15 +499,22 @@ atmel_ac97c_playback_trigger(struct snd_pcm_substream *substream, int cmd) | |||
458 | case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: /* fall through */ | 499 | case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: /* fall through */ |
459 | case SNDRV_PCM_TRIGGER_RESUME: /* fall through */ | 500 | case SNDRV_PCM_TRIGGER_RESUME: /* fall through */ |
460 | case SNDRV_PCM_TRIGGER_START: | 501 | case SNDRV_PCM_TRIGGER_START: |
461 | retval = dw_dma_cyclic_start(chip->dma.tx_chan); | 502 | if (cpu_is_at32ap7000()) { |
462 | if (retval) | 503 | retval = dw_dma_cyclic_start(chip->dma.tx_chan); |
463 | goto out; | 504 | if (retval) |
505 | goto out; | ||
506 | } else { | ||
507 | ptcr = ATMEL_PDC_TXTEN; | ||
508 | } | ||
464 | camr |= AC97C_CMR_CENA; | 509 | camr |= AC97C_CMR_CENA; |
465 | break; | 510 | break; |
466 | case SNDRV_PCM_TRIGGER_PAUSE_PUSH: /* fall through */ | 511 | case SNDRV_PCM_TRIGGER_PAUSE_PUSH: /* fall through */ |
467 | case SNDRV_PCM_TRIGGER_SUSPEND: /* fall through */ | 512 | case SNDRV_PCM_TRIGGER_SUSPEND: /* fall through */ |
468 | case SNDRV_PCM_TRIGGER_STOP: | 513 | case SNDRV_PCM_TRIGGER_STOP: |
469 | dw_dma_cyclic_stop(chip->dma.tx_chan); | 514 | if (cpu_is_at32ap7000()) |
515 | dw_dma_cyclic_stop(chip->dma.tx_chan); | ||
516 | else | ||
517 | ptcr |= ATMEL_PDC_TXTDIS; | ||
470 | if (chip->opened <= 1) | 518 | if (chip->opened <= 1) |
471 | camr &= ~AC97C_CMR_CENA; | 519 | camr &= ~AC97C_CMR_CENA; |
472 | break; | 520 | break; |
@@ -476,6 +524,8 @@ atmel_ac97c_playback_trigger(struct snd_pcm_substream *substream, int cmd) | |||
476 | } | 524 | } |
477 | 525 | ||
478 | ac97c_writel(chip, CAMR, camr); | 526 | ac97c_writel(chip, CAMR, camr); |
527 | if (!cpu_is_at32ap7000()) | ||
528 | writel(ptcr, chip->regs + ATMEL_PDC_PTCR); | ||
479 | out: | 529 | out: |
480 | return retval; | 530 | return retval; |
481 | } | 531 | } |
@@ -484,24 +534,32 @@ static int | |||
484 | atmel_ac97c_capture_trigger(struct snd_pcm_substream *substream, int cmd) | 534 | atmel_ac97c_capture_trigger(struct snd_pcm_substream *substream, int cmd) |
485 | { | 535 | { |
486 | struct atmel_ac97c *chip = snd_pcm_substream_chip(substream); | 536 | struct atmel_ac97c *chip = snd_pcm_substream_chip(substream); |
487 | unsigned long camr; | 537 | unsigned long camr, ptcr = 0; |
488 | int retval = 0; | 538 | int retval = 0; |
489 | 539 | ||
490 | camr = ac97c_readl(chip, CAMR); | 540 | camr = ac97c_readl(chip, CAMR); |
541 | ptcr = readl(chip->regs + ATMEL_PDC_PTSR); | ||
491 | 542 | ||
492 | switch (cmd) { | 543 | switch (cmd) { |
493 | case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: /* fall through */ | 544 | case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: /* fall through */ |
494 | case SNDRV_PCM_TRIGGER_RESUME: /* fall through */ | 545 | case SNDRV_PCM_TRIGGER_RESUME: /* fall through */ |
495 | case SNDRV_PCM_TRIGGER_START: | 546 | case SNDRV_PCM_TRIGGER_START: |
496 | retval = dw_dma_cyclic_start(chip->dma.rx_chan); | 547 | if (cpu_is_at32ap7000()) { |
497 | if (retval) | 548 | retval = dw_dma_cyclic_start(chip->dma.rx_chan); |
498 | goto out; | 549 | if (retval) |
550 | goto out; | ||
551 | } else { | ||
552 | ptcr = ATMEL_PDC_RXTEN; | ||
553 | } | ||
499 | camr |= AC97C_CMR_CENA; | 554 | camr |= AC97C_CMR_CENA; |
500 | break; | 555 | break; |
501 | case SNDRV_PCM_TRIGGER_PAUSE_PUSH: /* fall through */ | 556 | case SNDRV_PCM_TRIGGER_PAUSE_PUSH: /* fall through */ |
502 | case SNDRV_PCM_TRIGGER_SUSPEND: /* fall through */ | 557 | case SNDRV_PCM_TRIGGER_SUSPEND: /* fall through */ |
503 | case SNDRV_PCM_TRIGGER_STOP: | 558 | case SNDRV_PCM_TRIGGER_STOP: |
504 | dw_dma_cyclic_stop(chip->dma.rx_chan); | 559 | if (cpu_is_at32ap7000()) |
560 | dw_dma_cyclic_stop(chip->dma.rx_chan); | ||
561 | else | ||
562 | ptcr |= (ATMEL_PDC_RXTDIS); | ||
505 | if (chip->opened <= 1) | 563 | if (chip->opened <= 1) |
506 | camr &= ~AC97C_CMR_CENA; | 564 | camr &= ~AC97C_CMR_CENA; |
507 | break; | 565 | break; |
@@ -511,6 +569,8 @@ atmel_ac97c_capture_trigger(struct snd_pcm_substream *substream, int cmd) | |||
511 | } | 569 | } |
512 | 570 | ||
513 | ac97c_writel(chip, CAMR, camr); | 571 | ac97c_writel(chip, CAMR, camr); |
572 | if (!cpu_is_at32ap7000()) | ||
573 | writel(ptcr, chip->regs + ATMEL_PDC_PTCR); | ||
514 | out: | 574 | out: |
515 | return retval; | 575 | return retval; |
516 | } | 576 | } |
@@ -523,7 +583,10 @@ atmel_ac97c_playback_pointer(struct snd_pcm_substream *substream) | |||
523 | snd_pcm_uframes_t frames; | 583 | snd_pcm_uframes_t frames; |
524 | unsigned long bytes; | 584 | unsigned long bytes; |
525 | 585 | ||
526 | bytes = dw_dma_get_src_addr(chip->dma.tx_chan); | 586 | if (cpu_is_at32ap7000()) |
587 | bytes = dw_dma_get_src_addr(chip->dma.tx_chan); | ||
588 | else | ||
589 | bytes = readl(chip->regs + ATMEL_PDC_TPR); | ||
527 | bytes -= runtime->dma_addr; | 590 | bytes -= runtime->dma_addr; |
528 | 591 | ||
529 | frames = bytes_to_frames(runtime, bytes); | 592 | frames = bytes_to_frames(runtime, bytes); |
@@ -540,7 +603,10 @@ atmel_ac97c_capture_pointer(struct snd_pcm_substream *substream) | |||
540 | snd_pcm_uframes_t frames; | 603 | snd_pcm_uframes_t frames; |
541 | unsigned long bytes; | 604 | unsigned long bytes; |
542 | 605 | ||
543 | bytes = dw_dma_get_dst_addr(chip->dma.rx_chan); | 606 | if (cpu_is_at32ap7000()) |
607 | bytes = dw_dma_get_dst_addr(chip->dma.rx_chan); | ||
608 | else | ||
609 | bytes = readl(chip->regs + ATMEL_PDC_RPR); | ||
544 | bytes -= runtime->dma_addr; | 610 | bytes -= runtime->dma_addr; |
545 | 611 | ||
546 | frames = bytes_to_frames(runtime, bytes); | 612 | frames = bytes_to_frames(runtime, bytes); |
@@ -578,8 +644,11 @@ static irqreturn_t atmel_ac97c_interrupt(int irq, void *dev) | |||
578 | u32 sr = ac97c_readl(chip, SR); | 644 | u32 sr = ac97c_readl(chip, SR); |
579 | u32 casr = ac97c_readl(chip, CASR); | 645 | u32 casr = ac97c_readl(chip, CASR); |
580 | u32 cosr = ac97c_readl(chip, COSR); | 646 | u32 cosr = ac97c_readl(chip, COSR); |
647 | u32 camr = ac97c_readl(chip, CAMR); | ||
581 | 648 | ||
582 | if (sr & AC97C_SR_CAEVT) { | 649 | if (sr & AC97C_SR_CAEVT) { |
650 | struct snd_pcm_runtime *runtime; | ||
651 | int offset, next_period, block_size; | ||
583 | dev_info(&chip->pdev->dev, "channel A event%s%s%s%s%s%s\n", | 652 | dev_info(&chip->pdev->dev, "channel A event%s%s%s%s%s%s\n", |
584 | casr & AC97C_CSR_OVRUN ? " OVRUN" : "", | 653 | casr & AC97C_CSR_OVRUN ? " OVRUN" : "", |
585 | casr & AC97C_CSR_RXRDY ? " RXRDY" : "", | 654 | casr & AC97C_CSR_RXRDY ? " RXRDY" : "", |
@@ -587,6 +656,50 @@ static irqreturn_t atmel_ac97c_interrupt(int irq, void *dev) | |||
587 | casr & AC97C_CSR_TXEMPTY ? " TXEMPTY" : "", | 656 | casr & AC97C_CSR_TXEMPTY ? " TXEMPTY" : "", |
588 | casr & AC97C_CSR_TXRDY ? " TXRDY" : "", | 657 | casr & AC97C_CSR_TXRDY ? " TXRDY" : "", |
589 | !casr ? " NONE" : ""); | 658 | !casr ? " NONE" : ""); |
659 | if (!cpu_is_at32ap7000()) { | ||
660 | if ((casr & camr) & AC97C_CSR_ENDTX) { | ||
661 | runtime = chip->playback_substream->runtime; | ||
662 | block_size = frames_to_bytes(runtime, | ||
663 | runtime->period_size); | ||
664 | chip->playback_period++; | ||
665 | |||
666 | if (chip->playback_period == runtime->periods) | ||
667 | chip->playback_period = 0; | ||
668 | next_period = chip->playback_period + 1; | ||
669 | if (next_period == runtime->periods) | ||
670 | next_period = 0; | ||
671 | |||
672 | offset = block_size * next_period; | ||
673 | |||
674 | writel(runtime->dma_addr + offset, | ||
675 | chip->regs + ATMEL_PDC_TNPR); | ||
676 | writel(block_size / 2, | ||
677 | chip->regs + ATMEL_PDC_TNCR); | ||
678 | |||
679 | snd_pcm_period_elapsed( | ||
680 | chip->playback_substream); | ||
681 | } | ||
682 | if ((casr & camr) & AC97C_CSR_ENDRX) { | ||
683 | runtime = chip->capture_substream->runtime; | ||
684 | block_size = frames_to_bytes(runtime, | ||
685 | runtime->period_size); | ||
686 | chip->capture_period++; | ||
687 | |||
688 | if (chip->capture_period == runtime->periods) | ||
689 | chip->capture_period = 0; | ||
690 | next_period = chip->capture_period + 1; | ||
691 | if (next_period == runtime->periods) | ||
692 | next_period = 0; | ||
693 | |||
694 | offset = block_size * next_period; | ||
695 | |||
696 | writel(runtime->dma_addr + offset, | ||
697 | chip->regs + ATMEL_PDC_RNPR); | ||
698 | writel(block_size / 2, | ||
699 | chip->regs + ATMEL_PDC_RNCR); | ||
700 | snd_pcm_period_elapsed(chip->capture_substream); | ||
701 | } | ||
702 | } | ||
590 | retval = IRQ_HANDLED; | 703 | retval = IRQ_HANDLED; |
591 | } | 704 | } |
592 | 705 | ||
@@ -608,15 +721,50 @@ static irqreturn_t atmel_ac97c_interrupt(int irq, void *dev) | |||
608 | return retval; | 721 | return retval; |
609 | } | 722 | } |
610 | 723 | ||
724 | static struct ac97_pcm at91_ac97_pcm_defs[] __devinitdata = { | ||
725 | /* Playback */ | ||
726 | { | ||
727 | .exclusive = 1, | ||
728 | .r = { { | ||
729 | .slots = ((1 << AC97_SLOT_PCM_LEFT) | ||
730 | | (1 << AC97_SLOT_PCM_RIGHT)), | ||
731 | } }, | ||
732 | }, | ||
733 | /* PCM in */ | ||
734 | { | ||
735 | .stream = 1, | ||
736 | .exclusive = 1, | ||
737 | .r = { { | ||
738 | .slots = ((1 << AC97_SLOT_PCM_LEFT) | ||
739 | | (1 << AC97_SLOT_PCM_RIGHT)), | ||
740 | } } | ||
741 | }, | ||
742 | /* Mic in */ | ||
743 | { | ||
744 | .stream = 1, | ||
745 | .exclusive = 1, | ||
746 | .r = { { | ||
747 | .slots = (1<<AC97_SLOT_MIC), | ||
748 | } } | ||
749 | }, | ||
750 | }; | ||
751 | |||
611 | static int __devinit atmel_ac97c_pcm_new(struct atmel_ac97c *chip) | 752 | static int __devinit atmel_ac97c_pcm_new(struct atmel_ac97c *chip) |
612 | { | 753 | { |
613 | struct snd_pcm *pcm; | 754 | struct snd_pcm *pcm; |
614 | struct snd_pcm_hardware hw = atmel_ac97c_hw; | 755 | struct snd_pcm_hardware hw = atmel_ac97c_hw; |
615 | int capture, playback, retval; | 756 | int capture, playback, retval, err; |
616 | 757 | ||
617 | capture = test_bit(DMA_RX_CHAN_PRESENT, &chip->flags); | 758 | capture = test_bit(DMA_RX_CHAN_PRESENT, &chip->flags); |
618 | playback = test_bit(DMA_TX_CHAN_PRESENT, &chip->flags); | 759 | playback = test_bit(DMA_TX_CHAN_PRESENT, &chip->flags); |
619 | 760 | ||
761 | if (!cpu_is_at32ap7000()) { | ||
762 | err = snd_ac97_pcm_assign(chip->ac97_bus, | ||
763 | ARRAY_SIZE(at91_ac97_pcm_defs), | ||
764 | at91_ac97_pcm_defs); | ||
765 | if (err) | ||
766 | return err; | ||
767 | } | ||
620 | retval = snd_pcm_new(chip->card, chip->card->shortname, | 768 | retval = snd_pcm_new(chip->card, chip->card->shortname, |
621 | chip->pdev->id, playback, capture, &pcm); | 769 | chip->pdev->id, playback, capture, &pcm); |
622 | if (retval) | 770 | if (retval) |
@@ -775,7 +923,12 @@ static int __devinit atmel_ac97c_probe(struct platform_device *pdev) | |||
775 | return -ENXIO; | 923 | return -ENXIO; |
776 | } | 924 | } |
777 | 925 | ||
778 | pclk = clk_get(&pdev->dev, "pclk"); | 926 | if (cpu_is_at32ap7000()) { |
927 | pclk = clk_get(&pdev->dev, "pclk"); | ||
928 | } else { | ||
929 | pclk = clk_get(&pdev->dev, "ac97_clk"); | ||
930 | } | ||
931 | |||
779 | if (IS_ERR(pclk)) { | 932 | if (IS_ERR(pclk)) { |
780 | dev_dbg(&pdev->dev, "no peripheral clock\n"); | 933 | dev_dbg(&pdev->dev, "no peripheral clock\n"); |
781 | return PTR_ERR(pclk); | 934 | return PTR_ERR(pclk); |
@@ -844,43 +997,52 @@ static int __devinit atmel_ac97c_probe(struct platform_device *pdev) | |||
844 | goto err_ac97_bus; | 997 | goto err_ac97_bus; |
845 | } | 998 | } |
846 | 999 | ||
847 | if (pdata->rx_dws.dma_dev) { | 1000 | if (cpu_is_at32ap7000()) { |
848 | struct dw_dma_slave *dws = &pdata->rx_dws; | 1001 | if (pdata->rx_dws.dma_dev) { |
849 | dma_cap_mask_t mask; | 1002 | struct dw_dma_slave *dws = &pdata->rx_dws; |
1003 | dma_cap_mask_t mask; | ||
850 | 1004 | ||
851 | dws->rx_reg = regs->start + AC97C_CARHR + 2; | 1005 | dws->rx_reg = regs->start + AC97C_CARHR + 2; |
852 | 1006 | ||
853 | dma_cap_zero(mask); | 1007 | dma_cap_zero(mask); |
854 | dma_cap_set(DMA_SLAVE, mask); | 1008 | dma_cap_set(DMA_SLAVE, mask); |
855 | 1009 | ||
856 | chip->dma.rx_chan = dma_request_channel(mask, filter, dws); | 1010 | chip->dma.rx_chan = dma_request_channel(mask, filter, |
1011 | dws); | ||
857 | 1012 | ||
858 | dev_info(&chip->pdev->dev, "using %s for DMA RX\n", | 1013 | dev_info(&chip->pdev->dev, "using %s for DMA RX\n", |
859 | dev_name(&chip->dma.rx_chan->dev->device)); | 1014 | dev_name(&chip->dma.rx_chan->dev->device)); |
860 | set_bit(DMA_RX_CHAN_PRESENT, &chip->flags); | 1015 | set_bit(DMA_RX_CHAN_PRESENT, &chip->flags); |
861 | } | 1016 | } |
862 | 1017 | ||
863 | if (pdata->tx_dws.dma_dev) { | 1018 | if (pdata->tx_dws.dma_dev) { |
864 | struct dw_dma_slave *dws = &pdata->tx_dws; | 1019 | struct dw_dma_slave *dws = &pdata->tx_dws; |
865 | dma_cap_mask_t mask; | 1020 | dma_cap_mask_t mask; |
866 | 1021 | ||
867 | dws->tx_reg = regs->start + AC97C_CATHR + 2; | 1022 | dws->tx_reg = regs->start + AC97C_CATHR + 2; |
868 | 1023 | ||
869 | dma_cap_zero(mask); | 1024 | dma_cap_zero(mask); |
870 | dma_cap_set(DMA_SLAVE, mask); | 1025 | dma_cap_set(DMA_SLAVE, mask); |
871 | 1026 | ||
872 | chip->dma.tx_chan = dma_request_channel(mask, filter, dws); | 1027 | chip->dma.tx_chan = dma_request_channel(mask, filter, |
1028 | dws); | ||
873 | 1029 | ||
874 | dev_info(&chip->pdev->dev, "using %s for DMA TX\n", | 1030 | dev_info(&chip->pdev->dev, "using %s for DMA TX\n", |
875 | dev_name(&chip->dma.tx_chan->dev->device)); | 1031 | dev_name(&chip->dma.tx_chan->dev->device)); |
876 | set_bit(DMA_TX_CHAN_PRESENT, &chip->flags); | 1032 | set_bit(DMA_TX_CHAN_PRESENT, &chip->flags); |
877 | } | 1033 | } |
878 | 1034 | ||
879 | if (!test_bit(DMA_RX_CHAN_PRESENT, &chip->flags) && | 1035 | if (!test_bit(DMA_RX_CHAN_PRESENT, &chip->flags) && |
880 | !test_bit(DMA_TX_CHAN_PRESENT, &chip->flags)) { | 1036 | !test_bit(DMA_TX_CHAN_PRESENT, &chip->flags)) { |
881 | dev_dbg(&pdev->dev, "DMA not available\n"); | 1037 | dev_dbg(&pdev->dev, "DMA not available\n"); |
882 | retval = -ENODEV; | 1038 | retval = -ENODEV; |
883 | goto err_dma; | 1039 | goto err_dma; |
1040 | } | ||
1041 | } else { | ||
1042 | /* Just pretend that we have DMA channel(for at91 i is actually | ||
1043 | * the PDC) */ | ||
1044 | set_bit(DMA_RX_CHAN_PRESENT, &chip->flags); | ||
1045 | set_bit(DMA_TX_CHAN_PRESENT, &chip->flags); | ||
884 | } | 1046 | } |
885 | 1047 | ||
886 | retval = atmel_ac97c_pcm_new(chip); | 1048 | retval = atmel_ac97c_pcm_new(chip); |
@@ -897,20 +1059,22 @@ static int __devinit atmel_ac97c_probe(struct platform_device *pdev) | |||
897 | 1059 | ||
898 | platform_set_drvdata(pdev, card); | 1060 | platform_set_drvdata(pdev, card); |
899 | 1061 | ||
900 | dev_info(&pdev->dev, "Atmel AC97 controller at 0x%p\n", | 1062 | dev_info(&pdev->dev, "Atmel AC97 controller at 0x%p, irq = %d\n", |
901 | chip->regs); | 1063 | chip->regs, irq); |
902 | 1064 | ||
903 | return 0; | 1065 | return 0; |
904 | 1066 | ||
905 | err_dma: | 1067 | err_dma: |
906 | if (test_bit(DMA_RX_CHAN_PRESENT, &chip->flags)) | 1068 | if (cpu_is_at32ap7000()) { |
907 | dma_release_channel(chip->dma.rx_chan); | 1069 | if (test_bit(DMA_RX_CHAN_PRESENT, &chip->flags)) |
908 | if (test_bit(DMA_TX_CHAN_PRESENT, &chip->flags)) | 1070 | dma_release_channel(chip->dma.rx_chan); |
909 | dma_release_channel(chip->dma.tx_chan); | 1071 | if (test_bit(DMA_TX_CHAN_PRESENT, &chip->flags)) |
910 | clear_bit(DMA_RX_CHAN_PRESENT, &chip->flags); | 1072 | dma_release_channel(chip->dma.tx_chan); |
911 | clear_bit(DMA_TX_CHAN_PRESENT, &chip->flags); | 1073 | clear_bit(DMA_RX_CHAN_PRESENT, &chip->flags); |
912 | chip->dma.rx_chan = NULL; | 1074 | clear_bit(DMA_TX_CHAN_PRESENT, &chip->flags); |
913 | chip->dma.tx_chan = NULL; | 1075 | chip->dma.rx_chan = NULL; |
1076 | chip->dma.tx_chan = NULL; | ||
1077 | } | ||
914 | err_ac97_bus: | 1078 | err_ac97_bus: |
915 | snd_card_set_dev(card, NULL); | 1079 | snd_card_set_dev(card, NULL); |
916 | 1080 | ||
@@ -934,10 +1098,12 @@ static int atmel_ac97c_suspend(struct platform_device *pdev, pm_message_t msg) | |||
934 | struct snd_card *card = platform_get_drvdata(pdev); | 1098 | struct snd_card *card = platform_get_drvdata(pdev); |
935 | struct atmel_ac97c *chip = card->private_data; | 1099 | struct atmel_ac97c *chip = card->private_data; |
936 | 1100 | ||
937 | if (test_bit(DMA_RX_READY, &chip->flags)) | 1101 | if (cpu_is_at32ap7000()) { |
938 | dw_dma_cyclic_stop(chip->dma.rx_chan); | 1102 | if (test_bit(DMA_RX_READY, &chip->flags)) |
939 | if (test_bit(DMA_TX_READY, &chip->flags)) | 1103 | dw_dma_cyclic_stop(chip->dma.rx_chan); |
940 | dw_dma_cyclic_stop(chip->dma.tx_chan); | 1104 | if (test_bit(DMA_TX_READY, &chip->flags)) |
1105 | dw_dma_cyclic_stop(chip->dma.tx_chan); | ||
1106 | } | ||
941 | clk_disable(chip->pclk); | 1107 | clk_disable(chip->pclk); |
942 | 1108 | ||
943 | return 0; | 1109 | return 0; |
@@ -949,11 +1115,12 @@ static int atmel_ac97c_resume(struct platform_device *pdev) | |||
949 | struct atmel_ac97c *chip = card->private_data; | 1115 | struct atmel_ac97c *chip = card->private_data; |
950 | 1116 | ||
951 | clk_enable(chip->pclk); | 1117 | clk_enable(chip->pclk); |
952 | if (test_bit(DMA_RX_READY, &chip->flags)) | 1118 | if (cpu_is_at32ap7000()) { |
953 | dw_dma_cyclic_start(chip->dma.rx_chan); | 1119 | if (test_bit(DMA_RX_READY, &chip->flags)) |
954 | if (test_bit(DMA_TX_READY, &chip->flags)) | 1120 | dw_dma_cyclic_start(chip->dma.rx_chan); |
955 | dw_dma_cyclic_start(chip->dma.tx_chan); | 1121 | if (test_bit(DMA_TX_READY, &chip->flags)) |
956 | 1122 | dw_dma_cyclic_start(chip->dma.tx_chan); | |
1123 | } | ||
957 | return 0; | 1124 | return 0; |
958 | } | 1125 | } |
959 | #else | 1126 | #else |
@@ -978,14 +1145,16 @@ static int __devexit atmel_ac97c_remove(struct platform_device *pdev) | |||
978 | iounmap(chip->regs); | 1145 | iounmap(chip->regs); |
979 | free_irq(chip->irq, chip); | 1146 | free_irq(chip->irq, chip); |
980 | 1147 | ||
981 | if (test_bit(DMA_RX_CHAN_PRESENT, &chip->flags)) | 1148 | if (cpu_is_at32ap7000()) { |
982 | dma_release_channel(chip->dma.rx_chan); | 1149 | if (test_bit(DMA_RX_CHAN_PRESENT, &chip->flags)) |
983 | if (test_bit(DMA_TX_CHAN_PRESENT, &chip->flags)) | 1150 | dma_release_channel(chip->dma.rx_chan); |
984 | dma_release_channel(chip->dma.tx_chan); | 1151 | if (test_bit(DMA_TX_CHAN_PRESENT, &chip->flags)) |
985 | clear_bit(DMA_RX_CHAN_PRESENT, &chip->flags); | 1152 | dma_release_channel(chip->dma.tx_chan); |
986 | clear_bit(DMA_TX_CHAN_PRESENT, &chip->flags); | 1153 | clear_bit(DMA_RX_CHAN_PRESENT, &chip->flags); |
987 | chip->dma.rx_chan = NULL; | 1154 | clear_bit(DMA_TX_CHAN_PRESENT, &chip->flags); |
988 | chip->dma.tx_chan = NULL; | 1155 | chip->dma.rx_chan = NULL; |
1156 | chip->dma.tx_chan = NULL; | ||
1157 | } | ||
989 | 1158 | ||
990 | snd_card_set_dev(card, NULL); | 1159 | snd_card_set_dev(card, NULL); |
991 | snd_card_free(card); | 1160 | snd_card_free(card); |