aboutsummaryrefslogtreecommitdiffstats
path: root/sound
diff options
context:
space:
mode:
authorGeorg Chini <georg.chini@triaton-webhosting.com>2005-11-07 17:08:25 -0500
committerDavid S. Miller <davem@davemloft.net>2005-11-07 17:08:25 -0500
commit5a820fa7e1a34f12fec4e6766e5c335ae9427028 (patch)
treef2cf3a0747fd71cc817a6bfe565d73b60370a6b2 /sound
parentee1858d3122dedd2e82a61b6ab56b229aefd9447 (diff)
[SPARC]: Make SBUS dma code similar to EBUS
From: Georg Chini <georg.chini@triaton-webhosting.com> Introduce some sbus_dma routines similar to the ebus_dma stuff to make the code look nearly the same for both cases. Thanks to Christopher for testing. Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'sound')
-rw-r--r--sound/sparc/cs4231.c311
1 files changed, 199 insertions, 112 deletions
diff --git a/sound/sparc/cs4231.c b/sound/sparc/cs4231.c
index f4361c518e46..110d64d4848d 100644
--- a/sound/sparc/cs4231.c
+++ b/sound/sparc/cs4231.c
@@ -61,6 +61,14 @@ MODULE_DESCRIPTION("Sun CS4231");
61MODULE_LICENSE("GPL"); 61MODULE_LICENSE("GPL");
62MODULE_SUPPORTED_DEVICE("{{Sun,CS4231}}"); 62MODULE_SUPPORTED_DEVICE("{{Sun,CS4231}}");
63 63
64#ifdef SBUS_SUPPORT
65struct sbus_dma_info {
66 spinlock_t lock;
67 int dir;
68 void __iomem *regs;
69};
70#endif
71
64typedef struct snd_cs4231 { 72typedef struct snd_cs4231 {
65 spinlock_t lock; 73 spinlock_t lock;
66 void __iomem *port; 74 void __iomem *port;
@@ -69,6 +77,11 @@ typedef struct snd_cs4231 {
69 struct ebus_dma_info eb2p; 77 struct ebus_dma_info eb2p;
70#endif 78#endif
71 79
80#ifdef SBUS_SUPPORT
81 struct sbus_dma_info sb2c;
82 struct sbus_dma_info sb2p;
83#endif
84
72 u32 flags; 85 u32 flags;
73#define CS4231_FLAG_EBUS 0x00000001 86#define CS4231_FLAG_EBUS 0x00000001
74#define CS4231_FLAG_PLAYBACK 0x00000002 87#define CS4231_FLAG_PLAYBACK 0x00000002
@@ -251,6 +264,15 @@ static cs4231_t *cs4231_list;
251#define APCPNVA 0x38UL /* APC Play DMA Next Address */ 264#define APCPNVA 0x38UL /* APC Play DMA Next Address */
252#define APCPNC 0x3cUL /* APC Play Next Count */ 265#define APCPNC 0x3cUL /* APC Play Next Count */
253 266
267/* Defines for SBUS DMA-routines */
268
269#define APCVA 0x0UL /* APC DMA Address */
270#define APCC 0x4UL /* APC Count */
271#define APCNVA 0x8UL /* APC DMA Next Address */
272#define APCNC 0xcUL /* APC Next Count */
273#define APC_PLAY 0x30UL /* Play registers start at 0x30 */
274#define APC_RECORD 0x20UL /* Record registers start at 0x20 */
275
254/* APCCSR bits */ 276/* APCCSR bits */
255 277
256#define APC_INT_PENDING 0x800000 /* Interrupt Pending */ 278#define APC_INT_PENDING 0x800000 /* Interrupt Pending */
@@ -472,6 +494,103 @@ static unsigned char snd_cs4231_in(cs4231_t *chip, unsigned char reg)
472} 494}
473 495
474/* 496/*
497 * SBUS DMA routines
498 */
499#ifdef SBUS_SUPPORT
500
501int 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);
527out:
528 spin_unlock_irqrestore(&base->lock, flags);
529 return err;
530}
531
532void 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
550void 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
586unsigned 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/*
475 * CS4231 detection / MCE routines 594 * CS4231 detection / MCE routines
476 */ 595 */
477 596
@@ -589,29 +708,21 @@ static void snd_cs4231_ebus_advance_dma(struct ebus_dma_info *p, snd_pcm_substre
589#endif 708#endif
590 709
591#ifdef SBUS_SUPPORT 710#ifdef SBUS_SUPPORT
592static void snd_cs4231_sbus_advance_dma(snd_pcm_substream_t *substream, unsigned int *periods_sent) 711static void snd_cs4231_sbus_advance_dma(struct sbus_dma_info *p, snd_pcm_substream_t *substream, unsigned int *periods_sent)
593{ 712{
594 cs4231_t *chip = snd_pcm_substream_chip(substream);
595 snd_pcm_runtime_t *runtime = substream->runtime; 713 snd_pcm_runtime_t *runtime = substream->runtime;
596 714
597 unsigned int period_size = snd_pcm_lib_period_bytes(substream); 715 while (1) {
598 unsigned int offset = period_size * (*periods_sent % runtime->periods); 716 unsigned int period_size = snd_pcm_lib_period_bytes(substream);
599 717 unsigned int offset = period_size * (*periods_sent);
600 if (runtime->period_size > 0xffff + 1)
601 BUG();
602
603 switch (substream->stream) {
604 case SNDRV_PCM_STREAM_PLAYBACK:
605 sbus_writel(runtime->dma_addr + offset, chip->port + APCPNVA);
606 sbus_writel(period_size, chip->port + APCPNC);
607 break;
608 case SNDRV_PCM_STREAM_CAPTURE:
609 sbus_writel(runtime->dma_addr + offset, chip->port + APCCNVA);
610 sbus_writel(period_size, chip->port + APCCNC);
611 break;
612 }
613 718
614 (*periods_sent) = (*periods_sent + 1) % runtime->periods; 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 }
615} 726}
616#endif 727#endif
617 728
@@ -646,59 +757,27 @@ static void cs4231_dma_trigger(snd_pcm_substream_t *substream, unsigned int what
646 } else { 757 } else {
647#endif 758#endif
648#ifdef SBUS_SUPPORT 759#ifdef SBUS_SUPPORT
649 u32 csr = sbus_readl(chip->port + APCCSR); 760 if (what & CS4231_PLAYBACK_ENABLE) {
650 /* I don't know why, but on sbus the period counter must
651 * only start counting after the first period is sent.
652 * Therefore this dummy thing.
653 */
654 unsigned int dummy = 0;
655
656 switch (what) {
657 case CS4231_PLAYBACK_ENABLE:
658 if (on) { 761 if (on) {
659 csr &= ~APC_XINT_PLAY; 762 sbus_dma_prepare(&chip->sb2p);
660 sbus_writel(csr, chip->port + APCCSR); 763 sbus_dma_enable(&chip->sb2p, 1);
661 764 snd_cs4231_sbus_advance_dma(&chip->sb2p,
662 csr &= ~APC_PPAUSE; 765 chip->playback_substream,
663 sbus_writel(csr, chip->port + APCCSR); 766 &chip->p_periods_sent);
664
665 snd_cs4231_sbus_advance_dma(substream, &dummy);
666
667 csr |= APC_GENL_INT | APC_PLAY_INT | APC_XINT_ENA |
668 APC_XINT_PLAY | APC_XINT_EMPT | APC_XINT_GENL |
669 APC_XINT_PENA | APC_PDMA_READY;
670 sbus_writel(csr, chip->port + APCCSR);
671 } else { 767 } else {
672 csr |= APC_PPAUSE; 768 sbus_dma_enable(&chip->sb2p, 0);
673 sbus_writel(csr, chip->port + APCCSR);
674
675 csr &= ~APC_PDMA_READY;
676 sbus_writel(csr, chip->port + APCCSR);
677 } 769 }
678 break; 770 }
679 case CS4231_RECORD_ENABLE: 771 if (what & CS4231_RECORD_ENABLE) {
680 if (on) { 772 if (on) {
681 csr &= ~APC_XINT_CAPT; 773 sbus_dma_prepare(&chip->sb2c);
682 sbus_writel(csr, chip->port + APCCSR); 774 sbus_dma_enable(&chip->sb2c, 1);
683 775 snd_cs4231_sbus_advance_dma(&chip->sb2c,
684 csr &= ~APC_CPAUSE; 776 chip->capture_substream,
685 sbus_writel(csr, chip->port + APCCSR); 777 &chip->c_periods_sent);
686
687 snd_cs4231_sbus_advance_dma(substream, &dummy);
688
689 csr |= APC_GENL_INT | APC_CAPT_INT | APC_XINT_ENA |
690 APC_XINT_CAPT | APC_XINT_CEMP | APC_XINT_GENL |
691 APC_CDMA_READY;
692
693 sbus_writel(csr, chip->port + APCCSR);
694 } else { 778 } else {
695 csr |= APC_CPAUSE; 779 sbus_dma_enable(&chip->sb2c, 0);
696 sbus_writel(csr, chip->port + APCCSR);
697
698 csr &= ~APC_CDMA_READY;
699 sbus_writel(csr, chip->port + APCCSR);
700 } 780 }
701 break;
702 } 781 }
703#endif 782#endif
704#ifdef EBUS_SUPPORT 783#ifdef EBUS_SUPPORT
@@ -1136,10 +1215,7 @@ static int snd_cs4231_playback_prepare(snd_pcm_substream_t *substream)
1136 if (runtime->period_size > 0xffff + 1) 1215 if (runtime->period_size > 0xffff + 1)
1137 BUG(); 1216 BUG();
1138 1217
1139 snd_cs4231_out(chip, CS4231_PLY_LWR_CNT, (runtime->period_size - 1) & 0x00ff);
1140 snd_cs4231_out(chip, CS4231_PLY_UPR_CNT, (runtime->period_size - 1) >> 8 & 0x00ff);
1141 chip->p_periods_sent = 0; 1218 chip->p_periods_sent = 0;
1142
1143 spin_unlock_irqrestore(&chip->lock, flags); 1219 spin_unlock_irqrestore(&chip->lock, flags);
1144 1220
1145 return 0; 1221 return 0;
@@ -1171,16 +1247,14 @@ static int snd_cs4231_capture_hw_free(snd_pcm_substream_t *substream)
1171static int snd_cs4231_capture_prepare(snd_pcm_substream_t *substream) 1247static int snd_cs4231_capture_prepare(snd_pcm_substream_t *substream)
1172{ 1248{
1173 cs4231_t *chip = snd_pcm_substream_chip(substream); 1249 cs4231_t *chip = snd_pcm_substream_chip(substream);
1174 snd_pcm_runtime_t *runtime = substream->runtime;
1175 unsigned long flags; 1250 unsigned long flags;
1176 1251
1177 spin_lock_irqsave(&chip->lock, flags); 1252 spin_lock_irqsave(&chip->lock, flags);
1178 chip->image[CS4231_IFACE_CTRL] &= ~(CS4231_RECORD_ENABLE | 1253 chip->image[CS4231_IFACE_CTRL] &= ~(CS4231_RECORD_ENABLE |
1179 CS4231_RECORD_PIO); 1254 CS4231_RECORD_PIO);
1180 1255
1181 snd_cs4231_out(chip, CS4231_REC_LWR_CNT, (runtime->period_size - 1) & 0x00ff);
1182 snd_cs4231_out(chip, CS4231_REC_LWR_CNT, (runtime->period_size - 1) >> 8 & 0x00ff);
1183 1256
1257 chip->c_periods_sent = 0;
1184 spin_unlock_irqrestore(&chip->lock, flags); 1258 spin_unlock_irqrestore(&chip->lock, flags);
1185 1259
1186 return 0; 1260 return 0;
@@ -1199,40 +1273,20 @@ static void snd_cs4231_overrange(cs4231_t *chip)
1199 chip->capture_substream->runtime->overrange++; 1273 chip->capture_substream->runtime->overrange++;
1200} 1274}
1201 1275
1202static irqreturn_t snd_cs4231_generic_interrupt(cs4231_t *chip) 1276#ifdef SBUS_SUPPORT
1277static irqreturn_t snd_cs4231_sbus_interrupt(int irq, void *dev_id, struct pt_regs *regs)
1203{ 1278{
1204 unsigned long flags; 1279 unsigned long flags;
1205 unsigned char status; 1280 unsigned char status;
1281 u32 csr;
1282 cs4231_t *chip = dev_id;
1206 1283
1207 /*This is IRQ is not raised by the cs4231*/ 1284 /*This is IRQ is not raised by the cs4231*/
1208 if (!(__cs4231_readb(chip, CS4231P(chip, STATUS)) & CS4231_GLOBALIRQ)) 1285 if (!(__cs4231_readb(chip, CS4231P(chip, STATUS)) & CS4231_GLOBALIRQ))
1209 return IRQ_NONE; 1286 return IRQ_NONE;
1210 1287
1211 status = snd_cs4231_in(chip, CS4231_IRQ_STATUS);
1212
1213 if (status & CS4231_TIMER_IRQ) {
1214 if (chip->timer)
1215 snd_timer_interrupt(chip->timer, chip->timer->sticks);
1216 }
1217
1218 if (status & CS4231_RECORD_IRQ)
1219 snd_cs4231_overrange(chip);
1220
1221 /* ACK the CS4231 interrupt. */
1222 spin_lock_irqsave(&chip->lock, flags);
1223 snd_cs4231_outm(chip, CS4231_IRQ_STATUS, ~CS4231_ALL_IRQS | ~status, 0);
1224 spin_unlock_irqrestore(&chip->lock, flags);
1225
1226 return 0;
1227}
1228
1229#ifdef SBUS_SUPPORT
1230static irqreturn_t snd_cs4231_sbus_interrupt(int irq, void *dev_id, struct pt_regs *regs)
1231{
1232 cs4231_t *chip = dev_id;
1233
1234 /* ACK the APC interrupt. */ 1288 /* ACK the APC interrupt. */
1235 u32 csr = sbus_readl(chip->port + APCCSR); 1289 csr = sbus_readl(chip->port + APCCSR);
1236 1290
1237 sbus_writel(csr, chip->port + APCCSR); 1291 sbus_writel(csr, chip->port + APCCSR);
1238 1292
@@ -1240,20 +1294,36 @@ static irqreturn_t snd_cs4231_sbus_interrupt(int irq, void *dev_id, struct pt_re
1240 (csr & APC_PLAY_INT) && 1294 (csr & APC_PLAY_INT) &&
1241 (csr & APC_XINT_PNVA) && 1295 (csr & APC_XINT_PNVA) &&
1242 !(csr & APC_XINT_EMPT)) { 1296 !(csr & APC_XINT_EMPT)) {
1243 snd_cs4231_sbus_advance_dma(chip->playback_substream,
1244 &chip->p_periods_sent);
1245 snd_pcm_period_elapsed(chip->playback_substream); 1297 snd_pcm_period_elapsed(chip->playback_substream);
1298 snd_cs4231_sbus_advance_dma(&chip->sb2p, chip->playback_substream,
1299 &chip->p_periods_sent);
1246 } 1300 }
1247 1301
1248 if ((chip->image[CS4231_IFACE_CTRL] & CS4231_RECORD_ENABLE) && 1302 if ((chip->image[CS4231_IFACE_CTRL] & CS4231_RECORD_ENABLE) &&
1249 (csr & APC_CAPT_INT) && 1303 (csr & APC_CAPT_INT) &&
1250 (csr & APC_XINT_CNVA)) { 1304 (csr & APC_XINT_CNVA) &&
1251 snd_cs4231_sbus_advance_dma(chip->capture_substream, 1305 !(csr & APC_XINT_EMPT)) {
1252 &chip->c_periods_sent);
1253 snd_pcm_period_elapsed(chip->capture_substream); 1306 snd_pcm_period_elapsed(chip->capture_substream);
1307 snd_cs4231_sbus_advance_dma(&chip->sb2c,chip->capture_substream,
1308 &chip->c_periods_sent);
1254 } 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);
1255 1320
1256 return snd_cs4231_generic_interrupt(chip); 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;
1257} 1327}
1258#endif 1328#endif
1259 1329
@@ -1284,24 +1354,29 @@ static void snd_cs4231_ebus_capture_callback(struct ebus_dma_info *p, int event,
1284static snd_pcm_uframes_t snd_cs4231_playback_pointer(snd_pcm_substream_t *substream) 1354static snd_pcm_uframes_t snd_cs4231_playback_pointer(snd_pcm_substream_t *substream)
1285{ 1355{
1286 cs4231_t *chip = snd_pcm_substream_chip(substream); 1356 cs4231_t *chip = snd_pcm_substream_chip(substream);
1287 size_t ptr, residue, period_bytes; 1357 size_t ptr;
1288 1358#ifdef EBUS_SUPPORT
1359 size_t residue, period_bytes;
1360#endif
1361
1289 if (!(chip->image[CS4231_IFACE_CTRL] & CS4231_PLAYBACK_ENABLE)) 1362 if (!(chip->image[CS4231_IFACE_CTRL] & CS4231_PLAYBACK_ENABLE))
1290 return 0; 1363 return 0;
1364#ifdef EBUS_SUPPORT
1291 period_bytes = snd_pcm_lib_period_bytes(substream); 1365 period_bytes = snd_pcm_lib_period_bytes(substream);
1292 ptr = period_bytes * chip->p_periods_sent; 1366 ptr = period_bytes * chip->p_periods_sent;
1293#ifdef EBUS_SUPPORT
1294 if (chip->flags & CS4231_FLAG_EBUS) { 1367 if (chip->flags & CS4231_FLAG_EBUS) {
1295 residue = ebus_dma_residue(&chip->eb2p); 1368 residue = ebus_dma_residue(&chip->eb2p);
1369 ptr += period_bytes - residue;
1296 } else { 1370 } else {
1297#endif 1371#endif
1298#ifdef SBUS_SUPPORT 1372#ifdef SBUS_SUPPORT
1299 residue = sbus_readl(chip->port + APCPC); 1373 ptr = sbus_dma_addr(&chip->sb2p);
1374 if (ptr != 0)
1375 ptr -= substream->runtime->dma_addr;
1300#endif 1376#endif
1301#ifdef EBUS_SUPPORT 1377#ifdef EBUS_SUPPORT
1302 } 1378 }
1303#endif 1379#endif
1304 ptr += period_bytes - residue;
1305 1380
1306 return bytes_to_frames(substream->runtime, ptr); 1381 return bytes_to_frames(substream->runtime, ptr);
1307} 1382}
@@ -1309,24 +1384,29 @@ static snd_pcm_uframes_t snd_cs4231_playback_pointer(snd_pcm_substream_t *substr
1309static snd_pcm_uframes_t snd_cs4231_capture_pointer(snd_pcm_substream_t * substream) 1384static snd_pcm_uframes_t snd_cs4231_capture_pointer(snd_pcm_substream_t * substream)
1310{ 1385{
1311 cs4231_t *chip = snd_pcm_substream_chip(substream); 1386 cs4231_t *chip = snd_pcm_substream_chip(substream);
1312 size_t ptr, residue, period_bytes; 1387 size_t ptr;
1388#ifdef EBUS_SUPPORT
1389 size_t residue, period_bytes;
1390#endif
1313 1391
1314 if (!(chip->image[CS4231_IFACE_CTRL] & CS4231_RECORD_ENABLE)) 1392 if (!(chip->image[CS4231_IFACE_CTRL] & CS4231_RECORD_ENABLE))
1315 return 0; 1393 return 0;
1394#ifdef EBUS_SUPPORT
1316 period_bytes = snd_pcm_lib_period_bytes(substream); 1395 period_bytes = snd_pcm_lib_period_bytes(substream);
1317 ptr = period_bytes * chip->c_periods_sent; 1396 ptr = period_bytes * chip->c_periods_sent;
1318#ifdef EBUS_SUPPORT
1319 if (chip->flags & CS4231_FLAG_EBUS) { 1397 if (chip->flags & CS4231_FLAG_EBUS) {
1320 residue = ebus_dma_residue(&chip->eb2c); 1398 residue = ebus_dma_residue(&chip->eb2c);
1399 ptr += period_bytes - residue;
1321 } else { 1400 } else {
1322#endif 1401#endif
1323#ifdef SBUS_SUPPORT 1402#ifdef SBUS_SUPPORT
1324 residue = sbus_readl(chip->port + APCCC); 1403 ptr = sbus_dma_addr(&chip->sb2c);
1404 if (ptr != 0)
1405 ptr -= substream->runtime->dma_addr;
1325#endif 1406#endif
1326#ifdef EBUS_SUPPORT 1407#ifdef EBUS_SUPPORT
1327 } 1408 }
1328#endif 1409#endif
1329 ptr += period_bytes - residue;
1330 return bytes_to_frames(substream->runtime, ptr); 1410 return bytes_to_frames(substream->runtime, ptr);
1331} 1411}
1332 1412
@@ -1983,6 +2063,8 @@ static int __init snd_cs4231_sbus_create(snd_card_t *card,
1983 return -ENOMEM; 2063 return -ENOMEM;
1984 2064
1985 spin_lock_init(&chip->lock); 2065 spin_lock_init(&chip->lock);
2066 spin_lock_init(&chip->sb2c.lock);
2067 spin_lock_init(&chip->sb2p.lock);
1986 init_MUTEX(&chip->mce_mutex); 2068 init_MUTEX(&chip->mce_mutex);
1987 init_MUTEX(&chip->open_mutex); 2069 init_MUTEX(&chip->open_mutex);
1988 chip->card = card; 2070 chip->card = card;
@@ -1998,6 +2080,11 @@ static int __init snd_cs4231_sbus_create(snd_card_t *card,
1998 return -EIO; 2080 return -EIO;
1999 } 2081 }
2000 2082
2083 chip->sb2c.regs = chip->port;
2084 chip->sb2p.regs = chip->port;
2085 chip->sb2c.dir = APC_RECORD;
2086 chip->sb2p.dir = APC_PLAY;
2087
2001 if (request_irq(sdev->irqs[0], snd_cs4231_sbus_interrupt, 2088 if (request_irq(sdev->irqs[0], snd_cs4231_sbus_interrupt,
2002 SA_SHIRQ, "cs4231", chip)) { 2089 SA_SHIRQ, "cs4231", chip)) {
2003 snd_printdd("cs4231-%d: Unable to grab SBUS IRQ %s\n", 2090 snd_printdd("cs4231-%d: Unable to grab SBUS IRQ %s\n",