Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 7cfa153d authored by Andreas Eversberg's avatar Andreas Eversberg Committed by David S. Miller
Browse files

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: default avatarAndreas Eversberg <andreas@eversberg.eu>
Signed-off-by: default avatarKarsten Keil <keil@b1-systems.de>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent a5355c27
Loading
Loading
Loading
Loading
+1 −0
Original line number Original line Diff line number Diff line
@@ -44,6 +44,7 @@ struct hfc_chan {
	int		conf;	/* conference setting of TX slot */
	int		conf;	/* conference setting of TX slot */
	int		txpending;	/* if there is currently data in */
	int		txpending;	/* if there is currently data in */
					/* the FIFO 0=no, 1=yes, 2=splloop */
					/* 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		rx_off; /* set to turn fifo receive off */
	int		coeff_count; /* curren coeff block */
	int		coeff_count; /* curren coeff block */
	s32		*coeff; /* memory pointer to 8 coeff blocks */
	s32		*coeff; /* memory pointer to 8 coeff blocks */
+6 −2
Original line number Original line Diff line number Diff line
@@ -1945,6 +1945,9 @@ next_frame:
				"%d!=%d\n", __func__, hc->id + 1, temp, z2);
				"%d!=%d\n", __func__, hc->id + 1, temp, z2);
		z2 = temp; /* repeat unti Z2 is equal */
		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;
	Zspace = z2 - z1;
	if (Zspace <= 0)
	if (Zspace <= 0)
		Zspace += hc->Zlen;
		Zspace += hc->Zlen;
@@ -2031,6 +2034,7 @@ next_frame:


	/* Have to prep the audio data */
	/* Have to prep the audio data */
	hc->write_fifo(hc, d, ii - i);
	hc->write_fifo(hc, d, ii - i);
	hc->chan[ch].Zfill += ii - i;
	*idxp = ii;
	*idxp = ii;


	/* if not all data has been written */
	/* if not all data has been written */
@@ -2226,7 +2230,7 @@ next_frame:
			if (dch)
			if (dch)
				recv_Dchannel(dch);
				recv_Dchannel(dch);
			else
			else
				recv_Bchannel(bch);
				recv_Bchannel(bch, MISDN_ID_ANY);
			*sp = skb;
			*sp = skb;
			again++;
			again++;
			goto next_frame;
			goto next_frame;
@@ -2258,7 +2262,7 @@ next_frame:
			    "(z1=%04x, z2=%04x) TRANS\n",
			    "(z1=%04x, z2=%04x) TRANS\n",
				__func__, hc->id + 1, ch, Zsize, z1, z2);
				__func__, hc->id + 1, ch, Zsize, z1, z2);
		/* only bch is transparent */
		/* only bch is transparent */
		recv_Bchannel(bch);
		recv_Bchannel(bch, hc->chan[ch].Zfill);
		*sp = skb;
		*sp = skb;
	}
	}
}
}
+41 −29
Original line number Original line Diff line number Diff line
@@ -452,7 +452,7 @@ hfcpci_empty_bfifo(struct bchannel *bch, struct bzfifo *bz,
		}
		}
		bz->za[new_f2].z2 = cpu_to_le16(new_z2);
		bz->za[new_f2].z2 = cpu_to_le16(new_z2);
		bz->f2 = new_f2;	/* next buffer */
		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
 * check for transparent receive data and read max one 'poll' size if avail
 */
 */
static void
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;
	 __le16	*z1r, *z2r, *z1t, *z2t;
	int		new_z2, fcnt, maxlen;
	int	new_z2, fcnt_rx, fcnt_tx, maxlen;
	u_char	*ptr, *ptr1;
	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;
	z2r = z1r + 1;
	z1t = &txbz->za[MAX_B_FRAMES].z1;
	z2t = z1t + 1;


	fcnt = le16_to_cpu(*z1r) - le16_to_cpu(*z2r);
	fcnt_rx = le16_to_cpu(*z1r) - le16_to_cpu(*z2r);
	if (!fcnt)
	if (!fcnt_rx)
		return;	/* no data avail */
		return;	/* no data avail */


	if (fcnt <= 0)
	if (fcnt_rx <= 0)
		fcnt += B_FIFO_SIZE;	/* bytes actually buffered */
		fcnt_rx += B_FIFO_SIZE;	/* bytes actually buffered */
	new_z2 = le16_to_cpu(*z2r) + fcnt;	/* new position in fifo */
	new_z2 = le16_to_cpu(*z2r) + fcnt_rx;	/* new position in fifo */
	if (new_z2 >= (B_FIFO_SIZE + B_SUB_VAL))
	if (new_z2 >= (B_FIFO_SIZE + B_SUB_VAL))
		new_z2 -= B_FIFO_SIZE;	/* buffer wrap */
		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 */
		*z2r = cpu_to_le16(new_z2);		/* new position */
		return;
		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) {
	if (bch->rx_skb) {
		ptr = skb_put(bch->rx_skb, fcnt);
		ptr = skb_put(bch->rx_skb, fcnt_rx);
		if (le16_to_cpu(*z2r) + fcnt <= B_FIFO_SIZE + B_SUB_VAL)
		if (le16_to_cpu(*z2r) + fcnt_rx <= B_FIFO_SIZE + B_SUB_VAL)
			maxlen = fcnt;	/* complete transfer */
			maxlen = fcnt_rx;	/* complete transfer */
		else
		else
			maxlen = B_FIFO_SIZE + B_SUB_VAL - le16_to_cpu(*z2r);
			maxlen = B_FIFO_SIZE + B_SUB_VAL - le16_to_cpu(*z2r);
			    /* maximum */
			    /* 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);
		ptr1 = bdata + (le16_to_cpu(*z2r) - B_SUB_VAL);
		    /* start of data */
		    /* start of data */
		memcpy(ptr, ptr1, maxlen);	/* copy data */
		memcpy(ptr, ptr1, maxlen);	/* copy data */
		fcnt -= maxlen;
		fcnt_rx -= maxlen;


		if (fcnt) {	/* rest remaining */
		if (fcnt_rx) {	/* rest remaining */
			ptr += maxlen;
			ptr += maxlen;
			ptr1 = bdata;	/* start of buffer */
			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
	} else
		printk(KERN_WARNING "HFCPCI: receive out of memory\n");
		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;
	struct hfc_pci	*hc = bch->hw;
	int		rcnt, real_fifo;
	int		rcnt, real_fifo;
	int		receive = 0, count = 5;
	int		receive = 0, count = 5;
	struct bzfifo	*bz;
	struct bzfifo	*txbz, *rxbz;
	u_char		*bdata;
	u_char		*bdata;
	struct zt	*zp;
	struct zt	*zp;


	if ((bch->nr & 2) && (!hc->hw.bswapped)) {
	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;
		bdata = ((union fifo_area *)(hc->hw.fifos))->b_chans.rxdat_b2;
		real_fifo = 1;
		real_fifo = 1;
	} else {
	} 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;
		bdata = ((union fifo_area *)(hc->hw.fifos))->b_chans.rxdat_b1;
		real_fifo = 0;
		real_fifo = 0;
	}
	}
Begin:
Begin:
	count--;
	count--;
	if (bz->f1 != bz->f2) {
	if (rxbz->f1 != rxbz->f2) {
		if (bch->debug & DEBUG_HW_BCHANNEL)
		if (bch->debug & DEBUG_HW_BCHANNEL)
			printk(KERN_DEBUG "hfcpci rec ch(%x) f1(%d) f2(%d)\n",
			printk(KERN_DEBUG "hfcpci rec ch(%x) f1(%d) f2(%d)\n",
			    bch->nr, bz->f1, bz->f2);
			    bch->nr, rxbz->f1, rxbz->f2);
		zp = &bz->za[bz->f2];
		zp = &rxbz->za[rxbz->f2];


		rcnt = le16_to_cpu(zp->z1) - le16_to_cpu(zp->z2);
		rcnt = le16_to_cpu(zp->z1) - le16_to_cpu(zp->z2);
		if (rcnt < 0)
		if (rcnt < 0)
@@ -630,8 +642,8 @@ Begin:
			    "hfcpci rec ch(%x) z1(%x) z2(%x) cnt(%d)\n",
			    "hfcpci rec ch(%x) z1(%x) z2(%x) cnt(%d)\n",
			    bch->nr, le16_to_cpu(zp->z1),
			    bch->nr, le16_to_cpu(zp->z1),
			    le16_to_cpu(zp->z2), rcnt);
			    le16_to_cpu(zp->z2), rcnt);
		hfcpci_empty_bfifo(bch, bz, bdata, rcnt);
		hfcpci_empty_bfifo(bch, rxbz, bdata, rcnt);
		rcnt = bz->f1 - bz->f2;
		rcnt = rxbz->f1 - rxbz->f2;
		if (rcnt < 0)
		if (rcnt < 0)
			rcnt += MAX_B_FRAMES + 1;
			rcnt += MAX_B_FRAMES + 1;
		if (hc->hw.last_bfifo_cnt[real_fifo] > rcnt + 1) {
		if (hc->hw.last_bfifo_cnt[real_fifo] > rcnt + 1) {
@@ -644,7 +656,7 @@ Begin:
		else
		else
			receive = 0;
			receive = 0;
	} else if (test_bit(FLG_TRANSPARENT, &bch->Flags)) {
	} else if (test_bit(FLG_TRANSPARENT, &bch->Flags)) {
		hfcpci_empty_fifo_trans(bch, bz, bdata);
		hfcpci_empty_fifo_trans(bch, rxbz, txbz, bdata);
		return;
		return;
	} else
	} else
		receive = 0;
		receive = 0;
+2 −2
Original line number Original line Diff line number Diff line
@@ -947,7 +947,7 @@ hfcsusb_rx_frame(struct usb_fifo *fifo, __u8 *data, unsigned int len,
				if (fifo->dch)
				if (fifo->dch)
					recv_Dchannel(fifo->dch);
					recv_Dchannel(fifo->dch);
				if (fifo->bch)
				if (fifo->bch)
					recv_Bchannel(fifo->bch);
					recv_Bchannel(fifo->bch, MISDN_ID_ANY);
				if (fifo->ech)
				if (fifo->ech)
					recv_Echannel(fifo->ech,
					recv_Echannel(fifo->ech,
						     &hw->dch);
						     &hw->dch);
@@ -969,7 +969,7 @@ hfcsusb_rx_frame(struct usb_fifo *fifo, __u8 *data, unsigned int len,
	} else {
	} else {
		/* deliver transparent data to layer2 */
		/* deliver transparent data to layer2 */
		if (rx_skb->len >= poll)
		if (rx_skb->len >= poll)
			recv_Bchannel(fifo->bch);
			recv_Bchannel(fifo->bch, MISDN_ID_ANY);
	}
	}
	spin_unlock(&hw->lock);
	spin_unlock(&hw->lock);
}
}
+1 −1
Original line number Original line Diff line number Diff line
@@ -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,
extern void dsp_pipeline_process_tx(struct dsp_pipeline *pipeline, u8 *data,
		int len);
		int len);
extern void dsp_pipeline_process_rx(struct dsp_pipeline *pipeline, u8 *data,
extern void dsp_pipeline_process_rx(struct dsp_pipeline *pipeline, u8 *data,
		int len);
		int len, unsigned int txlen);
Loading