diff options
author | Andreas Eversberg <andreas@eversberg.eu> | 2009-05-22 07:04:46 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2009-05-25 03:51:31 -0400 |
commit | 7cfa153dd709f15188fe84b78ae76387841fe17b (patch) | |
tree | 35df67cef71397759e9fad76fb878fa439f26f45 /drivers/isdn/hardware/mISDN | |
parent | a5355c27d26001865a5ac32c868c82a523c275d3 (diff) |
mISDN: Echo canceler now gets delay information from hardware
Added tx-fifo information for calculation of current delay to sync tx and rx
streams for echo canceler.
Signed-off-by: Andreas Eversberg <andreas@eversberg.eu>
Signed-off-by: Karsten Keil <keil@b1-systems.de>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/isdn/hardware/mISDN')
-rw-r--r-- | drivers/isdn/hardware/mISDN/hfc_multi.h | 1 | ||||
-rw-r--r-- | drivers/isdn/hardware/mISDN/hfcmulti.c | 8 | ||||
-rw-r--r-- | drivers/isdn/hardware/mISDN/hfcpci.c | 70 | ||||
-rw-r--r-- | drivers/isdn/hardware/mISDN/hfcsusb.c | 4 |
4 files changed, 50 insertions, 33 deletions
diff --git a/drivers/isdn/hardware/mISDN/hfc_multi.h b/drivers/isdn/hardware/mISDN/hfc_multi.h index 5765e1962911..c4878cc712c9 100644 --- a/drivers/isdn/hardware/mISDN/hfc_multi.h +++ b/drivers/isdn/hardware/mISDN/hfc_multi.h | |||
@@ -44,6 +44,7 @@ struct hfc_chan { | |||
44 | int conf; /* conference setting of TX slot */ | 44 | int conf; /* conference setting of TX slot */ |
45 | int txpending; /* if there is currently data in */ | 45 | int txpending; /* if there is currently data in */ |
46 | /* the FIFO 0=no, 1=yes, 2=splloop */ | 46 | /* the FIFO 0=no, 1=yes, 2=splloop */ |
47 | int Zfill; /* rx-fifo level on last hfcmulti_tx */ | ||
47 | int rx_off; /* set to turn fifo receive off */ | 48 | int rx_off; /* set to turn fifo receive off */ |
48 | int coeff_count; /* curren coeff block */ | 49 | int coeff_count; /* curren coeff block */ |
49 | s32 *coeff; /* memory pointer to 8 coeff blocks */ | 50 | s32 *coeff; /* memory pointer to 8 coeff blocks */ |
diff --git a/drivers/isdn/hardware/mISDN/hfcmulti.c b/drivers/isdn/hardware/mISDN/hfcmulti.c index ca153de6954e..3a7c26ce12cf 100644 --- a/drivers/isdn/hardware/mISDN/hfcmulti.c +++ b/drivers/isdn/hardware/mISDN/hfcmulti.c | |||
@@ -1945,6 +1945,9 @@ next_frame: | |||
1945 | "%d!=%d\n", __func__, hc->id + 1, temp, z2); | 1945 | "%d!=%d\n", __func__, hc->id + 1, temp, z2); |
1946 | z2 = temp; /* repeat unti Z2 is equal */ | 1946 | z2 = temp; /* repeat unti Z2 is equal */ |
1947 | } | 1947 | } |
1948 | hc->chan[ch].Zfill = z1 - z2; | ||
1949 | if (hc->chan[ch].Zfill < 0) | ||
1950 | hc->chan[ch].Zfill += hc->Zlen; | ||
1948 | Zspace = z2 - z1; | 1951 | Zspace = z2 - z1; |
1949 | if (Zspace <= 0) | 1952 | if (Zspace <= 0) |
1950 | Zspace += hc->Zlen; | 1953 | Zspace += hc->Zlen; |
@@ -2031,6 +2034,7 @@ next_frame: | |||
2031 | 2034 | ||
2032 | /* Have to prep the audio data */ | 2035 | /* Have to prep the audio data */ |
2033 | hc->write_fifo(hc, d, ii - i); | 2036 | hc->write_fifo(hc, d, ii - i); |
2037 | hc->chan[ch].Zfill += ii - i; | ||
2034 | *idxp = ii; | 2038 | *idxp = ii; |
2035 | 2039 | ||
2036 | /* if not all data has been written */ | 2040 | /* if not all data has been written */ |
@@ -2226,7 +2230,7 @@ next_frame: | |||
2226 | if (dch) | 2230 | if (dch) |
2227 | recv_Dchannel(dch); | 2231 | recv_Dchannel(dch); |
2228 | else | 2232 | else |
2229 | recv_Bchannel(bch); | 2233 | recv_Bchannel(bch, MISDN_ID_ANY); |
2230 | *sp = skb; | 2234 | *sp = skb; |
2231 | again++; | 2235 | again++; |
2232 | goto next_frame; | 2236 | goto next_frame; |
@@ -2258,7 +2262,7 @@ next_frame: | |||
2258 | "(z1=%04x, z2=%04x) TRANS\n", | 2262 | "(z1=%04x, z2=%04x) TRANS\n", |
2259 | __func__, hc->id + 1, ch, Zsize, z1, z2); | 2263 | __func__, hc->id + 1, ch, Zsize, z1, z2); |
2260 | /* only bch is transparent */ | 2264 | /* only bch is transparent */ |
2261 | recv_Bchannel(bch); | 2265 | recv_Bchannel(bch, hc->chan[ch].Zfill); |
2262 | *sp = skb; | 2266 | *sp = skb; |
2263 | } | 2267 | } |
2264 | } | 2268 | } |
diff --git a/drivers/isdn/hardware/mISDN/hfcpci.c b/drivers/isdn/hardware/mISDN/hfcpci.c index 641a9cd1a532..60dc92562c6d 100644 --- a/drivers/isdn/hardware/mISDN/hfcpci.c +++ b/drivers/isdn/hardware/mISDN/hfcpci.c | |||
@@ -452,7 +452,7 @@ hfcpci_empty_bfifo(struct bchannel *bch, struct bzfifo *bz, | |||
452 | } | 452 | } |
453 | bz->za[new_f2].z2 = cpu_to_le16(new_z2); | 453 | bz->za[new_f2].z2 = cpu_to_le16(new_z2); |
454 | bz->f2 = new_f2; /* next buffer */ | 454 | bz->f2 = new_f2; /* next buffer */ |
455 | recv_Bchannel(bch); | 455 | recv_Bchannel(bch, MISDN_ID_ANY); |
456 | } | 456 | } |
457 | } | 457 | } |
458 | 458 | ||
@@ -541,35 +541,45 @@ receive_dmsg(struct hfc_pci *hc) | |||
541 | * check for transparent receive data and read max one 'poll' size if avail | 541 | * check for transparent receive data and read max one 'poll' size if avail |
542 | */ | 542 | */ |
543 | static void | 543 | static void |
544 | hfcpci_empty_fifo_trans(struct bchannel *bch, struct bzfifo *bz, u_char *bdata) | 544 | hfcpci_empty_fifo_trans(struct bchannel *bch, struct bzfifo *rxbz, |
545 | struct bzfifo *txbz, u_char *bdata) | ||
545 | { | 546 | { |
546 | __le16 *z1r, *z2r; | 547 | __le16 *z1r, *z2r, *z1t, *z2t; |
547 | int new_z2, fcnt, maxlen; | 548 | int new_z2, fcnt_rx, fcnt_tx, maxlen; |
548 | u_char *ptr, *ptr1; | 549 | u_char *ptr, *ptr1; |
549 | 550 | ||
550 | z1r = &bz->za[MAX_B_FRAMES].z1; /* pointer to z reg */ | 551 | z1r = &rxbz->za[MAX_B_FRAMES].z1; /* pointer to z reg */ |
551 | z2r = z1r + 1; | 552 | z2r = z1r + 1; |
553 | z1t = &txbz->za[MAX_B_FRAMES].z1; | ||
554 | z2t = z1t + 1; | ||
552 | 555 | ||
553 | fcnt = le16_to_cpu(*z1r) - le16_to_cpu(*z2r); | 556 | fcnt_rx = le16_to_cpu(*z1r) - le16_to_cpu(*z2r); |
554 | if (!fcnt) | 557 | if (!fcnt_rx) |
555 | return; /* no data avail */ | 558 | return; /* no data avail */ |
556 | 559 | ||
557 | if (fcnt <= 0) | 560 | if (fcnt_rx <= 0) |
558 | fcnt += B_FIFO_SIZE; /* bytes actually buffered */ | 561 | fcnt_rx += B_FIFO_SIZE; /* bytes actually buffered */ |
559 | new_z2 = le16_to_cpu(*z2r) + fcnt; /* new position in fifo */ | 562 | new_z2 = le16_to_cpu(*z2r) + fcnt_rx; /* new position in fifo */ |
560 | if (new_z2 >= (B_FIFO_SIZE + B_SUB_VAL)) | 563 | if (new_z2 >= (B_FIFO_SIZE + B_SUB_VAL)) |
561 | new_z2 -= B_FIFO_SIZE; /* buffer wrap */ | 564 | new_z2 -= B_FIFO_SIZE; /* buffer wrap */ |
562 | 565 | ||
563 | if (fcnt > MAX_DATA_SIZE) { /* flush, if oversized */ | 566 | if (fcnt_rx > MAX_DATA_SIZE) { /* flush, if oversized */ |
564 | *z2r = cpu_to_le16(new_z2); /* new position */ | 567 | *z2r = cpu_to_le16(new_z2); /* new position */ |
565 | return; | 568 | return; |
566 | } | 569 | } |
567 | 570 | ||
568 | bch->rx_skb = mI_alloc_skb(fcnt, GFP_ATOMIC); | 571 | fcnt_tx = le16_to_cpu(*z2t) - le16_to_cpu(*z1t); |
572 | if (fcnt_tx <= 0) | ||
573 | fcnt_tx += B_FIFO_SIZE; | ||
574 | /* fcnt_tx contains available bytes in tx-fifo */ | ||
575 | fcnt_tx = B_FIFO_SIZE - fcnt_tx; | ||
576 | /* remaining bytes to send (bytes in tx-fifo) */ | ||
577 | |||
578 | bch->rx_skb = mI_alloc_skb(fcnt_rx, GFP_ATOMIC); | ||
569 | if (bch->rx_skb) { | 579 | if (bch->rx_skb) { |
570 | ptr = skb_put(bch->rx_skb, fcnt); | 580 | ptr = skb_put(bch->rx_skb, fcnt_rx); |
571 | if (le16_to_cpu(*z2r) + fcnt <= B_FIFO_SIZE + B_SUB_VAL) | 581 | if (le16_to_cpu(*z2r) + fcnt_rx <= B_FIFO_SIZE + B_SUB_VAL) |
572 | maxlen = fcnt; /* complete transfer */ | 582 | maxlen = fcnt_rx; /* complete transfer */ |
573 | else | 583 | else |
574 | maxlen = B_FIFO_SIZE + B_SUB_VAL - le16_to_cpu(*z2r); | 584 | maxlen = B_FIFO_SIZE + B_SUB_VAL - le16_to_cpu(*z2r); |
575 | /* maximum */ | 585 | /* maximum */ |
@@ -577,14 +587,14 @@ hfcpci_empty_fifo_trans(struct bchannel *bch, struct bzfifo *bz, u_char *bdata) | |||
577 | ptr1 = bdata + (le16_to_cpu(*z2r) - B_SUB_VAL); | 587 | ptr1 = bdata + (le16_to_cpu(*z2r) - B_SUB_VAL); |
578 | /* start of data */ | 588 | /* start of data */ |
579 | memcpy(ptr, ptr1, maxlen); /* copy data */ | 589 | memcpy(ptr, ptr1, maxlen); /* copy data */ |
580 | fcnt -= maxlen; | 590 | fcnt_rx -= maxlen; |
581 | 591 | ||
582 | if (fcnt) { /* rest remaining */ | 592 | if (fcnt_rx) { /* rest remaining */ |
583 | ptr += maxlen; | 593 | ptr += maxlen; |
584 | ptr1 = bdata; /* start of buffer */ | 594 | ptr1 = bdata; /* start of buffer */ |
585 | memcpy(ptr, ptr1, fcnt); /* rest */ | 595 | memcpy(ptr, ptr1, fcnt_rx); /* rest */ |
586 | } | 596 | } |
587 | recv_Bchannel(bch); | 597 | recv_Bchannel(bch, fcnt_tx); /* bch, id */ |
588 | } else | 598 | } else |
589 | printk(KERN_WARNING "HFCPCI: receive out of memory\n"); | 599 | printk(KERN_WARNING "HFCPCI: receive out of memory\n"); |
590 | 600 | ||
@@ -600,26 +610,28 @@ main_rec_hfcpci(struct bchannel *bch) | |||
600 | struct hfc_pci *hc = bch->hw; | 610 | struct hfc_pci *hc = bch->hw; |
601 | int rcnt, real_fifo; | 611 | int rcnt, real_fifo; |
602 | int receive = 0, count = 5; | 612 | int receive = 0, count = 5; |
603 | struct bzfifo *bz; | 613 | struct bzfifo *txbz, *rxbz; |
604 | u_char *bdata; | 614 | u_char *bdata; |
605 | struct zt *zp; | 615 | struct zt *zp; |
606 | 616 | ||
607 | if ((bch->nr & 2) && (!hc->hw.bswapped)) { | 617 | if ((bch->nr & 2) && (!hc->hw.bswapped)) { |
608 | bz = &((union fifo_area *)(hc->hw.fifos))->b_chans.rxbz_b2; | 618 | rxbz = &((union fifo_area *)(hc->hw.fifos))->b_chans.rxbz_b2; |
619 | txbz = &((union fifo_area *)(hc->hw.fifos))->b_chans.txbz_b2; | ||
609 | bdata = ((union fifo_area *)(hc->hw.fifos))->b_chans.rxdat_b2; | 620 | bdata = ((union fifo_area *)(hc->hw.fifos))->b_chans.rxdat_b2; |
610 | real_fifo = 1; | 621 | real_fifo = 1; |
611 | } else { | 622 | } else { |
612 | bz = &((union fifo_area *)(hc->hw.fifos))->b_chans.rxbz_b1; | 623 | rxbz = &((union fifo_area *)(hc->hw.fifos))->b_chans.rxbz_b1; |
624 | txbz = &((union fifo_area *)(hc->hw.fifos))->b_chans.txbz_b1; | ||
613 | bdata = ((union fifo_area *)(hc->hw.fifos))->b_chans.rxdat_b1; | 625 | bdata = ((union fifo_area *)(hc->hw.fifos))->b_chans.rxdat_b1; |
614 | real_fifo = 0; | 626 | real_fifo = 0; |
615 | } | 627 | } |
616 | Begin: | 628 | Begin: |
617 | count--; | 629 | count--; |
618 | if (bz->f1 != bz->f2) { | 630 | if (rxbz->f1 != rxbz->f2) { |
619 | if (bch->debug & DEBUG_HW_BCHANNEL) | 631 | if (bch->debug & DEBUG_HW_BCHANNEL) |
620 | printk(KERN_DEBUG "hfcpci rec ch(%x) f1(%d) f2(%d)\n", | 632 | printk(KERN_DEBUG "hfcpci rec ch(%x) f1(%d) f2(%d)\n", |
621 | bch->nr, bz->f1, bz->f2); | 633 | bch->nr, rxbz->f1, rxbz->f2); |
622 | zp = &bz->za[bz->f2]; | 634 | zp = &rxbz->za[rxbz->f2]; |
623 | 635 | ||
624 | rcnt = le16_to_cpu(zp->z1) - le16_to_cpu(zp->z2); | 636 | rcnt = le16_to_cpu(zp->z1) - le16_to_cpu(zp->z2); |
625 | if (rcnt < 0) | 637 | if (rcnt < 0) |
@@ -630,8 +642,8 @@ Begin: | |||
630 | "hfcpci rec ch(%x) z1(%x) z2(%x) cnt(%d)\n", | 642 | "hfcpci rec ch(%x) z1(%x) z2(%x) cnt(%d)\n", |
631 | bch->nr, le16_to_cpu(zp->z1), | 643 | bch->nr, le16_to_cpu(zp->z1), |
632 | le16_to_cpu(zp->z2), rcnt); | 644 | le16_to_cpu(zp->z2), rcnt); |
633 | hfcpci_empty_bfifo(bch, bz, bdata, rcnt); | 645 | hfcpci_empty_bfifo(bch, rxbz, bdata, rcnt); |
634 | rcnt = bz->f1 - bz->f2; | 646 | rcnt = rxbz->f1 - rxbz->f2; |
635 | if (rcnt < 0) | 647 | if (rcnt < 0) |
636 | rcnt += MAX_B_FRAMES + 1; | 648 | rcnt += MAX_B_FRAMES + 1; |
637 | if (hc->hw.last_bfifo_cnt[real_fifo] > rcnt + 1) { | 649 | if (hc->hw.last_bfifo_cnt[real_fifo] > rcnt + 1) { |
@@ -644,7 +656,7 @@ Begin: | |||
644 | else | 656 | else |
645 | receive = 0; | 657 | receive = 0; |
646 | } else if (test_bit(FLG_TRANSPARENT, &bch->Flags)) { | 658 | } else if (test_bit(FLG_TRANSPARENT, &bch->Flags)) { |
647 | hfcpci_empty_fifo_trans(bch, bz, bdata); | 659 | hfcpci_empty_fifo_trans(bch, rxbz, txbz, bdata); |
648 | return; | 660 | return; |
649 | } else | 661 | } else |
650 | receive = 0; | 662 | receive = 0; |
diff --git a/drivers/isdn/hardware/mISDN/hfcsusb.c b/drivers/isdn/hardware/mISDN/hfcsusb.c index 9c427fb204ee..6b7704c41b94 100644 --- a/drivers/isdn/hardware/mISDN/hfcsusb.c +++ b/drivers/isdn/hardware/mISDN/hfcsusb.c | |||
@@ -947,7 +947,7 @@ hfcsusb_rx_frame(struct usb_fifo *fifo, __u8 *data, unsigned int len, | |||
947 | if (fifo->dch) | 947 | if (fifo->dch) |
948 | recv_Dchannel(fifo->dch); | 948 | recv_Dchannel(fifo->dch); |
949 | if (fifo->bch) | 949 | if (fifo->bch) |
950 | recv_Bchannel(fifo->bch); | 950 | recv_Bchannel(fifo->bch, MISDN_ID_ANY); |
951 | if (fifo->ech) | 951 | if (fifo->ech) |
952 | recv_Echannel(fifo->ech, | 952 | recv_Echannel(fifo->ech, |
953 | &hw->dch); | 953 | &hw->dch); |
@@ -969,7 +969,7 @@ hfcsusb_rx_frame(struct usb_fifo *fifo, __u8 *data, unsigned int len, | |||
969 | } else { | 969 | } else { |
970 | /* deliver transparent data to layer2 */ | 970 | /* deliver transparent data to layer2 */ |
971 | if (rx_skb->len >= poll) | 971 | if (rx_skb->len >= poll) |
972 | recv_Bchannel(fifo->bch); | 972 | recv_Bchannel(fifo->bch, MISDN_ID_ANY); |
973 | } | 973 | } |
974 | spin_unlock(&hw->lock); | 974 | spin_unlock(&hw->lock); |
975 | } | 975 | } |