summaryrefslogtreecommitdiff
path: root/drivers/isdn/mISDN/dsp_core.c
diff options
context:
space:
mode:
authorAndreas Eversberg <andreas@eversberg.eu>2008-08-02 22:51:52 +0200
committerKarsten Keil <kkeil@suse.de>2009-01-09 22:44:22 +0100
commit8dd2f36f317569665e454268a2677cfba3e848f1 (patch)
tree62f0d30aa090594648ed21cb9a863e4cc2b4f4fd /drivers/isdn/mISDN/dsp_core.c
parent69e656cc16511719a89d83373c48172d3f39bc5f (diff)
downloadlwn-8dd2f36f317569665e454268a2677cfba3e848f1.tar.gz
lwn-8dd2f36f317569665e454268a2677cfba3e848f1.zip
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: Andreas Eversberg <andreas@eversberg.eu> Signed-off-by: Karsten Keil <kkeil@suse.de>
Diffstat (limited to 'drivers/isdn/mISDN/dsp_core.c')
-rw-r--r--drivers/isdn/mISDN/dsp_core.c37
1 files changed, 35 insertions, 2 deletions
diff --git a/drivers/isdn/mISDN/dsp_core.c b/drivers/isdn/mISDN/dsp_core.c
index 1dc21d803410..1d504ba954f5 100644
--- a/drivers/isdn/mISDN/dsp_core.c
+++ b/drivers/isdn/mISDN/dsp_core.c
@@ -191,6 +191,8 @@ dsp_rx_off_member(struct dsp *dsp)
struct mISDN_ctrl_req cq;
int rx_off = 1;
+ memset(&cq, 0, sizeof(cq));
+
if (!dsp->features_rx_off)
return;
@@ -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
dsp_control_req(struct dsp *dsp, struct mISDNhead *hh, struct sk_buff *skb)
{
@@ -593,8 +621,6 @@ get_features(struct mISDNchannel *ch)
struct dsp *dsp = container_of(ch, struct dsp, ch);
struct mISDN_ctrl_req cq;
- if (dsp_options & DSP_OPT_NOHARDWARE)
- return;
if (!ch->peer) {
if (dsp_debug & DEBUG_DSP_CORE)
printk(KERN_DEBUG "%s: no peer, no features\n",
@@ -610,6 +636,10 @@ get_features(struct mISDNchannel *ch)
}
if (cq.op & MISDN_CTRL_RX_OFF)
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)) {
cq.op = MISDN_CTRL_HW_FEATURES;
*((u_long *)&cq.p1) = (u_long)&dsp->features;
@@ -865,6 +895,9 @@ dsp_function(struct mISDNchannel *ch, struct sk_buff *skb)
if (dsp->dtmf.hardware || dsp->dtmf.software)
dsp_dtmf_goertzel_init(dsp);
get_features(ch);
+ /* enable fill_empty feature */
+ if (dsp->features_fill_empty)
+ dsp_fill_empty(dsp);
/* send ph_activate */
hh->prim = PH_ACTIVATE_REQ;
if (ch->peer)