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

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
...@@ -9,6 +9,7 @@ ...@@ -9,6 +9,7 @@
#define DEBUG_HFCMULTI_MODE 0x00100000 #define DEBUG_HFCMULTI_MODE 0x00100000
#define DEBUG_HFCMULTI_MSG 0x00200000 #define DEBUG_HFCMULTI_MSG 0x00200000
#define DEBUG_HFCMULTI_STATE 0x00400000 #define DEBUG_HFCMULTI_STATE 0x00400000
#define DEBUG_HFCMULTI_FILL 0x00800000
#define DEBUG_HFCMULTI_SYNC 0x01000000 #define DEBUG_HFCMULTI_SYNC 0x01000000
#define DEBUG_HFCMULTI_DTMF 0x02000000 #define DEBUG_HFCMULTI_DTMF 0x02000000
#define DEBUG_HFCMULTI_LOCK 0x80000000 #define DEBUG_HFCMULTI_LOCK 0x80000000
...@@ -166,6 +167,8 @@ struct hfc_multi { ...@@ -166,6 +167,8 @@ struct hfc_multi {
u_long chip; /* chip configuration */ u_long chip; /* chip configuration */
int masterclk; /* port that provides master clock -1=off */ 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 dtmf; /* flag that dtmf is currently in process */
int Flen; /* F-buffer size */ int Flen; /* F-buffer size */
int Zlen; /* Z-buffer size (must be int for calculation)*/ int Zlen; /* Z-buffer size (must be int for calculation)*/
......
...@@ -27,6 +27,7 @@ ...@@ -27,6 +27,7 @@
*/ */
#define HFCPCI_BTRANS_THRESHOLD 128 #define HFCPCI_BTRANS_THRESHOLD 128
#define HFCPCI_BTRANS_MAX 256 #define HFCPCI_BTRANS_MAX 256
#define HFCPCI_FILLEMPTY 64
#define HFCPCI_BTRANS_THRESMASK 0x00 #define HFCPCI_BTRANS_THRESMASK 0x00
/* defines for PCI config */ /* defines for PCI config */
......
...@@ -180,7 +180,6 @@ static int nt_t1_count[] = { 3840, 1920, 960, 480, 240, 120, 60, 30 }; ...@@ -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_TE 0x0f /* CLKDEL in TE mode */
#define CLKDEL_NT 0x6c /* CLKDEL in NT mode #define CLKDEL_NT 0x6c /* CLKDEL in NT mode
(0x60 MUST be included!) */ (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_4S 0x1 /* DIP Switches for Beronet 1S/2S/4S cards */
#define DIP_8S 0x2 /* DIP Switches for Beronet 8S+ cards */ #define DIP_8S 0x2 /* DIP Switches for Beronet 8S+ cards */
...@@ -1975,6 +1974,17 @@ next_frame: ...@@ -1975,6 +1974,17 @@ next_frame:
return; /* no data */ 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 audio data and connected slot */
if (bch && (!test_bit(FLG_HDLC, &bch->Flags)) && (!*txpending) if (bch && (!test_bit(FLG_HDLC, &bch->Flags)) && (!*txpending)
&& slot_tx >= 0) { && slot_tx >= 0) {
...@@ -2011,7 +2021,6 @@ next_frame: ...@@ -2011,7 +2021,6 @@ next_frame:
__func__, hc->id + 1, ch, Zspace, z1, z2, ii-i, len-i, __func__, hc->id + 1, ch, Zspace, z1, z2, ii-i, len-i,
temp ? "HDLC":"TRANS"); temp ? "HDLC":"TRANS");
/* 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);
*idxp = ii; *idxp = ii;
...@@ -2050,7 +2059,7 @@ next_frame: ...@@ -2050,7 +2059,7 @@ next_frame:
* no more data at all. this prevents sending an undefined value. * no more data at all. this prevents sending an undefined value.
*/ */
if (bch && test_bit(FLG_TRANSPARENT, &bch->Flags)) 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, ...@@ -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_outb(hc, R_INC_RES_FIFO, V_RES_F);
HFC_wait(hc); HFC_wait(hc);
/* tx silence */ /* 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) + HFC_outb(hc, R_SLOT, (((ch / 4) * 8) +
((ch % 4) * 4)) << 1); ((ch % 4) * 4)) << 1);
HFC_outb(hc, A_SL_CFG, 0x80 | 0x20 | (ch << 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, ...@@ -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_outb(hc, R_INC_RES_FIFO, V_RES_F);
HFC_wait(hc); HFC_wait(hc);
/* tx silence */ /* tx silence */
HFC_outb_nodebug(hc, A_FIFO_DATA0_NOINC, silence); HFC_outb_nodebug(hc, A_FIFO_DATA0_NOINC, hc->silence);
/* enable RX fifo */ /* enable RX fifo */
HFC_outb(hc, R_FIFO, (ch<<1)|1); HFC_outb(hc, R_FIFO, (ch<<1)|1);
HFC_wait(hc); HFC_wait(hc);
...@@ -3439,7 +3448,7 @@ channel_bctrl(struct bchannel *bch, struct mISDN_ctrl_req *cq) ...@@ -3439,7 +3448,7 @@ channel_bctrl(struct bchannel *bch, struct mISDN_ctrl_req *cq)
switch (cq->op) { switch (cq->op) {
case MISDN_CTRL_GETOP: case MISDN_CTRL_GETOP:
cq->op = MISDN_CTRL_HFC_OP | MISDN_CTRL_HW_FEATURES_OP cq->op = MISDN_CTRL_HFC_OP | MISDN_CTRL_HW_FEATURES_OP
| MISDN_CTRL_RX_OFF; | MISDN_CTRL_RX_OFF | MISDN_CTRL_FILL_EMPTY;
break; break;
case MISDN_CTRL_RX_OFF: /* turn off / on rx stream */ case MISDN_CTRL_RX_OFF: /* turn off / on rx stream */
hc->chan[bch->slot].rx_off = !!cq->p1; hc->chan[bch->slot].rx_off = !!cq->p1;
...@@ -3454,6 +3463,12 @@ channel_bctrl(struct bchannel *bch, struct mISDN_ctrl_req *cq) ...@@ -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", printk(KERN_DEBUG "%s: RX_OFF request (nr=%d off=%d)\n",
__func__, bch->nr, hc->chan[bch->slot].rx_off); __func__, bch->nr, hc->chan[bch->slot].rx_off);
break; 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 */ case MISDN_CTRL_HW_FEATURES: /* fill features structure */
if (debug & DEBUG_HFCMULTI_MSG) if (debug & DEBUG_HFCMULTI_MSG)
printk(KERN_DEBUG "%s: HW_FEATURE request\n", printk(KERN_DEBUG "%s: HW_FEATURE request\n",
...@@ -3970,6 +3985,7 @@ open_bchannel(struct hfc_multi *hc, struct dchannel *dch, ...@@ -3970,6 +3985,7 @@ open_bchannel(struct hfc_multi *hc, struct dchannel *dch,
} }
if (test_and_set_bit(FLG_OPEN, &bch->Flags)) if (test_and_set_bit(FLG_OPEN, &bch->Flags))
return -EBUSY; /* b-channel can be only open once */ return -EBUSY; /* b-channel can be only open once */
test_and_clear_bit(FLG_FILLEMPTY, &bch->Flags);
bch->ch.protocol = rq->protocol; bch->ch.protocol = rq->protocol;
hc->chan[ch].rx_off = 0; hc->chan[ch].rx_off = 0;
rq->ch = &bch->ch; rq->ch = &bch->ch;
...@@ -4806,6 +4822,7 @@ hfcmulti_init(struct pci_dev *pdev, const struct pci_device_id *ent) ...@@ -4806,6 +4822,7 @@ hfcmulti_init(struct pci_dev *pdev, const struct pci_device_id *ent)
struct hfc_multi *hc; struct hfc_multi *hc;
u_long flags; u_long flags;
u_char dips = 0, pmj = 0; /* dip settings, port mode Jumpers */ u_char dips = 0, pmj = 0; /* dip settings, port mode Jumpers */
int i;
if (HFC_cnt >= MAX_CARDS) { if (HFC_cnt >= MAX_CARDS) {
printk(KERN_ERR "too many cards (max=%d).\n", 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) ...@@ -4839,11 +4856,11 @@ hfcmulti_init(struct pci_dev *pdev, const struct pci_device_id *ent)
hc->id = HFC_cnt; hc->id = HFC_cnt;
hc->pcm = pcm[HFC_cnt]; hc->pcm = pcm[HFC_cnt];
hc->io_mode = iomode[HFC_cnt]; hc->io_mode = iomode[HFC_cnt];
if (dslot[HFC_cnt] < 0) { if (dslot[HFC_cnt] < 0 && hc->type == 1) {
hc->dslot = 0; hc->dslot = 0;
printk(KERN_INFO "HFC-E1 card has disabled D-channel, but " printk(KERN_INFO "HFC-E1 card has disabled D-channel, but "
"31 B-channels\n"); "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]; hc->dslot = dslot[HFC_cnt];
printk(KERN_INFO "HFC-E1 card has alternating D-channel on " printk(KERN_INFO "HFC-E1 card has alternating D-channel on "
"time slot %d\n", dslot[HFC_cnt]); "time slot %d\n", dslot[HFC_cnt]);
...@@ -4854,9 +4871,17 @@ hfcmulti_init(struct pci_dev *pdev, const struct pci_device_id *ent) ...@@ -4854,9 +4871,17 @@ hfcmulti_init(struct pci_dev *pdev, const struct pci_device_id *ent)
hc->masterclk = -1; hc->masterclk = -1;
if (type[HFC_cnt] & 0x100) { if (type[HFC_cnt] & 0x100) {
test_and_set_bit(HFC_CHIP_ULAW, &hc->chip); test_and_set_bit(HFC_CHIP_ULAW, &hc->chip);
silence = 0xff; /* ulaw silence */ hc->silence = 0xff; /* ulaw silence */
} else } 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)) if (!(type[HFC_cnt] & 0x200))
test_and_set_bit(HFC_CHIP_DTMF, &hc->chip); test_and_set_bit(HFC_CHIP_DTMF, &hc->chip);
......
...@@ -751,6 +751,36 @@ hfcpci_fill_fifo(struct bchannel *bch) ...@@ -751,6 +751,36 @@ hfcpci_fill_fifo(struct bchannel *bch)
/* fcnt contains available bytes in fifo */ /* fcnt contains available bytes in fifo */
fcnt = B_FIFO_SIZE - fcnt; fcnt = B_FIFO_SIZE - fcnt;
/* remaining bytes to send (bytes in fifo) */ /* 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: next_t_frame:
count = bch->tx_skb->len - bch->tx_idx; count = bch->tx_skb->len - bch->tx_idx;
/* maximum fill shall be HFCPCI_BTRANS_MAX */ /* maximum fill shall be HFCPCI_BTRANS_MAX */
...@@ -1481,11 +1511,17 @@ deactivate_bchannel(struct bchannel *bch) ...@@ -1481,11 +1511,17 @@ deactivate_bchannel(struct bchannel *bch)
static int static int
channel_bctrl(struct bchannel *bch, struct mISDN_ctrl_req *cq) channel_bctrl(struct bchannel *bch, struct mISDN_ctrl_req *cq)
{ {
int ret = 0; int ret = 0;
switch (cq->op) { switch (cq->op) {
case MISDN_CTRL_GETOP: 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; break;
default: default:
printk(KERN_WARNING "%s: unknown Op %x\n", __func__, cq->op); 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) ...@@ -1903,6 +1939,7 @@ open_bchannel(struct hfc_pci *hc, struct channel_req *rq)
bch = &hc->bch[rq->adr.channel - 1]; bch = &hc->bch[rq->adr.channel - 1];
if (test_and_set_bit(FLG_OPEN, &bch->Flags)) if (test_and_set_bit(FLG_OPEN, &bch->Flags))
return -EBUSY; /* b-channel can be only open once */ return -EBUSY; /* b-channel can be only open once */
test_and_clear_bit(FLG_FILLEMPTY, &bch->Flags);
bch->ch.protocol = rq->protocol; bch->ch.protocol = rq->protocol;
rq->ch = &bch->ch; /* TODO: E-channel */ rq->ch = &bch->ch; /* TODO: E-channel */
if (!try_module_get(THIS_MODULE)) if (!try_module_get(THIS_MODULE))
......
...@@ -198,6 +198,7 @@ struct dsp { ...@@ -198,6 +198,7 @@ struct dsp {
/* hardware stuff */ /* hardware stuff */
struct dsp_features features; struct dsp_features features;
int features_rx_off; /* set if rx_off is featured */ 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_slot_rx; /* current PCM slot (or -1) */
int pcm_bank_rx; int pcm_bank_rx;
int pcm_slot_tx; int pcm_slot_tx;
......
...@@ -1168,11 +1168,18 @@ dsp_cmx_receive(struct dsp *dsp, struct sk_buff *skb) ...@@ -1168,11 +1168,18 @@ dsp_cmx_receive(struct dsp *dsp, struct sk_buff *skb)
dsp->rx_init = 0; dsp->rx_init = 0;
if (dsp->features.unordered) { if (dsp->features.unordered) {
dsp->rx_R = (hh->id & CMX_BUFF_MASK); dsp->rx_R = (hh->id & CMX_BUFF_MASK);
dsp->rx_W = (dsp->rx_R + dsp->cmx_delay) if (dsp->cmx_delay)
& CMX_BUFF_MASK; dsp->rx_W = (dsp->rx_R + dsp->cmx_delay)
& CMX_BUFF_MASK;
else
dsp->rx_W = (dsp->rx_R + (dsp_poll >> 1))
& CMX_BUFF_MASK;
} else { } else {
dsp->rx_R = 0; dsp->rx_R = 0;
dsp->rx_W = dsp->cmx_delay; if (dsp->cmx_delay)
dsp->rx_W = dsp->cmx_delay;
else
dsp->rx_W = dsp_poll >> 1;
} }
} }
/* if frame contains time code, write directly */ /* if frame contains time code, write directly */
...@@ -1190,14 +1197,20 @@ dsp_cmx_receive(struct dsp *dsp, struct sk_buff *skb) ...@@ -1190,14 +1197,20 @@ dsp_cmx_receive(struct dsp *dsp, struct sk_buff *skb)
"cmx_receive(dsp=%lx): UNDERRUN (or overrun the " "cmx_receive(dsp=%lx): UNDERRUN (or overrun the "
"maximum delay), adjusting read pointer! " "maximum delay), adjusting read pointer! "
"(inst %s)\n", (u_long)dsp, dsp->name); "(inst %s)\n", (u_long)dsp, dsp->name);
/* flush buffer */ /* flush rx buffer and set delay to dsp_poll / 2 */
if (dsp->features.unordered) { if (dsp->features.unordered) {
dsp->rx_R = (hh->id & CMX_BUFF_MASK); dsp->rx_R = (hh->id & CMX_BUFF_MASK);
dsp->rx_W = (dsp->rx_R + dsp->cmx_delay) if (dsp->cmx_delay)
& CMX_BUFF_MASK; dsp->rx_W = (dsp->rx_R + dsp->cmx_delay)
& CMX_BUFF_MASK;
dsp->rx_W = (dsp->rx_R + (dsp_poll >> 1))
& CMX_BUFF_MASK;
} else { } else {
dsp->rx_R = 0; dsp->rx_R = 0;
dsp->rx_W = dsp->cmx_delay; if (dsp->cmx_delay)
dsp->rx_W = dsp->cmx_delay;
else
dsp->rx_W = dsp_poll >> 1;
} }
memset(dsp->rx_buff, dsp_silence, sizeof(dsp->rx_buff)); memset(dsp->rx_buff, dsp_silence, sizeof(dsp->rx_buff));
} }
...@@ -1360,8 +1373,11 @@ dsp_cmx_send_member(struct dsp *dsp, int len, s32 *c, int members) ...@@ -1360,8 +1373,11 @@ dsp_cmx_send_member(struct dsp *dsp, int len, s32 *c, int members)
t = (t+1) & CMX_BUFF_MASK; t = (t+1) & CMX_BUFF_MASK;
r = (r+1) & CMX_BUFF_MASK; r = (r+1) & CMX_BUFF_MASK;
} }
if (r != rr) if (r != rr) {
printk(KERN_DEBUG "%s: buffer empty\n",
__func__);
memset(d, dsp_silence, (rr-r)&CMX_BUFF_MASK); memset(d, dsp_silence, (rr-r)&CMX_BUFF_MASK);
}
/* -> if echo is enabled */ /* -> if echo is enabled */
} else { } else {
/* /*
...@@ -1704,9 +1720,10 @@ dsp_cmx_send(void *arg) ...@@ -1704,9 +1720,10 @@ dsp_cmx_send(void *arg)
} }
/* /*
* remove rx_delay only if we have delay AND we * remove rx_delay only if we have delay AND we
* have not preset cmx_delay * have not preset cmx_delay AND
* the delay is greater dsp_poll
*/ */
if (delay && !dsp->cmx_delay) { if (delay > dsp_poll && !dsp->cmx_delay) {
if (dsp_debug & DEBUG_DSP_CMX) if (dsp_debug & DEBUG_DSP_CMX)
printk(KERN_DEBUG printk(KERN_DEBUG
"%s lowest rx_delay of %d bytes for" "%s lowest rx_delay of %d bytes for"
...@@ -1714,7 +1731,8 @@ dsp_cmx_send(void *arg) ...@@ -1714,7 +1731,8 @@ dsp_cmx_send(void *arg)
__func__, delay, __func__, delay,
dsp->name); dsp->name);
r = dsp->rx_R; r = dsp->rx_R;
rr = (r + delay) & CMX_BUFF_MASK; rr = (r + delay - (dsp_poll >> 1))
& CMX_BUFF_MASK;
/* delete rx-data */ /* delete rx-data */
while (r != rr) { while (r != rr) {
p[r] = dsp_silence; p[r] = dsp_silence;
...@@ -1736,7 +1754,7 @@ dsp_cmx_send(void *arg) ...@@ -1736,7 +1754,7 @@ dsp_cmx_send(void *arg)
* remove delay only if we have delay AND we * remove delay only if we have delay AND we
* have enabled tx_dejitter * have enabled tx_dejitter
*/ */
if (delay && dsp->tx_dejitter) { if (delay > dsp_poll && dsp->tx_dejitter) {
if (dsp_debug & DEBUG_DSP_CMX) if (dsp_debug & DEBUG_DSP_CMX)
printk(KERN_DEBUG printk(KERN_DEBUG
"%s lowest tx_delay of %d bytes for" "%s lowest tx_delay of %d bytes for"
...@@ -1744,7 +1762,8 @@ dsp_cmx_send(void *arg) ...@@ -1744,7 +1762,8 @@ dsp_cmx_send(void *arg)
__func__, delay, __func__, delay,
dsp->name); dsp->name);
r = dsp->tx_R; r = dsp->tx_R;
rr = (r + delay) & CMX_BUFF_MASK; rr = (r + delay - (dsp_poll >> 1))
& CMX_BUFF_MASK;
/* delete tx-data */ /* delete tx-data */
while (r != rr) { while (r != rr) {
q[r] = dsp_silence; q[r] = dsp_silence;
...@@ -1797,14 +1816,13 @@ dsp_cmx_transmit(struct dsp *dsp, struct sk_buff *skb) ...@@ -1797,14 +1816,13 @@ dsp_cmx_transmit(struct dsp *dsp, struct sk_buff *skb)
ww = dsp->tx_R; ww = dsp->tx_R;
p = dsp->tx_buff; p = dsp->tx_buff;
d = skb->data; d = skb->data;
space = ww-w; space = (ww - w - 1) & CMX_BUFF_MASK;
if (space <= 0)
space += CMX_BUFF_SIZE;
/* write-pointer should not overrun nor reach read pointer */ /* write-pointer should not overrun nor reach read pointer */
if (space-1 < skb->len) if (space < skb->len) {
/* write to the space we have left */ /* write to the space we have left */
ww = (ww - 1) & CMX_BUFF_MASK; ww = (ww - 1) & CMX_BUFF_MASK; /* end one byte prior tx_R */
else printk(KERN_DEBUG "%s: buffer overflow\n", __func__);
} else
/* write until all byte are copied */ /* write until all byte are copied */
ww = (w + skb->len) & CMX_BUFF_MASK; ww = (w + skb->len) & CMX_BUFF_MASK;
dsp->tx_W = ww; dsp->tx_W = ww;
......
...@@ -191,6 +191,8 @@ dsp_rx_off_member(struct dsp *dsp) ...@@ -191,6 +191,8 @@ dsp_rx_off_member(struct dsp *dsp)
struct mISDN_ctrl_req cq; struct mISDN_ctrl_req cq;
int rx_off = 1; int rx_off = 1;
memset(&cq, 0, sizeof(cq));
if (!dsp->features_rx_off) if (!dsp->features_rx_off)
return; return;
...@@ -249,6 +251,32 @@ dsp_rx_off(struct dsp *dsp) ...@@ -249,6 +251,32 @@ dsp_rx_off(struct dsp *dsp)
} }
} }
/* enable "fill empty" feature */
static void
dsp_fill_empty(struct dsp *dsp)
{
struct mISDN_ctrl_req cq;
memset(&cq, 0, sizeof(cq));
if (!dsp->ch.peer) {
if (dsp_debug & DEBUG_DSP_CORE)
printk(KERN_DEBUG "%s: no peer, no fill_empty\n",
__func__);
return;
}
cq.op = MISDN_CTRL_FILL_EMPTY;
cq.p1 = 1;
if (dsp->ch.peer->ctrl(dsp->ch.peer, CONTROL_CHANNEL, &cq)) {
printk(KERN_DEBUG "%s: CONTROL_CHANNEL failed\n",
__func__);
return;
}
if (dsp_debug & DEBUG_DSP_CORE)
printk(KERN_DEBUG "%s: %s set fill_empty = 1\n",
__func__, dsp->name);
}
static int static int
dsp_control_req(struct dsp *dsp, struct mISDNhead *hh, struct sk_buff *skb) dsp_control_req(struct dsp *dsp, struct mISDNhead *hh, struct sk_buff *skb)
{ {
...@@ -593,8 +621,6 @@ get_features(struct mISDNchannel *ch) ...@@ -593,8 +621,6 @@ get_features(struct mISDNchannel *ch)
struct dsp *dsp = container_of(ch, struct dsp, ch); struct dsp *dsp = container_of(ch, struct dsp, ch);
struct mISDN_ctrl_req cq; struct mISDN_ctrl_req cq;
if (dsp_options & DSP_OPT_NOHARDWARE)
return;
if (!ch->peer) { if (!ch->peer) {
if (dsp_debug & DEBUG_DSP_CORE) if (dsp_debug & DEBUG_DSP_CORE)
printk(KERN_DEBUG "%s: no peer, no features\n", printk(KERN_DEBUG "%s: no peer, no features\n",
...@@ -610,6 +636,10 @@ get_features(struct mISDNchannel *ch) ...@@ -610,6 +636,10 @@ get_features(struct mISDNchannel *ch)
} }
if (cq.op & MISDN_CTRL_RX_OFF) if (cq.op & MISDN_CTRL_RX_OFF)
dsp->features_rx_off = 1; dsp->features_rx_off = 1;
if (cq.op & MISDN_CTRL_FILL_EMPTY)
dsp->features_fill_empty = 1;
if (dsp_options & DSP_OPT_NOHARDWARE)
return;
if ((cq.op & MISDN_CTRL_HW_FEATURES_OP)) { if ((cq.op & MISDN_CTRL_HW_FEATURES_OP)) {
cq.op = MISDN_CTRL_HW_FEATURES; cq.op = MISDN_CTRL_HW_FEATURES;
*((u_long *)&cq.p1) = (u_long)&dsp->features; *((u_long *)&cq.p1) = (u_long)&dsp->features;
...@@ -865,6 +895,9 @@ dsp_function(struct mISDNchannel *ch, struct sk_buff *skb) ...@@ -865,6 +895,9 @@ dsp_function(struct mISDNchannel *ch, struct sk_buff *skb)
if (dsp->dtmf.hardware || dsp->dtmf.software) if (dsp->dtmf.hardware || dsp->dtmf.software)
dsp_dtmf_goertzel_init(dsp); dsp_dtmf_goertzel_init(dsp);
get_features(ch); get_features(ch);
/* enable fill_empty feature */
if (dsp->features_fill_empty)
dsp_fill_empty(dsp);
/* send ph_activate */ /* send ph_activate */
hh->prim = PH_ACTIVATE_REQ; hh->prim = PH_ACTIVATE_REQ;
if (ch->peer) if (ch->peer)
......
...@@ -57,20 +57,21 @@ ...@@ -57,20 +57,21 @@
#define FLG_L2DATA 14 /* channel use L2 DATA primitivs */ #define FLG_L2DATA 14 /* channel use L2 DATA primitivs */
#define FLG_ORIGIN 15 /* channel is on origin site */ #define FLG_ORIGIN 15 /* channel is on origin site */
/* channel specific stuff */ /* channel specific stuff */
#define FLG_FILLEMPTY 16 /* fill fifo on first frame (empty) */
/* arcofi specific */ /* arcofi specific */
#define FLG_ARCOFI_TIMER 16 #define FLG_ARCOFI_TIMER 17
#define FLG_ARCOFI_ERROR 17 #define FLG_ARCOFI_ERROR 18
/* isar specific */ /* isar specific */
#define FLG_INITIALIZED 16 #define FLG_INITIALIZED 17
#define FLG_DLEETX 17 #define FLG_DLEETX 18
#define FLG_LASTDLE 18 #define FLG_LASTDLE 19
#define FLG_FIRST 19 #define FLG_FIRST 20
#define FLG_LASTDATA 20 #define FLG_LASTDATA 21
#define FLG_NMD_DATA 21 #define FLG_NMD_DATA 22
#define FLG_FTI_RUN 22 #define FLG_FTI_RUN 23
#define FLG_LL_OK 23 #define FLG_LL_OK 24
#define FLG_LL_CONN 24 #define FLG_LL_CONN 25
#define FLG_DTMFSEND 25 #define FLG_DTMFSEND 26
/* workq events */ /* workq events */
#define FLG_RECVQUEUE 30 #define FLG_RECVQUEUE 30
......
...@@ -312,6 +312,7 @@ clear_channelmap(u_int nr, u_char *map) ...@@ -312,6 +312,7 @@ clear_channelmap(u_int nr, u_char *map)
#define MISDN_CTRL_SETPEER 0x0040 #define MISDN_CTRL_SETPEER 0x0040
#define MISDN_CTRL_UNSETPEER 0x0080 #define MISDN_CTRL_UNSETPEER 0x0080
#define MISDN_CTRL_RX_OFF 0x0100 #define MISDN_CTRL_RX_OFF 0x0100
#define MISDN_CTRL_FILL_EMPTY 0x0200
#define MISDN_CTRL_HW_FEATURES_OP 0x2000 #define MISDN_CTRL_HW_FEATURES_OP 0x2000
#define MISDN_CTRL_HW_FEATURES 0x2001 #define MISDN_CTRL_HW_FEATURES 0x2001
#define MISDN_CTRL_HFC_OP 0x4000 #define MISDN_CTRL_HFC_OP 0x4000
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment