diff options
author | Georg Chini <georg.chini@triaton-webhosting.com> | 2005-11-07 17:09:19 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2005-11-07 17:09:19 -0500 |
commit | b128254fdb172eaa3273de24fa6ce405a1f534c9 (patch) | |
tree | 3b099bf16fafe78c5fca7b01933bb02353c60aa4 /sound/sparc | |
parent | dedeb0029b9c83420fc1337d4ee53daa7b2a0ad4 (diff) |
[SPARC]: More abstractions and cleanups of dma handling in cs4231.
From: Georg Chini <georg.chini@triaton-webhosting.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'sound/sparc')
-rw-r--r-- | sound/sparc/cs4231.c | 683 |
1 files changed, 342 insertions, 341 deletions
diff --git a/sound/sparc/cs4231.c b/sound/sparc/cs4231.c index 110d64d4848d..1f8d27a6152e 100644 --- a/sound/sparc/cs4231.c +++ b/sound/sparc/cs4231.c | |||
@@ -62,25 +62,36 @@ MODULE_LICENSE("GPL"); | |||
62 | MODULE_SUPPORTED_DEVICE("{{Sun,CS4231}}"); | 62 | MODULE_SUPPORTED_DEVICE("{{Sun,CS4231}}"); |
63 | 63 | ||
64 | #ifdef SBUS_SUPPORT | 64 | #ifdef SBUS_SUPPORT |
65 | struct sbus_dma_info { | 65 | typedef struct sbus_dma_info { |
66 | spinlock_t lock; | 66 | spinlock_t lock; |
67 | int dir; | 67 | int dir; |
68 | void __iomem *regs; | 68 | void __iomem *regs; |
69 | }; | 69 | } sbus_dma_info_t; |
70 | #endif | 70 | #endif |
71 | 71 | ||
72 | typedef struct snd_cs4231 { | 72 | typedef struct snd_cs4231 cs4231_t; |
73 | spinlock_t lock; | 73 | |
74 | void __iomem *port; | 74 | typedef struct cs4231_dma_control { |
75 | void (*prepare)(struct cs4231_dma_control *dma_cont, int dir); | ||
76 | void (*enable)(struct cs4231_dma_control *dma_cont, int on); | ||
77 | int (*request)(struct cs4231_dma_control *dma_cont, dma_addr_t bus_addr, size_t len); | ||
78 | unsigned int (*address)(struct cs4231_dma_control *dma_cont); | ||
79 | void (*reset)(cs4231_t *chip); | ||
80 | void (*preallocate)(cs4231_t *chip, snd_pcm_t *pcm); | ||
75 | #ifdef EBUS_SUPPORT | 81 | #ifdef EBUS_SUPPORT |
76 | struct ebus_dma_info eb2c; | 82 | struct ebus_dma_info ebus_info; |
77 | struct ebus_dma_info eb2p; | ||
78 | #endif | 83 | #endif |
79 | |||
80 | #ifdef SBUS_SUPPORT | 84 | #ifdef SBUS_SUPPORT |
81 | struct sbus_dma_info sb2c; | 85 | struct sbus_dma_info sbus_info; |
82 | struct sbus_dma_info sb2p; | ||
83 | #endif | 86 | #endif |
87 | } cs4231_dma_control_t; | ||
88 | |||
89 | struct snd_cs4231 { | ||
90 | spinlock_t lock; | ||
91 | void __iomem *port; | ||
92 | |||
93 | cs4231_dma_control_t p_dma; | ||
94 | cs4231_dma_control_t c_dma; | ||
84 | 95 | ||
85 | u32 flags; | 96 | u32 flags; |
86 | #define CS4231_FLAG_EBUS 0x00000001 | 97 | #define CS4231_FLAG_EBUS 0x00000001 |
@@ -119,7 +130,7 @@ typedef struct snd_cs4231 { | |||
119 | unsigned int irq[2]; | 130 | unsigned int irq[2]; |
120 | unsigned int regs_size; | 131 | unsigned int regs_size; |
121 | struct snd_cs4231 *next; | 132 | struct snd_cs4231 *next; |
122 | } cs4231_t; | 133 | }; |
123 | 134 | ||
124 | static cs4231_t *cs4231_list; | 135 | static cs4231_t *cs4231_list; |
125 | 136 | ||
@@ -494,103 +505,6 @@ static unsigned char snd_cs4231_in(cs4231_t *chip, unsigned char reg) | |||
494 | } | 505 | } |
495 | 506 | ||
496 | /* | 507 | /* |
497 | * SBUS DMA routines | ||
498 | */ | ||
499 | #ifdef SBUS_SUPPORT | ||
500 | |||
501 | int sbus_dma_request(struct sbus_dma_info *base, dma_addr_t bus_addr, size_t len) | ||
502 | { | ||
503 | unsigned long flags; | ||
504 | u32 test, csr; | ||
505 | int err; | ||
506 | |||
507 | if (len >= (1 << 24)) | ||
508 | return -EINVAL; | ||
509 | spin_lock_irqsave(&base->lock, flags); | ||
510 | csr = sbus_readl(base->regs + APCCSR); | ||
511 | err = -EINVAL; | ||
512 | test = APC_CDMA_READY; | ||
513 | if ( base->dir == APC_PLAY ) | ||
514 | test = APC_PDMA_READY; | ||
515 | if (!(csr & test)) | ||
516 | goto out; | ||
517 | err = -EBUSY; | ||
518 | csr = sbus_readl(base->regs + APCCSR); | ||
519 | test = APC_XINT_CNVA; | ||
520 | if ( base->dir == APC_PLAY ) | ||
521 | test = APC_XINT_PNVA; | ||
522 | if (!(csr & test)) | ||
523 | goto out; | ||
524 | err = 0; | ||
525 | sbus_writel(bus_addr, base->regs + base->dir + APCNVA); | ||
526 | sbus_writel(len, base->regs + base->dir + APCNC); | ||
527 | out: | ||
528 | spin_unlock_irqrestore(&base->lock, flags); | ||
529 | return err; | ||
530 | } | ||
531 | |||
532 | void sbus_dma_prepare(struct sbus_dma_info *base) | ||
533 | { | ||
534 | unsigned long flags; | ||
535 | u32 csr, test; | ||
536 | |||
537 | spin_lock_irqsave(&base->lock, flags); | ||
538 | csr = sbus_readl(base->regs + APCCSR); | ||
539 | test = APC_GENL_INT | APC_PLAY_INT | APC_XINT_ENA | | ||
540 | APC_XINT_PLAY | APC_XINT_PEMP | APC_XINT_GENL | | ||
541 | APC_XINT_PENA; | ||
542 | if ( base->dir == APC_RECORD ) | ||
543 | test = APC_GENL_INT | APC_CAPT_INT | APC_XINT_ENA | | ||
544 | APC_XINT_CAPT | APC_XINT_CEMP | APC_XINT_GENL; | ||
545 | csr |= test; | ||
546 | sbus_writel(csr, base->regs + APCCSR); | ||
547 | spin_unlock_irqrestore(&base->lock, flags); | ||
548 | } | ||
549 | |||
550 | void sbus_dma_enable(struct sbus_dma_info *base, int on) | ||
551 | { | ||
552 | unsigned long flags; | ||
553 | u32 csr, shift; | ||
554 | |||
555 | spin_lock_irqsave(&base->lock, flags); | ||
556 | if (!on) { | ||
557 | if (base->dir == APC_PLAY) { | ||
558 | sbus_writel(0, base->regs + base->dir + APCNVA); | ||
559 | sbus_writel(1, base->regs + base->dir + APCC); | ||
560 | } | ||
561 | else | ||
562 | { | ||
563 | sbus_writel(0, base->regs + base->dir + APCNC); | ||
564 | sbus_writel(0, base->regs + base->dir + APCVA); | ||
565 | } | ||
566 | } | ||
567 | udelay(500); | ||
568 | csr = sbus_readl(base->regs + APCCSR); | ||
569 | shift = 0; | ||
570 | if ( base->dir == APC_PLAY ) | ||
571 | shift = 1; | ||
572 | if (on) | ||
573 | csr &= ~(APC_CPAUSE << shift); | ||
574 | else | ||
575 | csr |= (APC_CPAUSE << shift); | ||
576 | sbus_writel(csr, base->regs + APCCSR); | ||
577 | if (on) | ||
578 | csr |= (APC_CDMA_READY << shift); | ||
579 | else | ||
580 | csr &= ~(APC_CDMA_READY << shift); | ||
581 | sbus_writel(csr, base->regs + APCCSR); | ||
582 | |||
583 | spin_unlock_irqrestore(&base->lock, flags); | ||
584 | } | ||
585 | |||
586 | unsigned int sbus_dma_addr(struct sbus_dma_info *base) | ||
587 | { | ||
588 | return sbus_readl(base->regs + base->dir + APCVA); | ||
589 | } | ||
590 | |||
591 | #endif | ||
592 | |||
593 | /* | ||
594 | * CS4231 detection / MCE routines | 508 | * CS4231 detection / MCE routines |
595 | */ | 509 | */ |
596 | 510 | ||
@@ -688,8 +602,7 @@ static void snd_cs4231_mce_down(cs4231_t *chip) | |||
688 | spin_unlock_irqrestore(&chip->lock, flags); | 602 | spin_unlock_irqrestore(&chip->lock, flags); |
689 | } | 603 | } |
690 | 604 | ||
691 | #ifdef EBUS_SUPPORT | 605 | static void snd_cs4231_advance_dma(struct cs4231_dma_control *dma_cont, snd_pcm_substream_t *substream, unsigned int *periods_sent) |
692 | static void snd_cs4231_ebus_advance_dma(struct ebus_dma_info *p, snd_pcm_substream_t *substream, unsigned int *periods_sent) | ||
693 | { | 606 | { |
694 | snd_pcm_runtime_t *runtime = substream->runtime; | 607 | snd_pcm_runtime_t *runtime = substream->runtime; |
695 | 608 | ||
@@ -700,89 +613,41 @@ static void snd_cs4231_ebus_advance_dma(struct ebus_dma_info *p, snd_pcm_substre | |||
700 | if (period_size >= (1 << 24)) | 613 | if (period_size >= (1 << 24)) |
701 | BUG(); | 614 | BUG(); |
702 | 615 | ||
703 | if (ebus_dma_request(p, runtime->dma_addr + offset, period_size)) | 616 | if (dma_cont->request(dma_cont, runtime->dma_addr + offset, period_size)) |
704 | return; | 617 | return; |
705 | (*periods_sent) = ((*periods_sent) + 1) % runtime->periods; | 618 | (*periods_sent) = ((*periods_sent) + 1) % runtime->periods; |
706 | } | 619 | } |
707 | } | 620 | } |
708 | #endif | ||
709 | |||
710 | #ifdef SBUS_SUPPORT | ||
711 | static void snd_cs4231_sbus_advance_dma(struct sbus_dma_info *p, snd_pcm_substream_t *substream, unsigned int *periods_sent) | ||
712 | { | ||
713 | snd_pcm_runtime_t *runtime = substream->runtime; | ||
714 | |||
715 | while (1) { | ||
716 | unsigned int period_size = snd_pcm_lib_period_bytes(substream); | ||
717 | unsigned int offset = period_size * (*periods_sent); | ||
718 | |||
719 | if (period_size > 0xffff + 1) | ||
720 | BUG(); | ||
721 | |||
722 | if (sbus_dma_request(p, runtime->dma_addr + offset, period_size)) | ||
723 | return; | ||
724 | (*periods_sent) = (*periods_sent + 1) % runtime->periods; | ||
725 | } | ||
726 | } | ||
727 | #endif | ||
728 | 621 | ||
729 | static void cs4231_dma_trigger(snd_pcm_substream_t *substream, unsigned int what, int on) | 622 | static void cs4231_dma_trigger(snd_pcm_substream_t *substream, unsigned int what, int on) |
730 | { | 623 | { |
731 | cs4231_t *chip = snd_pcm_substream_chip(substream); | 624 | cs4231_t *chip = snd_pcm_substream_chip(substream); |
625 | cs4231_dma_control_t *dma_cont; | ||
732 | 626 | ||
733 | #ifdef EBUS_SUPPORT | ||
734 | if (chip->flags & CS4231_FLAG_EBUS) { | ||
735 | if (what & CS4231_PLAYBACK_ENABLE) { | ||
736 | if (on) { | ||
737 | ebus_dma_prepare(&chip->eb2p, 0); | ||
738 | ebus_dma_enable(&chip->eb2p, 1); | ||
739 | snd_cs4231_ebus_advance_dma(&chip->eb2p, | ||
740 | chip->playback_substream, | ||
741 | &chip->p_periods_sent); | ||
742 | } else { | ||
743 | ebus_dma_enable(&chip->eb2p, 0); | ||
744 | } | ||
745 | } | ||
746 | if (what & CS4231_RECORD_ENABLE) { | ||
747 | if (on) { | ||
748 | ebus_dma_prepare(&chip->eb2c, 1); | ||
749 | ebus_dma_enable(&chip->eb2c, 1); | ||
750 | snd_cs4231_ebus_advance_dma(&chip->eb2c, | ||
751 | chip->capture_substream, | ||
752 | &chip->c_periods_sent); | ||
753 | } else { | ||
754 | ebus_dma_enable(&chip->eb2c, 0); | ||
755 | } | ||
756 | } | ||
757 | } else { | ||
758 | #endif | ||
759 | #ifdef SBUS_SUPPORT | ||
760 | if (what & CS4231_PLAYBACK_ENABLE) { | 627 | if (what & CS4231_PLAYBACK_ENABLE) { |
628 | dma_cont = &chip->p_dma; | ||
761 | if (on) { | 629 | if (on) { |
762 | sbus_dma_prepare(&chip->sb2p); | 630 | dma_cont->prepare(dma_cont, 0); |
763 | sbus_dma_enable(&chip->sb2p, 1); | 631 | dma_cont->enable(dma_cont, 1); |
764 | snd_cs4231_sbus_advance_dma(&chip->sb2p, | 632 | snd_cs4231_advance_dma(dma_cont, |
765 | chip->playback_substream, | 633 | chip->playback_substream, |
766 | &chip->p_periods_sent); | 634 | &chip->p_periods_sent); |
767 | } else { | 635 | } else { |
768 | sbus_dma_enable(&chip->sb2p, 0); | 636 | dma_cont->enable(dma_cont, 0); |
769 | } | 637 | } |
770 | } | 638 | } |
771 | if (what & CS4231_RECORD_ENABLE) { | 639 | if (what & CS4231_RECORD_ENABLE) { |
640 | dma_cont = &chip->c_dma; | ||
772 | if (on) { | 641 | if (on) { |
773 | sbus_dma_prepare(&chip->sb2c); | 642 | dma_cont->prepare(dma_cont, 1); |
774 | sbus_dma_enable(&chip->sb2c, 1); | 643 | dma_cont->enable(dma_cont, 1); |
775 | snd_cs4231_sbus_advance_dma(&chip->sb2c, | 644 | snd_cs4231_advance_dma(dma_cont, |
776 | chip->capture_substream, | 645 | chip->capture_substream, |
777 | &chip->c_periods_sent); | 646 | &chip->c_periods_sent); |
778 | } else { | 647 | } else { |
779 | sbus_dma_enable(&chip->sb2c, 0); | 648 | dma_cont->enable(dma_cont, 0); |
780 | } | 649 | } |
781 | } | 650 | } |
782 | #endif | ||
783 | #ifdef EBUS_SUPPORT | ||
784 | } | ||
785 | #endif | ||
786 | } | 651 | } |
787 | 652 | ||
788 | static int snd_cs4231_trigger(snd_pcm_substream_t *substream, int cmd) | 653 | static int snd_cs4231_trigger(snd_pcm_substream_t *substream, int cmd) |
@@ -1273,140 +1138,55 @@ static void snd_cs4231_overrange(cs4231_t *chip) | |||
1273 | chip->capture_substream->runtime->overrange++; | 1138 | chip->capture_substream->runtime->overrange++; |
1274 | } | 1139 | } |
1275 | 1140 | ||
1276 | #ifdef SBUS_SUPPORT | 1141 | static void snd_cs4231_play_callback(cs4231_t *cookie) |
1277 | static irqreturn_t snd_cs4231_sbus_interrupt(int irq, void *dev_id, struct pt_regs *regs) | ||
1278 | { | ||
1279 | unsigned long flags; | ||
1280 | unsigned char status; | ||
1281 | u32 csr; | ||
1282 | cs4231_t *chip = dev_id; | ||
1283 | |||
1284 | /*This is IRQ is not raised by the cs4231*/ | ||
1285 | if (!(__cs4231_readb(chip, CS4231P(chip, STATUS)) & CS4231_GLOBALIRQ)) | ||
1286 | return IRQ_NONE; | ||
1287 | |||
1288 | /* ACK the APC interrupt. */ | ||
1289 | csr = sbus_readl(chip->port + APCCSR); | ||
1290 | |||
1291 | sbus_writel(csr, chip->port + APCCSR); | ||
1292 | |||
1293 | if ((chip->image[CS4231_IFACE_CTRL] & CS4231_PLAYBACK_ENABLE) && | ||
1294 | (csr & APC_PLAY_INT) && | ||
1295 | (csr & APC_XINT_PNVA) && | ||
1296 | !(csr & APC_XINT_EMPT)) { | ||
1297 | snd_pcm_period_elapsed(chip->playback_substream); | ||
1298 | snd_cs4231_sbus_advance_dma(&chip->sb2p, chip->playback_substream, | ||
1299 | &chip->p_periods_sent); | ||
1300 | } | ||
1301 | |||
1302 | if ((chip->image[CS4231_IFACE_CTRL] & CS4231_RECORD_ENABLE) && | ||
1303 | (csr & APC_CAPT_INT) && | ||
1304 | (csr & APC_XINT_CNVA) && | ||
1305 | !(csr & APC_XINT_EMPT)) { | ||
1306 | snd_pcm_period_elapsed(chip->capture_substream); | ||
1307 | snd_cs4231_sbus_advance_dma(&chip->sb2c,chip->capture_substream, | ||
1308 | &chip->c_periods_sent); | ||
1309 | } | ||
1310 | |||
1311 | status = snd_cs4231_in(chip, CS4231_IRQ_STATUS); | ||
1312 | |||
1313 | if (status & CS4231_TIMER_IRQ) { | ||
1314 | if (chip->timer) | ||
1315 | snd_timer_interrupt(chip->timer, chip->timer->sticks); | ||
1316 | } | ||
1317 | |||
1318 | if (status & CS4231_RECORD_IRQ) | ||
1319 | snd_cs4231_overrange(chip); | ||
1320 | |||
1321 | /* ACK the CS4231 interrupt. */ | ||
1322 | spin_lock_irqsave(&chip->lock, flags); | ||
1323 | snd_cs4231_outm(chip, CS4231_IRQ_STATUS, ~CS4231_ALL_IRQS | ~status, 0); | ||
1324 | spin_unlock_irqrestore(&chip->lock, flags); | ||
1325 | |||
1326 | return 0; | ||
1327 | } | ||
1328 | #endif | ||
1329 | |||
1330 | #ifdef EBUS_SUPPORT | ||
1331 | static void snd_cs4231_ebus_play_callback(struct ebus_dma_info *p, int event, void *cookie) | ||
1332 | { | 1142 | { |
1333 | cs4231_t *chip = cookie; | 1143 | cs4231_t *chip = cookie; |
1334 | 1144 | ||
1335 | if (chip->image[CS4231_IFACE_CTRL] & CS4231_PLAYBACK_ENABLE) { | 1145 | if (chip->image[CS4231_IFACE_CTRL] & CS4231_PLAYBACK_ENABLE) { |
1336 | snd_pcm_period_elapsed(chip->playback_substream); | 1146 | snd_pcm_period_elapsed(chip->playback_substream); |
1337 | snd_cs4231_ebus_advance_dma(p, chip->playback_substream, | 1147 | snd_cs4231_advance_dma(&chip->p_dma, chip->playback_substream, |
1338 | &chip->p_periods_sent); | 1148 | &chip->p_periods_sent); |
1339 | } | 1149 | } |
1340 | } | 1150 | } |
1341 | 1151 | ||
1342 | static void snd_cs4231_ebus_capture_callback(struct ebus_dma_info *p, int event, void *cookie) | 1152 | static void snd_cs4231_capture_callback(cs4231_t *cookie) |
1343 | { | 1153 | { |
1344 | cs4231_t *chip = cookie; | 1154 | cs4231_t *chip = cookie; |
1345 | 1155 | ||
1346 | if (chip->image[CS4231_IFACE_CTRL] & CS4231_RECORD_ENABLE) { | 1156 | if (chip->image[CS4231_IFACE_CTRL] & CS4231_RECORD_ENABLE) { |
1347 | snd_pcm_period_elapsed(chip->capture_substream); | 1157 | snd_pcm_period_elapsed(chip->capture_substream); |
1348 | snd_cs4231_ebus_advance_dma(p, chip->capture_substream, | 1158 | snd_cs4231_advance_dma(&chip->c_dma, chip->capture_substream, |
1349 | &chip->c_periods_sent); | 1159 | &chip->c_periods_sent); |
1350 | } | 1160 | } |
1351 | } | 1161 | } |
1352 | #endif | ||
1353 | 1162 | ||
1354 | static snd_pcm_uframes_t snd_cs4231_playback_pointer(snd_pcm_substream_t *substream) | 1163 | static snd_pcm_uframes_t snd_cs4231_playback_pointer(snd_pcm_substream_t *substream) |
1355 | { | 1164 | { |
1356 | cs4231_t *chip = snd_pcm_substream_chip(substream); | 1165 | cs4231_t *chip = snd_pcm_substream_chip(substream); |
1166 | cs4231_dma_control_t *dma_cont = &chip->p_dma; | ||
1357 | size_t ptr; | 1167 | size_t ptr; |
1358 | #ifdef EBUS_SUPPORT | ||
1359 | size_t residue, period_bytes; | ||
1360 | #endif | ||
1361 | 1168 | ||
1362 | if (!(chip->image[CS4231_IFACE_CTRL] & CS4231_PLAYBACK_ENABLE)) | 1169 | if (!(chip->image[CS4231_IFACE_CTRL] & CS4231_PLAYBACK_ENABLE)) |
1363 | return 0; | 1170 | return 0; |
1364 | #ifdef EBUS_SUPPORT | 1171 | ptr = dma_cont->address(dma_cont); |
1365 | period_bytes = snd_pcm_lib_period_bytes(substream); | 1172 | if (ptr != 0) |
1366 | ptr = period_bytes * chip->p_periods_sent; | 1173 | ptr -= substream->runtime->dma_addr; |
1367 | if (chip->flags & CS4231_FLAG_EBUS) { | 1174 | |
1368 | residue = ebus_dma_residue(&chip->eb2p); | ||
1369 | ptr += period_bytes - residue; | ||
1370 | } else { | ||
1371 | #endif | ||
1372 | #ifdef SBUS_SUPPORT | ||
1373 | ptr = sbus_dma_addr(&chip->sb2p); | ||
1374 | if (ptr != 0) | ||
1375 | ptr -= substream->runtime->dma_addr; | ||
1376 | #endif | ||
1377 | #ifdef EBUS_SUPPORT | ||
1378 | } | ||
1379 | #endif | ||
1380 | |||
1381 | return bytes_to_frames(substream->runtime, ptr); | 1175 | return bytes_to_frames(substream->runtime, ptr); |
1382 | } | 1176 | } |
1383 | 1177 | ||
1384 | static snd_pcm_uframes_t snd_cs4231_capture_pointer(snd_pcm_substream_t * substream) | 1178 | static snd_pcm_uframes_t snd_cs4231_capture_pointer(snd_pcm_substream_t * substream) |
1385 | { | 1179 | { |
1386 | cs4231_t *chip = snd_pcm_substream_chip(substream); | 1180 | cs4231_t *chip = snd_pcm_substream_chip(substream); |
1181 | cs4231_dma_control_t *dma_cont = &chip->c_dma; | ||
1387 | size_t ptr; | 1182 | size_t ptr; |
1388 | #ifdef EBUS_SUPPORT | ||
1389 | size_t residue, period_bytes; | ||
1390 | #endif | ||
1391 | 1183 | ||
1392 | if (!(chip->image[CS4231_IFACE_CTRL] & CS4231_RECORD_ENABLE)) | 1184 | if (!(chip->image[CS4231_IFACE_CTRL] & CS4231_RECORD_ENABLE)) |
1393 | return 0; | 1185 | return 0; |
1394 | #ifdef EBUS_SUPPORT | 1186 | ptr = dma_cont->address(dma_cont); |
1395 | period_bytes = snd_pcm_lib_period_bytes(substream); | 1187 | if (ptr != 0) |
1396 | ptr = period_bytes * chip->c_periods_sent; | 1188 | ptr -= substream->runtime->dma_addr; |
1397 | if (chip->flags & CS4231_FLAG_EBUS) { | 1189 | |
1398 | residue = ebus_dma_residue(&chip->eb2c); | ||
1399 | ptr += period_bytes - residue; | ||
1400 | } else { | ||
1401 | #endif | ||
1402 | #ifdef SBUS_SUPPORT | ||
1403 | ptr = sbus_dma_addr(&chip->sb2c); | ||
1404 | if (ptr != 0) | ||
1405 | ptr -= substream->runtime->dma_addr; | ||
1406 | #endif | ||
1407 | #ifdef EBUS_SUPPORT | ||
1408 | } | ||
1409 | #endif | ||
1410 | return bytes_to_frames(substream->runtime, ptr); | 1190 | return bytes_to_frames(substream->runtime, ptr); |
1411 | } | 1191 | } |
1412 | 1192 | ||
@@ -1442,30 +1222,8 @@ static int snd_cs4231_probe(cs4231_t *chip) | |||
1442 | spin_lock_irqsave(&chip->lock, flags); | 1222 | spin_lock_irqsave(&chip->lock, flags); |
1443 | 1223 | ||
1444 | 1224 | ||
1445 | /* Reset DMA engine. */ | 1225 | /* Reset DMA engine (sbus only). */ |
1446 | #ifdef EBUS_SUPPORT | 1226 | chip->p_dma.reset(chip); |
1447 | if (chip->flags & CS4231_FLAG_EBUS) { | ||
1448 | /* Done by ebus_dma_register */ | ||
1449 | } else { | ||
1450 | #endif | ||
1451 | #ifdef SBUS_SUPPORT | ||
1452 | sbus_writel(APC_CHIP_RESET, chip->port + APCCSR); | ||
1453 | sbus_writel(0x00, chip->port + APCCSR); | ||
1454 | sbus_writel(sbus_readl(chip->port + APCCSR) | APC_CDC_RESET, | ||
1455 | chip->port + APCCSR); | ||
1456 | |||
1457 | udelay(20); | ||
1458 | |||
1459 | sbus_writel(sbus_readl(chip->port + APCCSR) & ~APC_CDC_RESET, | ||
1460 | chip->port + APCCSR); | ||
1461 | sbus_writel(sbus_readl(chip->port + APCCSR) | (APC_XINT_ENA | | ||
1462 | APC_XINT_PENA | | ||
1463 | APC_XINT_CENA), | ||
1464 | chip->port + APCCSR); | ||
1465 | #endif | ||
1466 | #ifdef EBUS_SUPPORT | ||
1467 | } | ||
1468 | #endif | ||
1469 | 1227 | ||
1470 | __cs4231_readb(chip, CS4231P(chip, STATUS)); /* clear any pendings IRQ */ | 1228 | __cs4231_readb(chip, CS4231P(chip, STATUS)); /* clear any pendings IRQ */ |
1471 | __cs4231_writeb(chip, 0, CS4231P(chip, STATUS)); | 1229 | __cs4231_writeb(chip, 0, CS4231P(chip, STATUS)); |
@@ -1585,8 +1343,8 @@ static int snd_cs4231_playback_close(snd_pcm_substream_t *substream) | |||
1585 | { | 1343 | { |
1586 | cs4231_t *chip = snd_pcm_substream_chip(substream); | 1344 | cs4231_t *chip = snd_pcm_substream_chip(substream); |
1587 | 1345 | ||
1588 | chip->playback_substream = NULL; | ||
1589 | snd_cs4231_close(chip, CS4231_MODE_PLAY); | 1346 | snd_cs4231_close(chip, CS4231_MODE_PLAY); |
1347 | chip->playback_substream = NULL; | ||
1590 | 1348 | ||
1591 | return 0; | 1349 | return 0; |
1592 | } | 1350 | } |
@@ -1595,8 +1353,8 @@ static int snd_cs4231_capture_close(snd_pcm_substream_t *substream) | |||
1595 | { | 1353 | { |
1596 | cs4231_t *chip = snd_pcm_substream_chip(substream); | 1354 | cs4231_t *chip = snd_pcm_substream_chip(substream); |
1597 | 1355 | ||
1598 | chip->capture_substream = NULL; | ||
1599 | snd_cs4231_close(chip, CS4231_MODE_RECORD); | 1356 | snd_cs4231_close(chip, CS4231_MODE_RECORD); |
1357 | chip->capture_substream = NULL; | ||
1600 | 1358 | ||
1601 | return 0; | 1359 | return 0; |
1602 | } | 1360 | } |
@@ -1651,21 +1409,7 @@ int snd_cs4231_pcm(cs4231_t *chip) | |||
1651 | pcm->info_flags = SNDRV_PCM_INFO_JOINT_DUPLEX; | 1409 | pcm->info_flags = SNDRV_PCM_INFO_JOINT_DUPLEX; |
1652 | strcpy(pcm->name, "CS4231"); | 1410 | strcpy(pcm->name, "CS4231"); |
1653 | 1411 | ||
1654 | #ifdef EBUS_SUPPORT | 1412 | chip->p_dma.preallocate(chip, pcm); |
1655 | if (chip->flags & CS4231_FLAG_EBUS) { | ||
1656 | snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV, | ||
1657 | snd_dma_pci_data(chip->dev_u.pdev), | ||
1658 | 64*1024, 128*1024); | ||
1659 | } else { | ||
1660 | #endif | ||
1661 | #ifdef SBUS_SUPPORT | ||
1662 | snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_SBUS, | ||
1663 | snd_dma_sbus_data(chip->dev_u.sdev), | ||
1664 | 64*1024, 128*1024); | ||
1665 | #endif | ||
1666 | #ifdef EBUS_SUPPORT | ||
1667 | } | ||
1668 | #endif | ||
1669 | 1413 | ||
1670 | chip->pcm = pcm; | 1414 | chip->pcm = pcm; |
1671 | 1415 | ||
@@ -2022,6 +1766,180 @@ out_err: | |||
2022 | } | 1766 | } |
2023 | 1767 | ||
2024 | #ifdef SBUS_SUPPORT | 1768 | #ifdef SBUS_SUPPORT |
1769 | |||
1770 | static irqreturn_t snd_cs4231_sbus_interrupt(int irq, void *dev_id, struct pt_regs *regs) | ||
1771 | { | ||
1772 | unsigned long flags; | ||
1773 | unsigned char status; | ||
1774 | u32 csr; | ||
1775 | cs4231_t *chip = dev_id; | ||
1776 | |||
1777 | /*This is IRQ is not raised by the cs4231*/ | ||
1778 | if (!(__cs4231_readb(chip, CS4231P(chip, STATUS)) & CS4231_GLOBALIRQ)) | ||
1779 | return IRQ_NONE; | ||
1780 | |||
1781 | /* ACK the APC interrupt. */ | ||
1782 | csr = sbus_readl(chip->port + APCCSR); | ||
1783 | |||
1784 | sbus_writel(csr, chip->port + APCCSR); | ||
1785 | |||
1786 | if ((csr & APC_PDMA_READY) && | ||
1787 | (csr & APC_PLAY_INT) && | ||
1788 | (csr & APC_XINT_PNVA) && | ||
1789 | !(csr & APC_XINT_EMPT)) | ||
1790 | snd_cs4231_play_callback(chip); | ||
1791 | |||
1792 | if ((csr & APC_CDMA_READY) && | ||
1793 | (csr & APC_CAPT_INT) && | ||
1794 | (csr & APC_XINT_CNVA) && | ||
1795 | !(csr & APC_XINT_EMPT)) | ||
1796 | snd_cs4231_capture_callback(chip); | ||
1797 | |||
1798 | status = snd_cs4231_in(chip, CS4231_IRQ_STATUS); | ||
1799 | |||
1800 | if (status & CS4231_TIMER_IRQ) { | ||
1801 | if (chip->timer) | ||
1802 | snd_timer_interrupt(chip->timer, chip->timer->sticks); | ||
1803 | } | ||
1804 | |||
1805 | if ((status & CS4231_RECORD_IRQ) && (csr & APC_CDMA_READY)) | ||
1806 | snd_cs4231_overrange(chip); | ||
1807 | |||
1808 | /* ACK the CS4231 interrupt. */ | ||
1809 | spin_lock_irqsave(&chip->lock, flags); | ||
1810 | snd_cs4231_outm(chip, CS4231_IRQ_STATUS, ~CS4231_ALL_IRQS | ~status, 0); | ||
1811 | spin_unlock_irqrestore(&chip->lock, flags); | ||
1812 | |||
1813 | return 0; | ||
1814 | } | ||
1815 | |||
1816 | /* | ||
1817 | * SBUS DMA routines | ||
1818 | */ | ||
1819 | |||
1820 | int sbus_dma_request(struct cs4231_dma_control *dma_cont, dma_addr_t bus_addr, size_t len) | ||
1821 | { | ||
1822 | unsigned long flags; | ||
1823 | u32 test, csr; | ||
1824 | int err; | ||
1825 | sbus_dma_info_t *base = &dma_cont->sbus_info; | ||
1826 | |||
1827 | if (len >= (1 << 24)) | ||
1828 | return -EINVAL; | ||
1829 | spin_lock_irqsave(&base->lock, flags); | ||
1830 | csr = sbus_readl(base->regs + APCCSR); | ||
1831 | err = -EINVAL; | ||
1832 | test = APC_CDMA_READY; | ||
1833 | if ( base->dir == APC_PLAY ) | ||
1834 | test = APC_PDMA_READY; | ||
1835 | if (!(csr & test)) | ||
1836 | goto out; | ||
1837 | err = -EBUSY; | ||
1838 | csr = sbus_readl(base->regs + APCCSR); | ||
1839 | test = APC_XINT_CNVA; | ||
1840 | if ( base->dir == APC_PLAY ) | ||
1841 | test = APC_XINT_PNVA; | ||
1842 | if (!(csr & test)) | ||
1843 | goto out; | ||
1844 | err = 0; | ||
1845 | sbus_writel(bus_addr, base->regs + base->dir + APCNVA); | ||
1846 | sbus_writel(len, base->regs + base->dir + APCNC); | ||
1847 | out: | ||
1848 | spin_unlock_irqrestore(&base->lock, flags); | ||
1849 | return err; | ||
1850 | } | ||
1851 | |||
1852 | void sbus_dma_prepare(struct cs4231_dma_control *dma_cont, int d) | ||
1853 | { | ||
1854 | unsigned long flags; | ||
1855 | u32 csr, test; | ||
1856 | sbus_dma_info_t *base = &dma_cont->sbus_info; | ||
1857 | |||
1858 | spin_lock_irqsave(&base->lock, flags); | ||
1859 | csr = sbus_readl(base->regs + APCCSR); | ||
1860 | test = APC_GENL_INT | APC_PLAY_INT | APC_XINT_ENA | | ||
1861 | APC_XINT_PLAY | APC_XINT_PEMP | APC_XINT_GENL | | ||
1862 | APC_XINT_PENA; | ||
1863 | if ( base->dir == APC_RECORD ) | ||
1864 | test = APC_GENL_INT | APC_CAPT_INT | APC_XINT_ENA | | ||
1865 | APC_XINT_CAPT | APC_XINT_CEMP | APC_XINT_GENL; | ||
1866 | csr |= test; | ||
1867 | sbus_writel(csr, base->regs + APCCSR); | ||
1868 | spin_unlock_irqrestore(&base->lock, flags); | ||
1869 | } | ||
1870 | |||
1871 | void sbus_dma_enable(struct cs4231_dma_control *dma_cont, int on) | ||
1872 | { | ||
1873 | unsigned long flags; | ||
1874 | u32 csr, shift; | ||
1875 | sbus_dma_info_t *base = &dma_cont->sbus_info; | ||
1876 | |||
1877 | spin_lock_irqsave(&base->lock, flags); | ||
1878 | if (!on) { | ||
1879 | if (base->dir == APC_PLAY) { | ||
1880 | sbus_writel(0, base->regs + base->dir + APCNVA); | ||
1881 | sbus_writel(1, base->regs + base->dir + APCC); | ||
1882 | } | ||
1883 | else | ||
1884 | { | ||
1885 | sbus_writel(0, base->regs + base->dir + APCNC); | ||
1886 | sbus_writel(0, base->regs + base->dir + APCVA); | ||
1887 | } | ||
1888 | } | ||
1889 | udelay(600); | ||
1890 | csr = sbus_readl(base->regs + APCCSR); | ||
1891 | shift = 0; | ||
1892 | if ( base->dir == APC_PLAY ) | ||
1893 | shift = 1; | ||
1894 | if (on) | ||
1895 | csr &= ~(APC_CPAUSE << shift); | ||
1896 | else | ||
1897 | csr |= (APC_CPAUSE << shift); | ||
1898 | sbus_writel(csr, base->regs + APCCSR); | ||
1899 | if (on) | ||
1900 | csr |= (APC_CDMA_READY << shift); | ||
1901 | else | ||
1902 | csr &= ~(APC_CDMA_READY << shift); | ||
1903 | sbus_writel(csr, base->regs + APCCSR); | ||
1904 | |||
1905 | spin_unlock_irqrestore(&base->lock, flags); | ||
1906 | } | ||
1907 | |||
1908 | unsigned int sbus_dma_addr(struct cs4231_dma_control *dma_cont) | ||
1909 | { | ||
1910 | sbus_dma_info_t *base = &dma_cont->sbus_info; | ||
1911 | |||
1912 | return sbus_readl(base->regs + base->dir + APCVA); | ||
1913 | } | ||
1914 | |||
1915 | void sbus_dma_reset(cs4231_t *chip) | ||
1916 | { | ||
1917 | sbus_writel(APC_CHIP_RESET, chip->port + APCCSR); | ||
1918 | sbus_writel(0x00, chip->port + APCCSR); | ||
1919 | sbus_writel(sbus_readl(chip->port + APCCSR) | APC_CDC_RESET, | ||
1920 | chip->port + APCCSR); | ||
1921 | |||
1922 | udelay(20); | ||
1923 | |||
1924 | sbus_writel(sbus_readl(chip->port + APCCSR) & ~APC_CDC_RESET, | ||
1925 | chip->port + APCCSR); | ||
1926 | sbus_writel(sbus_readl(chip->port + APCCSR) | (APC_XINT_ENA | | ||
1927 | APC_XINT_PENA | | ||
1928 | APC_XINT_CENA), | ||
1929 | chip->port + APCCSR); | ||
1930 | } | ||
1931 | |||
1932 | void sbus_dma_preallocate(cs4231_t *chip, snd_pcm_t *pcm) | ||
1933 | { | ||
1934 | snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_SBUS, | ||
1935 | snd_dma_sbus_data(chip->dev_u.sdev), | ||
1936 | 64*1024, 128*1024); | ||
1937 | } | ||
1938 | |||
1939 | /* | ||
1940 | * Init and exit routines | ||
1941 | */ | ||
1942 | |||
2025 | static int snd_cs4231_sbus_free(cs4231_t *chip) | 1943 | static int snd_cs4231_sbus_free(cs4231_t *chip) |
2026 | { | 1944 | { |
2027 | if (chip->irq[0]) | 1945 | if (chip->irq[0]) |
@@ -2063,8 +1981,8 @@ static int __init snd_cs4231_sbus_create(snd_card_t *card, | |||
2063 | return -ENOMEM; | 1981 | return -ENOMEM; |
2064 | 1982 | ||
2065 | spin_lock_init(&chip->lock); | 1983 | spin_lock_init(&chip->lock); |
2066 | spin_lock_init(&chip->sb2c.lock); | 1984 | spin_lock_init(&chip->c_dma.sbus_info.lock); |
2067 | spin_lock_init(&chip->sb2p.lock); | 1985 | spin_lock_init(&chip->p_dma.sbus_info.lock); |
2068 | init_MUTEX(&chip->mce_mutex); | 1986 | init_MUTEX(&chip->mce_mutex); |
2069 | init_MUTEX(&chip->open_mutex); | 1987 | init_MUTEX(&chip->open_mutex); |
2070 | chip->card = card; | 1988 | chip->card = card; |
@@ -2080,10 +1998,24 @@ static int __init snd_cs4231_sbus_create(snd_card_t *card, | |||
2080 | return -EIO; | 1998 | return -EIO; |
2081 | } | 1999 | } |
2082 | 2000 | ||
2083 | chip->sb2c.regs = chip->port; | 2001 | chip->c_dma.sbus_info.regs = chip->port; |
2084 | chip->sb2p.regs = chip->port; | 2002 | chip->p_dma.sbus_info.regs = chip->port; |
2085 | chip->sb2c.dir = APC_RECORD; | 2003 | chip->c_dma.sbus_info.dir = APC_RECORD; |
2086 | chip->sb2p.dir = APC_PLAY; | 2004 | chip->p_dma.sbus_info.dir = APC_PLAY; |
2005 | |||
2006 | chip->p_dma.prepare = sbus_dma_prepare; | ||
2007 | chip->p_dma.enable = sbus_dma_enable; | ||
2008 | chip->p_dma.request = sbus_dma_request; | ||
2009 | chip->p_dma.address = sbus_dma_addr; | ||
2010 | chip->p_dma.reset = sbus_dma_reset; | ||
2011 | chip->p_dma.preallocate = sbus_dma_preallocate; | ||
2012 | |||
2013 | chip->c_dma.prepare = sbus_dma_prepare; | ||
2014 | chip->c_dma.enable = sbus_dma_enable; | ||
2015 | chip->c_dma.request = sbus_dma_request; | ||
2016 | chip->c_dma.address = sbus_dma_addr; | ||
2017 | chip->c_dma.reset = sbus_dma_reset; | ||
2018 | chip->c_dma.preallocate = sbus_dma_preallocate; | ||
2087 | 2019 | ||
2088 | if (request_irq(sdev->irqs[0], snd_cs4231_sbus_interrupt, | 2020 | if (request_irq(sdev->irqs[0], snd_cs4231_sbus_interrupt, |
2089 | SA_SHIRQ, "cs4231", chip)) { | 2021 | SA_SHIRQ, "cs4231", chip)) { |
@@ -2138,15 +2070,70 @@ static int cs4231_sbus_attach(struct sbus_dev *sdev) | |||
2138 | #endif | 2070 | #endif |
2139 | 2071 | ||
2140 | #ifdef EBUS_SUPPORT | 2072 | #ifdef EBUS_SUPPORT |
2073 | |||
2074 | static void snd_cs4231_ebus_play_callback(struct ebus_dma_info *p, int event, void *cookie) | ||
2075 | { | ||
2076 | cs4231_t *chip = cookie; | ||
2077 | |||
2078 | snd_cs4231_play_callback(chip); | ||
2079 | } | ||
2080 | |||
2081 | static void snd_cs4231_ebus_capture_callback(struct ebus_dma_info *p, int event, void *cookie) | ||
2082 | { | ||
2083 | cs4231_t *chip = cookie; | ||
2084 | |||
2085 | snd_cs4231_capture_callback(chip); | ||
2086 | } | ||
2087 | |||
2088 | /* | ||
2089 | * EBUS DMA wrappers | ||
2090 | */ | ||
2091 | |||
2092 | int _ebus_dma_request(struct cs4231_dma_control *dma_cont, dma_addr_t bus_addr, size_t len) | ||
2093 | { | ||
2094 | return ebus_dma_request(&dma_cont->ebus_info, bus_addr, len); | ||
2095 | } | ||
2096 | |||
2097 | void _ebus_dma_enable(struct cs4231_dma_control *dma_cont, int on) | ||
2098 | { | ||
2099 | ebus_dma_enable(&dma_cont->ebus_info, on); | ||
2100 | } | ||
2101 | |||
2102 | void _ebus_dma_prepare(struct cs4231_dma_control *dma_cont, int dir) | ||
2103 | { | ||
2104 | ebus_dma_prepare(&dma_cont->ebus_info, dir); | ||
2105 | } | ||
2106 | |||
2107 | unsigned int _ebus_dma_addr(struct cs4231_dma_control *dma_cont) | ||
2108 | { | ||
2109 | return ebus_dma_addr(&dma_cont->ebus_info); | ||
2110 | } | ||
2111 | |||
2112 | void _ebus_dma_reset(cs4231_t *chip) | ||
2113 | { | ||
2114 | return; | ||
2115 | } | ||
2116 | |||
2117 | void _ebus_dma_preallocate(cs4231_t *chip, snd_pcm_t *pcm) | ||
2118 | { | ||
2119 | snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV, | ||
2120 | snd_dma_pci_data(chip->dev_u.pdev), | ||
2121 | 64*1024, 128*1024); | ||
2122 | } | ||
2123 | |||
2124 | /* | ||
2125 | * Init and exit routines | ||
2126 | */ | ||
2127 | |||
2141 | static int snd_cs4231_ebus_free(cs4231_t *chip) | 2128 | static int snd_cs4231_ebus_free(cs4231_t *chip) |
2142 | { | 2129 | { |
2143 | if (chip->eb2c.regs) { | 2130 | if (chip->c_dma.ebus_info.regs) { |
2144 | ebus_dma_unregister(&chip->eb2c); | 2131 | ebus_dma_unregister(&chip->c_dma.ebus_info); |
2145 | iounmap(chip->eb2c.regs); | 2132 | iounmap(chip->c_dma.ebus_info.regs); |
2146 | } | 2133 | } |
2147 | if (chip->eb2p.regs) { | 2134 | if (chip->p_dma.ebus_info.regs) { |
2148 | ebus_dma_unregister(&chip->eb2p); | 2135 | ebus_dma_unregister(&chip->p_dma.ebus_info); |
2149 | iounmap(chip->eb2p.regs); | 2136 | iounmap(chip->p_dma.ebus_info.regs); |
2150 | } | 2137 | } |
2151 | 2138 | ||
2152 | if (chip->port) | 2139 | if (chip->port) |
@@ -2184,8 +2171,8 @@ static int __init snd_cs4231_ebus_create(snd_card_t *card, | |||
2184 | return -ENOMEM; | 2171 | return -ENOMEM; |
2185 | 2172 | ||
2186 | spin_lock_init(&chip->lock); | 2173 | spin_lock_init(&chip->lock); |
2187 | spin_lock_init(&chip->eb2c.lock); | 2174 | spin_lock_init(&chip->c_dma.ebus_info.lock); |
2188 | spin_lock_init(&chip->eb2p.lock); | 2175 | spin_lock_init(&chip->p_dma.ebus_info.lock); |
2189 | init_MUTEX(&chip->mce_mutex); | 2176 | init_MUTEX(&chip->mce_mutex); |
2190 | init_MUTEX(&chip->open_mutex); | 2177 | init_MUTEX(&chip->open_mutex); |
2191 | chip->flags |= CS4231_FLAG_EBUS; | 2178 | chip->flags |= CS4231_FLAG_EBUS; |
@@ -2193,43 +2180,57 @@ static int __init snd_cs4231_ebus_create(snd_card_t *card, | |||
2193 | chip->dev_u.pdev = edev->bus->self; | 2180 | chip->dev_u.pdev = edev->bus->self; |
2194 | memcpy(&chip->image, &snd_cs4231_original_image, | 2181 | memcpy(&chip->image, &snd_cs4231_original_image, |
2195 | sizeof(snd_cs4231_original_image)); | 2182 | sizeof(snd_cs4231_original_image)); |
2196 | strcpy(chip->eb2c.name, "cs4231(capture)"); | 2183 | strcpy(chip->c_dma.ebus_info.name, "cs4231(capture)"); |
2197 | chip->eb2c.flags = EBUS_DMA_FLAG_USE_EBDMA_HANDLER; | 2184 | chip->c_dma.ebus_info.flags = EBUS_DMA_FLAG_USE_EBDMA_HANDLER; |
2198 | chip->eb2c.callback = snd_cs4231_ebus_capture_callback; | 2185 | chip->c_dma.ebus_info.callback = snd_cs4231_ebus_capture_callback; |
2199 | chip->eb2c.client_cookie = chip; | 2186 | chip->c_dma.ebus_info.client_cookie = chip; |
2200 | chip->eb2c.irq = edev->irqs[0]; | 2187 | chip->c_dma.ebus_info.irq = edev->irqs[0]; |
2201 | strcpy(chip->eb2p.name, "cs4231(play)"); | 2188 | strcpy(chip->p_dma.ebus_info.name, "cs4231(play)"); |
2202 | chip->eb2p.flags = EBUS_DMA_FLAG_USE_EBDMA_HANDLER; | 2189 | chip->p_dma.ebus_info.flags = EBUS_DMA_FLAG_USE_EBDMA_HANDLER; |
2203 | chip->eb2p.callback = snd_cs4231_ebus_play_callback; | 2190 | chip->p_dma.ebus_info.callback = snd_cs4231_ebus_play_callback; |
2204 | chip->eb2p.client_cookie = chip; | 2191 | chip->p_dma.ebus_info.client_cookie = chip; |
2205 | chip->eb2p.irq = edev->irqs[1]; | 2192 | chip->p_dma.ebus_info.irq = edev->irqs[1]; |
2193 | |||
2194 | chip->p_dma.prepare = _ebus_dma_prepare; | ||
2195 | chip->p_dma.enable = _ebus_dma_enable; | ||
2196 | chip->p_dma.request = _ebus_dma_request; | ||
2197 | chip->p_dma.address = _ebus_dma_addr; | ||
2198 | chip->p_dma.reset = _ebus_dma_reset; | ||
2199 | chip->p_dma.preallocate = _ebus_dma_preallocate; | ||
2200 | |||
2201 | chip->c_dma.prepare = _ebus_dma_prepare; | ||
2202 | chip->c_dma.enable = _ebus_dma_enable; | ||
2203 | chip->c_dma.request = _ebus_dma_request; | ||
2204 | chip->c_dma.address = _ebus_dma_addr; | ||
2205 | chip->c_dma.reset = _ebus_dma_reset; | ||
2206 | chip->c_dma.preallocate = _ebus_dma_preallocate; | ||
2206 | 2207 | ||
2207 | chip->port = ioremap(edev->resource[0].start, 0x10); | 2208 | chip->port = ioremap(edev->resource[0].start, 0x10); |
2208 | chip->eb2p.regs = ioremap(edev->resource[1].start, 0x10); | 2209 | chip->p_dma.ebus_info.regs = ioremap(edev->resource[1].start, 0x10); |
2209 | chip->eb2c.regs = ioremap(edev->resource[2].start, 0x10); | 2210 | chip->c_dma.ebus_info.regs = ioremap(edev->resource[2].start, 0x10); |
2210 | if (!chip->port || !chip->eb2p.regs || !chip->eb2c.regs) { | 2211 | if (!chip->port || !chip->p_dma.ebus_info.regs || !chip->c_dma.ebus_info.regs) { |
2211 | snd_cs4231_ebus_free(chip); | 2212 | snd_cs4231_ebus_free(chip); |
2212 | snd_printdd("cs4231-%d: Unable to map chip registers.\n", dev); | 2213 | snd_printdd("cs4231-%d: Unable to map chip registers.\n", dev); |
2213 | return -EIO; | 2214 | return -EIO; |
2214 | } | 2215 | } |
2215 | 2216 | ||
2216 | if (ebus_dma_register(&chip->eb2c)) { | 2217 | if (ebus_dma_register(&chip->c_dma.ebus_info)) { |
2217 | snd_cs4231_ebus_free(chip); | 2218 | snd_cs4231_ebus_free(chip); |
2218 | snd_printdd("cs4231-%d: Unable to register EBUS capture DMA\n", dev); | 2219 | snd_printdd("cs4231-%d: Unable to register EBUS capture DMA\n", dev); |
2219 | return -EBUSY; | 2220 | return -EBUSY; |
2220 | } | 2221 | } |
2221 | if (ebus_dma_irq_enable(&chip->eb2c, 1)) { | 2222 | if (ebus_dma_irq_enable(&chip->c_dma.ebus_info, 1)) { |
2222 | snd_cs4231_ebus_free(chip); | 2223 | snd_cs4231_ebus_free(chip); |
2223 | snd_printdd("cs4231-%d: Unable to enable EBUS capture IRQ\n", dev); | 2224 | snd_printdd("cs4231-%d: Unable to enable EBUS capture IRQ\n", dev); |
2224 | return -EBUSY; | 2225 | return -EBUSY; |
2225 | } | 2226 | } |
2226 | 2227 | ||
2227 | if (ebus_dma_register(&chip->eb2p)) { | 2228 | if (ebus_dma_register(&chip->p_dma.ebus_info)) { |
2228 | snd_cs4231_ebus_free(chip); | 2229 | snd_cs4231_ebus_free(chip); |
2229 | snd_printdd("cs4231-%d: Unable to register EBUS play DMA\n", dev); | 2230 | snd_printdd("cs4231-%d: Unable to register EBUS play DMA\n", dev); |
2230 | return -EBUSY; | 2231 | return -EBUSY; |
2231 | } | 2232 | } |
2232 | if (ebus_dma_irq_enable(&chip->eb2p, 1)) { | 2233 | if (ebus_dma_irq_enable(&chip->p_dma.ebus_info, 1)) { |
2233 | snd_cs4231_ebus_free(chip); | 2234 | snd_cs4231_ebus_free(chip); |
2234 | snd_printdd("cs4231-%d: Unable to enable EBUS play IRQ\n", dev); | 2235 | snd_printdd("cs4231-%d: Unable to enable EBUS play IRQ\n", dev); |
2235 | return -EBUSY; | 2236 | return -EBUSY; |