aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAndreas Eversberg <andreas@eversberg.eu>2009-05-22 07:04:46 -0400
committerDavid S. Miller <davem@davemloft.net>2009-05-25 03:51:31 -0400
commit7cfa153dd709f15188fe84b78ae76387841fe17b (patch)
tree35df67cef71397759e9fad76fb878fa439f26f45
parenta5355c27d26001865a5ac32c868c82a523c275d3 (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>
-rw-r--r--drivers/isdn/hardware/mISDN/hfc_multi.h1
-rw-r--r--drivers/isdn/hardware/mISDN/hfcmulti.c8
-rw-r--r--drivers/isdn/hardware/mISDN/hfcpci.c70
-rw-r--r--drivers/isdn/hardware/mISDN/hfcsusb.c4
-rw-r--r--drivers/isdn/mISDN/dsp.h2
-rw-r--r--drivers/isdn/mISDN/dsp_core.c2
-rw-r--r--drivers/isdn/mISDN/dsp_pipeline.c5
-rw-r--r--drivers/isdn/mISDN/hwchannel.c4
-rw-r--r--include/linux/mISDNdsp.h3
-rw-r--r--include/linux/mISDNhw.h2
10 files changed, 60 insertions, 41 deletions
diff --git a/drivers/isdn/hardware/mISDN/hfc_multi.h b/drivers/isdn/hardware/mISDN/hfc_multi.h
index 5765e196291..c4878cc712c 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 ca153de6954..3a7c26ce12c 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 641a9cd1a53..60dc92562c6 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 */
543static void 543static void
544hfcpci_empty_fifo_trans(struct bchannel *bch, struct bzfifo *bz, u_char *bdata) 544hfcpci_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 }
616Begin: 628Begin:
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 9c427fb204e..6b7704c41b9 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}
diff --git a/drivers/isdn/mISDN/dsp.h b/drivers/isdn/mISDN/dsp.h
index 0a4a362b89c..4a1c444d73a 100644
--- a/drivers/isdn/mISDN/dsp.h
+++ b/drivers/isdn/mISDN/dsp.h
@@ -262,5 +262,5 @@ extern int dsp_pipeline_build(struct dsp_pipeline *pipeline, const char *cfg);
262extern void dsp_pipeline_process_tx(struct dsp_pipeline *pipeline, u8 *data, 262extern void dsp_pipeline_process_tx(struct dsp_pipeline *pipeline, u8 *data,
263 int len); 263 int len);
264extern void dsp_pipeline_process_rx(struct dsp_pipeline *pipeline, u8 *data, 264extern void dsp_pipeline_process_rx(struct dsp_pipeline *pipeline, u8 *data,
265 int len); 265 int len, unsigned int txlen);
266 266
diff --git a/drivers/isdn/mISDN/dsp_core.c b/drivers/isdn/mISDN/dsp_core.c
index 3083338716b..1c49368e0a9 100644
--- a/drivers/isdn/mISDN/dsp_core.c
+++ b/drivers/isdn/mISDN/dsp_core.c
@@ -710,7 +710,7 @@ dsp_function(struct mISDNchannel *ch, struct sk_buff *skb)
710 /* pipeline */ 710 /* pipeline */
711 if (dsp->pipeline.inuse) 711 if (dsp->pipeline.inuse)
712 dsp_pipeline_process_rx(&dsp->pipeline, skb->data, 712 dsp_pipeline_process_rx(&dsp->pipeline, skb->data,
713 skb->len); 713 skb->len, hh->id);
714 /* change volume if requested */ 714 /* change volume if requested */
715 if (dsp->rx_volume) 715 if (dsp->rx_volume)
716 dsp_change_volume(skb, dsp->rx_volume); 716 dsp_change_volume(skb, dsp->rx_volume);
diff --git a/drivers/isdn/mISDN/dsp_pipeline.c b/drivers/isdn/mISDN/dsp_pipeline.c
index 18cf87c113e..ac61f198eb3 100644
--- a/drivers/isdn/mISDN/dsp_pipeline.c
+++ b/drivers/isdn/mISDN/dsp_pipeline.c
@@ -347,7 +347,8 @@ void dsp_pipeline_process_tx(struct dsp_pipeline *pipeline, u8 *data, int len)
347 entry->elem->process_tx(entry->p, data, len); 347 entry->elem->process_tx(entry->p, data, len);
348} 348}
349 349
350void dsp_pipeline_process_rx(struct dsp_pipeline *pipeline, u8 *data, int len) 350void dsp_pipeline_process_rx(struct dsp_pipeline *pipeline, u8 *data, int len,
351 unsigned int txlen)
351{ 352{
352 struct dsp_pipeline_entry *entry; 353 struct dsp_pipeline_entry *entry;
353 354
@@ -356,7 +357,7 @@ void dsp_pipeline_process_rx(struct dsp_pipeline *pipeline, u8 *data, int len)
356 357
357 list_for_each_entry_reverse(entry, &pipeline->list, list) 358 list_for_each_entry_reverse(entry, &pipeline->list, list)
358 if (entry->elem->process_rx) 359 if (entry->elem->process_rx)
359 entry->elem->process_rx(entry->p, data, len); 360 entry->elem->process_rx(entry->p, data, len, txlen);
360} 361}
361 362
362 363
diff --git a/drivers/isdn/mISDN/hwchannel.c b/drivers/isdn/mISDN/hwchannel.c
index ab1168a110a..0481a0cdf6d 100644
--- a/drivers/isdn/mISDN/hwchannel.c
+++ b/drivers/isdn/mISDN/hwchannel.c
@@ -185,13 +185,13 @@ recv_Echannel(struct dchannel *ech, struct dchannel *dch)
185EXPORT_SYMBOL(recv_Echannel); 185EXPORT_SYMBOL(recv_Echannel);
186 186
187void 187void
188recv_Bchannel(struct bchannel *bch) 188recv_Bchannel(struct bchannel *bch, unsigned int id)
189{ 189{
190 struct mISDNhead *hh; 190 struct mISDNhead *hh;
191 191
192 hh = mISDN_HEAD_P(bch->rx_skb); 192 hh = mISDN_HEAD_P(bch->rx_skb);
193 hh->prim = PH_DATA_IND; 193 hh->prim = PH_DATA_IND;
194 hh->id = MISDN_ID_ANY; 194 hh->id = id;
195 if (bch->rcount >= 64) { 195 if (bch->rcount >= 64) {
196 printk(KERN_WARNING "B-channel %p receive queue overflow, " 196 printk(KERN_WARNING "B-channel %p receive queue overflow, "
197 "fushing!\n", bch); 197 "fushing!\n", bch);
diff --git a/include/linux/mISDNdsp.h b/include/linux/mISDNdsp.h
index 6b71d2dce50..2c483d45f14 100644
--- a/include/linux/mISDNdsp.h
+++ b/include/linux/mISDNdsp.h
@@ -12,7 +12,8 @@ struct mISDN_dsp_element {
12 void *(*new)(const char *arg); 12 void *(*new)(const char *arg);
13 void (*free)(void *p); 13 void (*free)(void *p);
14 void (*process_tx)(void *p, unsigned char *data, int len); 14 void (*process_tx)(void *p, unsigned char *data, int len);
15 void (*process_rx)(void *p, unsigned char *data, int len); 15 void (*process_rx)(void *p, unsigned char *data, int len,
16 unsigned int txlen);
16 int num_args; 17 int num_args;
17 struct mISDN_dsp_element_arg 18 struct mISDN_dsp_element_arg
18 *args; 19 *args;
diff --git a/include/linux/mISDNhw.h b/include/linux/mISDNhw.h
index 97ffdc1d344..ce900f4c245 100644
--- a/include/linux/mISDNhw.h
+++ b/include/linux/mISDNhw.h
@@ -185,7 +185,7 @@ extern int dchannel_senddata(struct dchannel *, struct sk_buff *);
185extern int bchannel_senddata(struct bchannel *, struct sk_buff *); 185extern int bchannel_senddata(struct bchannel *, struct sk_buff *);
186extern void recv_Dchannel(struct dchannel *); 186extern void recv_Dchannel(struct dchannel *);
187extern void recv_Echannel(struct dchannel *, struct dchannel *); 187extern void recv_Echannel(struct dchannel *, struct dchannel *);
188extern void recv_Bchannel(struct bchannel *); 188extern void recv_Bchannel(struct bchannel *, unsigned int id);
189extern void recv_Dchannel_skb(struct dchannel *, struct sk_buff *); 189extern void recv_Dchannel_skb(struct dchannel *, struct sk_buff *);
190extern void recv_Bchannel_skb(struct bchannel *, struct sk_buff *); 190extern void recv_Bchannel_skb(struct bchannel *, struct sk_buff *);
191extern void confirm_Bsend(struct bchannel *bch); 191extern void confirm_Bsend(struct bchannel *bch);