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

Commit 8dd2f36f authored by Andreas Eversberg's avatar Andreas Eversberg Committed by Karsten Keil
Browse files

mISDN: Add feature via MISDN_CTRL_FILL_EMPTY to fill fifo if empty



This prevents underrun of fifo when filled and in case of an underrun it
prevents subsequent underruns due to jitter.
Improve dsp, so buffers are kept filled with a certain delay, so moderate
jitter will not cause underrun all the time -> the audio quality is highly
improved. tones are not interrupted by gaps anymore, except when CPU is
stalling or in high load.

Signed-off-by: default avatarAndreas Eversberg <andreas@eversberg.eu>
Signed-off-by: default avatarKarsten Keil <kkeil@suse.de>
parent 69e656cc
Loading
Loading
Loading
Loading
+3 −0
Original line number Diff line number Diff line
@@ -9,6 +9,7 @@
#define	DEBUG_HFCMULTI_MODE	0x00100000
#define	DEBUG_HFCMULTI_MSG	0x00200000
#define	DEBUG_HFCMULTI_STATE	0x00400000
#define	DEBUG_HFCMULTI_FILL	0x00800000
#define	DEBUG_HFCMULTI_SYNC	0x01000000
#define	DEBUG_HFCMULTI_DTMF	0x02000000
#define	DEBUG_HFCMULTI_LOCK	0x80000000
@@ -166,6 +167,8 @@ struct hfc_multi {

	u_long		chip;	/* chip configuration */
	int		masterclk; /* port that provides master clock -1=off */
	unsigned char	silence;/* silence byte */
	unsigned char	silence_data[128];/* silence block */
	int		dtmf;	/* flag that dtmf is currently in process */
	int		Flen;	/* F-buffer size */
	int		Zlen;	/* Z-buffer size (must be int for calculation)*/
+1 −0
Original line number Diff line number Diff line
@@ -27,6 +27,7 @@
 */
#define HFCPCI_BTRANS_THRESHOLD 128
#define HFCPCI_BTRANS_MAX	256
#define HFCPCI_FILLEMPTY	64
#define HFCPCI_BTRANS_THRESMASK 0x00

/* defines for PCI config */
+35 −10
Original line number Diff line number Diff line
@@ -180,7 +180,6 @@ static int nt_t1_count[] = { 3840, 1920, 960, 480, 240, 120, 60, 30 };
#define	CLKDEL_TE	0x0f	/* CLKDEL in TE mode */
#define	CLKDEL_NT	0x6c	/* CLKDEL in NT mode
				   (0x60 MUST be included!) */
static u_char silence =	0xff;	/* silence by LAW */

#define	DIP_4S	0x1		/* DIP Switches for Beronet 1S/2S/4S cards */
#define	DIP_8S	0x2		/* DIP Switches for Beronet 8S+ cards */
@@ -1975,6 +1974,17 @@ hfcmulti_tx(struct hfc_multi *hc, int ch)
		return; /* no data */
	}

	/* "fill fifo if empty" feature */
	if (bch && test_bit(FLG_FILLEMPTY, &bch->Flags)
		&& !test_bit(FLG_HDLC, &bch->Flags) && z2 == z1) {
		if (debug & DEBUG_HFCMULTI_FILL)
			printk(KERN_DEBUG "%s: buffer empty, so we have "
				"underrun\n", __func__);
		/* fill buffer, to prevent future underrun */
		hc->write_fifo(hc, hc->silence_data, poll >> 1);
		Zspace -= (poll >> 1);
	}

	/* if audio data and connected slot */
	if (bch && (!test_bit(FLG_HDLC, &bch->Flags)) && (!*txpending)
		&& slot_tx >= 0) {
@@ -2011,7 +2021,6 @@ hfcmulti_tx(struct hfc_multi *hc, int ch)
			__func__, hc->id + 1, ch, Zspace, z1, z2, ii-i, len-i,
			temp ? "HDLC":"TRANS");


	/* Have to prep the audio data */
	hc->write_fifo(hc, d, ii - i);
	*idxp = ii;
@@ -2050,7 +2059,7 @@ hfcmulti_tx(struct hfc_multi *hc, int ch)
	 * no more data at all. this prevents sending an undefined value.
	 */
	if (bch && test_bit(FLG_TRANSPARENT, &bch->Flags))
		HFC_outb_nodebug(hc, A_FIFO_DATA0_NOINC, silence);
		HFC_outb_nodebug(hc, A_FIFO_DATA0_NOINC, hc->silence);
}


@@ -2932,7 +2941,7 @@ mode_hfcmulti(struct hfc_multi *hc, int ch, int protocol, int slot_tx,
			HFC_outb(hc, R_INC_RES_FIFO, V_RES_F);
			HFC_wait(hc);
			/* tx silence */
			HFC_outb_nodebug(hc, A_FIFO_DATA0_NOINC, silence);
			HFC_outb_nodebug(hc, A_FIFO_DATA0_NOINC, hc->silence);
			HFC_outb(hc, R_SLOT, (((ch / 4) * 8) +
			    ((ch % 4) * 4)) << 1);
			HFC_outb(hc, A_SL_CFG, 0x80 | 0x20 | (ch << 1));
@@ -2947,7 +2956,7 @@ mode_hfcmulti(struct hfc_multi *hc, int ch, int protocol, int slot_tx,
			HFC_outb(hc, R_INC_RES_FIFO, V_RES_F);
			HFC_wait(hc);
			/* tx silence */
			HFC_outb_nodebug(hc, A_FIFO_DATA0_NOINC, silence);
			HFC_outb_nodebug(hc, A_FIFO_DATA0_NOINC, hc->silence);
			/* enable RX fifo */
			HFC_outb(hc, R_FIFO, (ch<<1)|1);
			HFC_wait(hc);
@@ -3439,7 +3448,7 @@ channel_bctrl(struct bchannel *bch, struct mISDN_ctrl_req *cq)
	switch (cq->op) {
	case MISDN_CTRL_GETOP:
		cq->op = MISDN_CTRL_HFC_OP | MISDN_CTRL_HW_FEATURES_OP
			| MISDN_CTRL_RX_OFF;
			| MISDN_CTRL_RX_OFF | MISDN_CTRL_FILL_EMPTY;
		break;
	case MISDN_CTRL_RX_OFF: /* turn off / on rx stream */
		hc->chan[bch->slot].rx_off = !!cq->p1;
@@ -3454,6 +3463,12 @@ channel_bctrl(struct bchannel *bch, struct mISDN_ctrl_req *cq)
			printk(KERN_DEBUG "%s: RX_OFF request (nr=%d off=%d)\n",
			    __func__, bch->nr, hc->chan[bch->slot].rx_off);
		break;
	case MISDN_CTRL_FILL_EMPTY: /* fill fifo, if empty */
		test_and_set_bit(FLG_FILLEMPTY, &bch->Flags);
		if (debug & DEBUG_HFCMULTI_MSG)
			printk(KERN_DEBUG "%s: FILL_EMPTY request (nr=%d "
				"off=%d)\n", __func__, bch->nr, !!cq->p1);
		break;
	case MISDN_CTRL_HW_FEATURES: /* fill features structure */
		if (debug & DEBUG_HFCMULTI_MSG)
			printk(KERN_DEBUG "%s: HW_FEATURE request\n",
@@ -3970,6 +3985,7 @@ open_bchannel(struct hfc_multi *hc, struct dchannel *dch,
	}
	if (test_and_set_bit(FLG_OPEN, &bch->Flags))
		return -EBUSY; /* b-channel can be only open once */
	test_and_clear_bit(FLG_FILLEMPTY, &bch->Flags);
	bch->ch.protocol = rq->protocol;
	hc->chan[ch].rx_off = 0;
	rq->ch = &bch->ch;
@@ -4806,6 +4822,7 @@ hfcmulti_init(struct pci_dev *pdev, const struct pci_device_id *ent)
	struct hfc_multi	*hc;
	u_long		flags;
	u_char		dips = 0, pmj = 0; /* dip settings, port mode Jumpers */
	int		i;

	if (HFC_cnt >= MAX_CARDS) {
		printk(KERN_ERR "too many cards (max=%d).\n",
@@ -4839,11 +4856,11 @@ hfcmulti_init(struct pci_dev *pdev, const struct pci_device_id *ent)
	hc->id = HFC_cnt;
	hc->pcm = pcm[HFC_cnt];
	hc->io_mode = iomode[HFC_cnt];
	if (dslot[HFC_cnt] < 0) {
	if (dslot[HFC_cnt] < 0 && hc->type == 1) {
		hc->dslot = 0;
		printk(KERN_INFO "HFC-E1 card has disabled D-channel, but "
			"31 B-channels\n");
	} if (dslot[HFC_cnt] > 0 && dslot[HFC_cnt] < 32) {
	} if (dslot[HFC_cnt] > 0 && dslot[HFC_cnt] < 32 && hc->type == 1) {
		hc->dslot = dslot[HFC_cnt];
		printk(KERN_INFO "HFC-E1 card has alternating D-channel on "
			"time slot %d\n", dslot[HFC_cnt]);
@@ -4854,9 +4871,17 @@ hfcmulti_init(struct pci_dev *pdev, const struct pci_device_id *ent)
	hc->masterclk = -1;
	if (type[HFC_cnt] & 0x100) {
		test_and_set_bit(HFC_CHIP_ULAW, &hc->chip);
		silence = 0xff; /* ulaw silence */
		hc->silence = 0xff; /* ulaw silence */
	} else
		silence = 0x2a; /* alaw silence */
		hc->silence = 0x2a; /* alaw silence */
	if ((poll >> 1) > sizeof(hc->silence_data)) {
		printk(KERN_ERR "HFCMULTI error: silence_data too small, "
			"please fix\n");
		return -EINVAL;
	}
	for (i = 0; i < (poll >> 1); i++)
		hc->silence_data[i] = hc->silence;

	if (!(type[HFC_cnt] & 0x200))
		test_and_set_bit(HFC_CHIP_DTMF, &hc->chip);

+39 −2
Original line number Diff line number Diff line
@@ -751,6 +751,36 @@ hfcpci_fill_fifo(struct bchannel *bch)
			    /* fcnt contains available bytes in fifo */
		fcnt = B_FIFO_SIZE - fcnt;
		    /* remaining bytes to send (bytes in fifo) */

		/* "fill fifo if empty" feature */
		if (test_bit(FLG_FILLEMPTY, &bch->Flags) && !fcnt) {
			/* printk(KERN_DEBUG "%s: buffer empty, so we have "
				"underrun\n", __func__); */
			/* fill buffer, to prevent future underrun */
			count = HFCPCI_FILLEMPTY;
			new_z1 = le16_to_cpu(*z1t) + count;
			   /* new buffer Position */
			if (new_z1 >= (B_FIFO_SIZE + B_SUB_VAL))
				new_z1 -= B_FIFO_SIZE;	/* buffer wrap */
			dst = bdata + (le16_to_cpu(*z1t) - B_SUB_VAL);
			maxlen = (B_FIFO_SIZE + B_SUB_VAL) - le16_to_cpu(*z1t);
			    /* end of fifo */
			if (bch->debug & DEBUG_HW_BFIFO)
				printk(KERN_DEBUG "hfcpci_FFt fillempty "
				    "fcnt(%d) maxl(%d) nz1(%x) dst(%p)\n",
				    fcnt, maxlen, new_z1, dst);
			fcnt += count;
			if (maxlen > count)
				maxlen = count; 	/* limit size */
			memset(dst, 0x2a, maxlen);	/* first copy */
			count -= maxlen;		/* remaining bytes */
			if (count) {
				dst = bdata;		/* start of buffer */
				memset(dst, 0x2a, count);
			}
			*z1t = cpu_to_le16(new_z1);	/* now send data */
		}

next_t_frame:
		count = bch->tx_skb->len - bch->tx_idx;
		/* maximum fill shall be HFCPCI_BTRANS_MAX */
@@ -1485,7 +1515,13 @@ channel_bctrl(struct bchannel *bch, struct mISDN_ctrl_req *cq)

	switch (cq->op) {
	case MISDN_CTRL_GETOP:
		cq->op = 0;
		cq->op = MISDN_CTRL_FILL_EMPTY;
		break;
	case MISDN_CTRL_FILL_EMPTY: /* fill fifo, if empty */
		test_and_set_bit(FLG_FILLEMPTY, &bch->Flags);
		if (debug & DEBUG_HW_OPEN)
			printk(KERN_DEBUG "%s: FILL_EMPTY request (nr=%d "
				"off=%d)\n", __func__, bch->nr, !!cq->p1);
		break;
	default:
		printk(KERN_WARNING "%s: unknown Op %x\n", __func__, cq->op);
@@ -1903,6 +1939,7 @@ open_bchannel(struct hfc_pci *hc, struct channel_req *rq)
	bch = &hc->bch[rq->adr.channel - 1];
	if (test_and_set_bit(FLG_OPEN, &bch->Flags))
		return -EBUSY; /* b-channel can be only open once */
	test_and_clear_bit(FLG_FILLEMPTY, &bch->Flags);
	bch->ch.protocol = rq->protocol;
	rq->ch = &bch->ch; /* TODO: E-channel */
	if (!try_module_get(THIS_MODULE))
+1 −0
Original line number Diff line number Diff line
@@ -198,6 +198,7 @@ struct dsp {
	/* hardware stuff */
	struct dsp_features features;
	int		features_rx_off; /* set if rx_off is featured */
	int		features_fill_empty; /* set if fill_empty is featured */
	int		pcm_slot_rx; /* current PCM slot (or -1) */
	int		pcm_bank_rx;
	int		pcm_slot_tx;
Loading