mISDN: Echo canceler now gets delay information from hardware
authorAndreas Eversberg <andreas@eversberg.eu>
Fri, 22 May 2009 11:04:46 +0000 (11:04 +0000)
committerDavid S. Miller <davem@davemloft.net>
Mon, 25 May 2009 07:51:31 +0000 (00:51 -0700)
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>
drivers/isdn/hardware/mISDN/hfc_multi.h
drivers/isdn/hardware/mISDN/hfcmulti.c
drivers/isdn/hardware/mISDN/hfcpci.c
drivers/isdn/hardware/mISDN/hfcsusb.c
drivers/isdn/mISDN/dsp.h
drivers/isdn/mISDN/dsp_core.c
drivers/isdn/mISDN/dsp_pipeline.c
drivers/isdn/mISDN/hwchannel.c
include/linux/mISDNdsp.h
include/linux/mISDNhw.h

index 5765e19629117c82e70e449ffe83b3533e0fdf58..c4878cc712c9d1024ef82051fd3d245a4e748f24 100644 (file)
@@ -44,6 +44,7 @@ struct hfc_chan {
        int             conf;   /* conference setting of TX slot */
        int             txpending;      /* if there is currently data in */
                                        /* the FIFO 0=no, 1=yes, 2=splloop */
+       int             Zfill;  /* rx-fifo level on last hfcmulti_tx */
        int             rx_off; /* set to turn fifo receive off */
        int             coeff_count; /* curren coeff block */
        s32             *coeff; /* memory pointer to 8 coeff blocks */
index ca153de6954e3384d8dbd44936aebc2828c78df1..3a7c26ce12cf8155e51f7407ad9df1f483e2f748 100644 (file)
@@ -1945,6 +1945,9 @@ next_frame:
                                "%d!=%d\n", __func__, hc->id + 1, temp, z2);
                z2 = temp; /* repeat unti Z2 is equal */
        }
+       hc->chan[ch].Zfill = z1 - z2;
+       if (hc->chan[ch].Zfill < 0)
+               hc->chan[ch].Zfill += hc->Zlen;
        Zspace = z2 - z1;
        if (Zspace <= 0)
                Zspace += hc->Zlen;
@@ -2031,6 +2034,7 @@ next_frame:
 
        /* Have to prep the audio data */
        hc->write_fifo(hc, d, ii - i);
+       hc->chan[ch].Zfill += ii - i;
        *idxp = ii;
 
        /* if not all data has been written */
@@ -2226,7 +2230,7 @@ next_frame:
                        if (dch)
                                recv_Dchannel(dch);
                        else
-                               recv_Bchannel(bch);
+                               recv_Bchannel(bch, MISDN_ID_ANY);
                        *sp = skb;
                        again++;
                        goto next_frame;
@@ -2258,7 +2262,7 @@ next_frame:
                            "(z1=%04x, z2=%04x) TRANS\n",
                                __func__, hc->id + 1, ch, Zsize, z1, z2);
                /* only bch is transparent */
-               recv_Bchannel(bch);
+               recv_Bchannel(bch, hc->chan[ch].Zfill);
                *sp = skb;
        }
 }
index 641a9cd1a5323947a00ef1e14bb150265ca287b5..60dc92562c6ddfd1bbe0c3f8b32048b3dcb572ec 100644 (file)
@@ -452,7 +452,7 @@ hfcpci_empty_bfifo(struct bchannel *bch, struct bzfifo *bz,
                }
                bz->za[new_f2].z2 = cpu_to_le16(new_z2);
                bz->f2 = new_f2;        /* next buffer */
-               recv_Bchannel(bch);
+               recv_Bchannel(bch, MISDN_ID_ANY);
        }
 }
 
@@ -541,35 +541,45 @@ receive_dmsg(struct hfc_pci *hc)
  * check for transparent receive data and read max one 'poll' size if avail
  */
 static void
-hfcpci_empty_fifo_trans(struct bchannel *bch, struct bzfifo *bz, u_char *bdata)
+hfcpci_empty_fifo_trans(struct bchannel *bch, struct bzfifo *rxbz,
+       struct bzfifo *txbz, u_char *bdata)
 {
-        __le16 *z1r, *z2r;
-       int             new_z2, fcnt, maxlen;
-       u_char          *ptr, *ptr1;
+        __le16 *z1r, *z2r, *z1t, *z2t;
+       int     new_z2, fcnt_rx, fcnt_tx, maxlen;
+       u_char  *ptr, *ptr1;
 
-       z1r = &bz->za[MAX_B_FRAMES].z1;         /* pointer to z reg */
+       z1r = &rxbz->za[MAX_B_FRAMES].z1;       /* pointer to z reg */
        z2r = z1r + 1;
+       z1t = &txbz->za[MAX_B_FRAMES].z1;
+       z2t = z1t + 1;
 
-       fcnt = le16_to_cpu(*z1r) - le16_to_cpu(*z2r);
-       if (!fcnt)
+       fcnt_rx = le16_to_cpu(*z1r) - le16_to_cpu(*z2r);
+       if (!fcnt_rx)
                return; /* no data avail */
 
-       if (fcnt <= 0)
-               fcnt += B_FIFO_SIZE;    /* bytes actually buffered */
-       new_z2 = le16_to_cpu(*z2r) + fcnt;      /* new position in fifo */
+       if (fcnt_rx <= 0)
+               fcnt_rx += B_FIFO_SIZE; /* bytes actually buffered */
+       new_z2 = le16_to_cpu(*z2r) + fcnt_rx;   /* new position in fifo */
        if (new_z2 >= (B_FIFO_SIZE + B_SUB_VAL))
                new_z2 -= B_FIFO_SIZE;  /* buffer wrap */
 
-       if (fcnt > MAX_DATA_SIZE) {     /* flush, if oversized */
+       if (fcnt_rx > MAX_DATA_SIZE) {  /* flush, if oversized */
                *z2r = cpu_to_le16(new_z2);             /* new position */
                return;
        }
 
-       bch->rx_skb = mI_alloc_skb(fcnt, GFP_ATOMIC);
+       fcnt_tx = le16_to_cpu(*z2t) - le16_to_cpu(*z1t);
+       if (fcnt_tx <= 0)
+               fcnt_tx += B_FIFO_SIZE;
+                   /* fcnt_tx contains available bytes in tx-fifo */
+       fcnt_tx = B_FIFO_SIZE - fcnt_tx;
+                   /* remaining bytes to send (bytes in tx-fifo) */
+
+       bch->rx_skb = mI_alloc_skb(fcnt_rx, GFP_ATOMIC);
        if (bch->rx_skb) {
-               ptr = skb_put(bch->rx_skb, fcnt);
-               if (le16_to_cpu(*z2r) + fcnt <= B_FIFO_SIZE + B_SUB_VAL)
-                       maxlen = fcnt;  /* complete transfer */
+               ptr = skb_put(bch->rx_skb, fcnt_rx);
+               if (le16_to_cpu(*z2r) + fcnt_rx <= B_FIFO_SIZE + B_SUB_VAL)
+                       maxlen = fcnt_rx;       /* complete transfer */
                else
                        maxlen = B_FIFO_SIZE + B_SUB_VAL - le16_to_cpu(*z2r);
                            /* maximum */
@@ -577,14 +587,14 @@ hfcpci_empty_fifo_trans(struct bchannel *bch, struct bzfifo *bz, u_char *bdata)
                ptr1 = bdata + (le16_to_cpu(*z2r) - B_SUB_VAL);
                    /* start of data */
                memcpy(ptr, ptr1, maxlen);      /* copy data */
-               fcnt -= maxlen;
+               fcnt_rx -= maxlen;
 
-               if (fcnt) {     /* rest remaining */
+               if (fcnt_rx) {  /* rest remaining */
                        ptr += maxlen;
                        ptr1 = bdata;   /* start of buffer */
-                       memcpy(ptr, ptr1, fcnt);        /* rest */
+                       memcpy(ptr, ptr1, fcnt_rx);     /* rest */
                }
-               recv_Bchannel(bch);
+               recv_Bchannel(bch, fcnt_tx); /* bch, id */
        } else
                printk(KERN_WARNING "HFCPCI: receive out of memory\n");
 
@@ -600,26 +610,28 @@ main_rec_hfcpci(struct bchannel *bch)
        struct hfc_pci  *hc = bch->hw;
        int             rcnt, real_fifo;
        int             receive = 0, count = 5;
-       struct bzfifo   *bz;
+       struct bzfifo   *txbz, *rxbz;
        u_char          *bdata;
        struct zt       *zp;
 
        if ((bch->nr & 2) && (!hc->hw.bswapped)) {
-               bz = &((union fifo_area *)(hc->hw.fifos))->b_chans.rxbz_b2;
+               rxbz = &((union fifo_area *)(hc->hw.fifos))->b_chans.rxbz_b2;
+               txbz = &((union fifo_area *)(hc->hw.fifos))->b_chans.txbz_b2;
                bdata = ((union fifo_area *)(hc->hw.fifos))->b_chans.rxdat_b2;
                real_fifo = 1;
        } else {
-               bz = &((union fifo_area *)(hc->hw.fifos))->b_chans.rxbz_b1;
+               rxbz = &((union fifo_area *)(hc->hw.fifos))->b_chans.rxbz_b1;
+               txbz = &((union fifo_area *)(hc->hw.fifos))->b_chans.txbz_b1;
                bdata = ((union fifo_area *)(hc->hw.fifos))->b_chans.rxdat_b1;
                real_fifo = 0;
        }
 Begin:
        count--;
-       if (bz->f1 != bz->f2) {
+       if (rxbz->f1 != rxbz->f2) {
                if (bch->debug & DEBUG_HW_BCHANNEL)
                        printk(KERN_DEBUG "hfcpci rec ch(%x) f1(%d) f2(%d)\n",
-                           bch->nr, bz->f1, bz->f2);
-               zp = &bz->za[bz->f2];
+                           bch->nr, rxbz->f1, rxbz->f2);
+               zp = &rxbz->za[rxbz->f2];
 
                rcnt = le16_to_cpu(zp->z1) - le16_to_cpu(zp->z2);
                if (rcnt < 0)
@@ -630,8 +642,8 @@ Begin:
                            "hfcpci rec ch(%x) z1(%x) z2(%x) cnt(%d)\n",
                            bch->nr, le16_to_cpu(zp->z1),
                            le16_to_cpu(zp->z2), rcnt);
-               hfcpci_empty_bfifo(bch, bz, bdata, rcnt);
-               rcnt = bz->f1 - bz->f2;
+               hfcpci_empty_bfifo(bch, rxbz, bdata, rcnt);
+               rcnt = rxbz->f1 - rxbz->f2;
                if (rcnt < 0)
                        rcnt += MAX_B_FRAMES + 1;
                if (hc->hw.last_bfifo_cnt[real_fifo] > rcnt + 1) {
@@ -644,7 +656,7 @@ Begin:
                else
                        receive = 0;
        } else if (test_bit(FLG_TRANSPARENT, &bch->Flags)) {
-               hfcpci_empty_fifo_trans(bch, bz, bdata);
+               hfcpci_empty_fifo_trans(bch, rxbz, txbz, bdata);
                return;
        } else
                receive = 0;
index 9c427fb204eec17f43e848c77f996b05914f592f..6b7704c41b947e4cc23b313c65caf40b64069367 100644 (file)
@@ -947,7 +947,7 @@ hfcsusb_rx_frame(struct usb_fifo *fifo, __u8 *data, unsigned int len,
                                if (fifo->dch)
                                        recv_Dchannel(fifo->dch);
                                if (fifo->bch)
-                                       recv_Bchannel(fifo->bch);
+                                       recv_Bchannel(fifo->bch, MISDN_ID_ANY);
                                if (fifo->ech)
                                        recv_Echannel(fifo->ech,
                                                     &hw->dch);
@@ -969,7 +969,7 @@ hfcsusb_rx_frame(struct usb_fifo *fifo, __u8 *data, unsigned int len,
        } else {
                /* deliver transparent data to layer2 */
                if (rx_skb->len >= poll)
-                       recv_Bchannel(fifo->bch);
+                       recv_Bchannel(fifo->bch, MISDN_ID_ANY);
        }
        spin_unlock(&hw->lock);
 }
index 0a4a362b89ceca25fe8d58926fd577e0060e571b..4a1c444d73acd324720288934667333e78c0167a 100644 (file)
@@ -262,5 +262,5 @@ extern int  dsp_pipeline_build(struct dsp_pipeline *pipeline, const char *cfg);
 extern void dsp_pipeline_process_tx(struct dsp_pipeline *pipeline, u8 *data,
                int len);
 extern void dsp_pipeline_process_rx(struct dsp_pipeline *pipeline, u8 *data,
-               int len);
+               int len, unsigned int txlen);
 
index 3083338716b262eb8a730ee4c5fbc4dd3f202e27..1c49368e0a90b34800d15a9d8078b734c66133db 100644 (file)
@@ -710,7 +710,7 @@ dsp_function(struct mISDNchannel *ch,  struct sk_buff *skb)
                /* pipeline */
                if (dsp->pipeline.inuse)
                        dsp_pipeline_process_rx(&dsp->pipeline, skb->data,
-                               skb->len);
+                               skb->len, hh->id);
                /* change volume if requested */
                if (dsp->rx_volume)
                        dsp_change_volume(skb, dsp->rx_volume);
index 18cf87c113e725cb9f7adc157963bb0105e3d5ea..ac61f198eb32031400823055f34015ff988f607d 100644 (file)
@@ -347,7 +347,8 @@ void dsp_pipeline_process_tx(struct dsp_pipeline *pipeline, u8 *data, int len)
                        entry->elem->process_tx(entry->p, data, len);
 }
 
-void dsp_pipeline_process_rx(struct dsp_pipeline *pipeline, u8 *data, int len)
+void dsp_pipeline_process_rx(struct dsp_pipeline *pipeline, u8 *data, int len,
+       unsigned int txlen)
 {
        struct dsp_pipeline_entry *entry;
 
@@ -356,7 +357,7 @@ void dsp_pipeline_process_rx(struct dsp_pipeline *pipeline, u8 *data, int len)
 
        list_for_each_entry_reverse(entry, &pipeline->list, list)
                if (entry->elem->process_rx)
-                       entry->elem->process_rx(entry->p, data, len);
+                       entry->elem->process_rx(entry->p, data, len, txlen);
 }
 
 
index ab1168a110ae96104c7db2ea8ea12ae214d83fe1..0481a0cdf6db9a1915ea8423f4d389655e86c66f 100644 (file)
@@ -185,13 +185,13 @@ recv_Echannel(struct dchannel *ech, struct dchannel *dch)
 EXPORT_SYMBOL(recv_Echannel);
 
 void
-recv_Bchannel(struct bchannel *bch)
+recv_Bchannel(struct bchannel *bch, unsigned int id)
 {
        struct mISDNhead *hh;
 
        hh = mISDN_HEAD_P(bch->rx_skb);
        hh->prim = PH_DATA_IND;
-       hh->id = MISDN_ID_ANY;
+       hh->id = id;
        if (bch->rcount >= 64) {
                printk(KERN_WARNING "B-channel %p receive queue overflow, "
                        "fushing!\n", bch);
index 6b71d2dce50855aa637ed5d32648e657a5433115..2c483d45f141e20a77d724d4ea2f5242d574a5fa 100644 (file)
@@ -12,7 +12,8 @@ struct mISDN_dsp_element {
        void    *(*new)(const char *arg);
        void    (*free)(void *p);
        void    (*process_tx)(void *p, unsigned char *data, int len);
-       void    (*process_rx)(void *p, unsigned char *data, int len);
+       void    (*process_rx)(void *p, unsigned char *data, int len,
+                       unsigned int txlen);
        int     num_args;
        struct mISDN_dsp_element_arg
                *args;
index 97ffdc1d344245c99085fbc2d1007188a50091b0..ce900f4c2458c8a88d829a55bffe2f719a8869a7 100644 (file)
@@ -185,7 +185,7 @@ extern int  dchannel_senddata(struct dchannel *, struct sk_buff *);
 extern int     bchannel_senddata(struct bchannel *, struct sk_buff *);
 extern void    recv_Dchannel(struct dchannel *);
 extern void    recv_Echannel(struct dchannel *, struct dchannel *);
-extern void    recv_Bchannel(struct bchannel *);
+extern void    recv_Bchannel(struct bchannel *, unsigned int id);
 extern void    recv_Dchannel_skb(struct dchannel *, struct sk_buff *);
 extern void    recv_Bchannel_skb(struct bchannel *, struct sk_buff *);
 extern void    confirm_Bsend(struct bchannel *bch);