aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/isdn/mISDN
diff options
context:
space:
mode:
authorAndreas Eversberg <andreas@eversberg.eu>2008-08-02 16:51:52 -0400
committerKarsten Keil <kkeil@suse.de>2009-01-09 16:44:22 -0500
commit8dd2f36f317569665e454268a2677cfba3e848f1 (patch)
tree62f0d30aa090594648ed21cb9a863e4cc2b4f4fd /drivers/isdn/mISDN
parent69e656cc16511719a89d83373c48172d3f39bc5f (diff)
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')
-rw-r--r--drivers/isdn/mISDN/dsp.h1
-rw-r--r--drivers/isdn/mISDN/dsp_cmx.c56
-rw-r--r--drivers/isdn/mISDN/dsp_core.c37
3 files changed, 73 insertions, 21 deletions
diff --git a/drivers/isdn/mISDN/dsp.h b/drivers/isdn/mISDN/dsp.h
index 6c3fed6b8d4f..ded948069335 100644
--- a/drivers/isdn/mISDN/dsp.h
+++ b/drivers/isdn/mISDN/dsp.h
@@ -198,6 +198,7 @@ struct dsp {
198 /* hardware stuff */ 198 /* hardware stuff */
199 struct dsp_features features; 199 struct dsp_features features;
200 int features_rx_off; /* set if rx_off is featured */ 200 int features_rx_off; /* set if rx_off is featured */
201 int features_fill_empty; /* set if fill_empty is featured */
201 int pcm_slot_rx; /* current PCM slot (or -1) */ 202 int pcm_slot_rx; /* current PCM slot (or -1) */
202 int pcm_bank_rx; 203 int pcm_bank_rx;
203 int pcm_slot_tx; 204 int pcm_slot_tx;
diff --git a/drivers/isdn/mISDN/dsp_cmx.c b/drivers/isdn/mISDN/dsp_cmx.c
index c884511e2d49..fc8ea41ae6a2 100644
--- a/drivers/isdn/mISDN/dsp_cmx.c
+++ b/drivers/isdn/mISDN/dsp_cmx.c
@@ -1168,11 +1168,18 @@ dsp_cmx_receive(struct dsp *dsp, struct sk_buff *skb)
1168 dsp->rx_init = 0; 1168 dsp->rx_init = 0;
1169 if (dsp->features.unordered) { 1169 if (dsp->features.unordered) {
1170 dsp->rx_R = (hh->id & CMX_BUFF_MASK); 1170 dsp->rx_R = (hh->id & CMX_BUFF_MASK);
1171 dsp->rx_W = (dsp->rx_R + dsp->cmx_delay) 1171 if (dsp->cmx_delay)
1172 & CMX_BUFF_MASK; 1172 dsp->rx_W = (dsp->rx_R + dsp->cmx_delay)
1173 & CMX_BUFF_MASK;
1174 else
1175 dsp->rx_W = (dsp->rx_R + (dsp_poll >> 1))
1176 & CMX_BUFF_MASK;
1173 } else { 1177 } else {
1174 dsp->rx_R = 0; 1178 dsp->rx_R = 0;
1175 dsp->rx_W = dsp->cmx_delay; 1179 if (dsp->cmx_delay)
1180 dsp->rx_W = dsp->cmx_delay;
1181 else
1182 dsp->rx_W = dsp_poll >> 1;
1176 } 1183 }
1177 } 1184 }
1178 /* if frame contains time code, write directly */ 1185 /* if frame contains time code, write directly */
@@ -1190,14 +1197,20 @@ dsp_cmx_receive(struct dsp *dsp, struct sk_buff *skb)
1190 "cmx_receive(dsp=%lx): UNDERRUN (or overrun the " 1197 "cmx_receive(dsp=%lx): UNDERRUN (or overrun the "
1191 "maximum delay), adjusting read pointer! " 1198 "maximum delay), adjusting read pointer! "
1192 "(inst %s)\n", (u_long)dsp, dsp->name); 1199 "(inst %s)\n", (u_long)dsp, dsp->name);
1193 /* flush buffer */ 1200 /* flush rx buffer and set delay to dsp_poll / 2 */
1194 if (dsp->features.unordered) { 1201 if (dsp->features.unordered) {
1195 dsp->rx_R = (hh->id & CMX_BUFF_MASK); 1202 dsp->rx_R = (hh->id & CMX_BUFF_MASK);
1196 dsp->rx_W = (dsp->rx_R + dsp->cmx_delay) 1203 if (dsp->cmx_delay)
1197 & CMX_BUFF_MASK; 1204 dsp->rx_W = (dsp->rx_R + dsp->cmx_delay)
1205 & CMX_BUFF_MASK;
1206 dsp->rx_W = (dsp->rx_R + (dsp_poll >> 1))
1207 & CMX_BUFF_MASK;
1198 } else { 1208 } else {
1199 dsp->rx_R = 0; 1209 dsp->rx_R = 0;
1200 dsp->rx_W = dsp->cmx_delay; 1210 if (dsp->cmx_delay)
1211 dsp->rx_W = dsp->cmx_delay;
1212 else
1213 dsp->rx_W = dsp_poll >> 1;
1201 } 1214 }
1202 memset(dsp->rx_buff, dsp_silence, sizeof(dsp->rx_buff)); 1215 memset(dsp->rx_buff, dsp_silence, sizeof(dsp->rx_buff));
1203 } 1216 }
@@ -1360,8 +1373,11 @@ dsp_cmx_send_member(struct dsp *dsp, int len, s32 *c, int members)
1360 t = (t+1) & CMX_BUFF_MASK; 1373 t = (t+1) & CMX_BUFF_MASK;
1361 r = (r+1) & CMX_BUFF_MASK; 1374 r = (r+1) & CMX_BUFF_MASK;
1362 } 1375 }
1363 if (r != rr) 1376 if (r != rr) {
1377 printk(KERN_DEBUG "%s: buffer empty\n",
1378 __func__);
1364 memset(d, dsp_silence, (rr-r)&CMX_BUFF_MASK); 1379 memset(d, dsp_silence, (rr-r)&CMX_BUFF_MASK);
1380 }
1365 /* -> if echo is enabled */ 1381 /* -> if echo is enabled */
1366 } else { 1382 } else {
1367 /* 1383 /*
@@ -1704,9 +1720,10 @@ dsp_cmx_send(void *arg)
1704 } 1720 }
1705 /* 1721 /*
1706 * remove rx_delay only if we have delay AND we 1722 * remove rx_delay only if we have delay AND we
1707 * have not preset cmx_delay 1723 * have not preset cmx_delay AND
1724 * the delay is greater dsp_poll
1708 */ 1725 */
1709 if (delay && !dsp->cmx_delay) { 1726 if (delay > dsp_poll && !dsp->cmx_delay) {
1710 if (dsp_debug & DEBUG_DSP_CMX) 1727 if (dsp_debug & DEBUG_DSP_CMX)
1711 printk(KERN_DEBUG 1728 printk(KERN_DEBUG
1712 "%s lowest rx_delay of %d bytes for" 1729 "%s lowest rx_delay of %d bytes for"
@@ -1714,7 +1731,8 @@ dsp_cmx_send(void *arg)
1714 __func__, delay, 1731 __func__, delay,
1715 dsp->name); 1732 dsp->name);
1716 r = dsp->rx_R; 1733 r = dsp->rx_R;
1717 rr = (r + delay) & CMX_BUFF_MASK; 1734 rr = (r + delay - (dsp_poll >> 1))
1735 & CMX_BUFF_MASK;
1718 /* delete rx-data */ 1736 /* delete rx-data */
1719 while (r != rr) { 1737 while (r != rr) {
1720 p[r] = dsp_silence; 1738 p[r] = dsp_silence;
@@ -1736,7 +1754,7 @@ dsp_cmx_send(void *arg)
1736 * remove delay only if we have delay AND we 1754 * remove delay only if we have delay AND we
1737 * have enabled tx_dejitter 1755 * have enabled tx_dejitter
1738 */ 1756 */
1739 if (delay && dsp->tx_dejitter) { 1757 if (delay > dsp_poll && dsp->tx_dejitter) {
1740 if (dsp_debug & DEBUG_DSP_CMX) 1758 if (dsp_debug & DEBUG_DSP_CMX)
1741 printk(KERN_DEBUG 1759 printk(KERN_DEBUG
1742 "%s lowest tx_delay of %d bytes for" 1760 "%s lowest tx_delay of %d bytes for"
@@ -1744,7 +1762,8 @@ dsp_cmx_send(void *arg)
1744 __func__, delay, 1762 __func__, delay,
1745 dsp->name); 1763 dsp->name);
1746 r = dsp->tx_R; 1764 r = dsp->tx_R;
1747 rr = (r + delay) & CMX_BUFF_MASK; 1765 rr = (r + delay - (dsp_poll >> 1))
1766 & CMX_BUFF_MASK;
1748 /* delete tx-data */ 1767 /* delete tx-data */
1749 while (r != rr) { 1768 while (r != rr) {
1750 q[r] = dsp_silence; 1769 q[r] = dsp_silence;
@@ -1797,14 +1816,13 @@ dsp_cmx_transmit(struct dsp *dsp, struct sk_buff *skb)
1797 ww = dsp->tx_R; 1816 ww = dsp->tx_R;
1798 p = dsp->tx_buff; 1817 p = dsp->tx_buff;
1799 d = skb->data; 1818 d = skb->data;
1800 space = ww-w; 1819 space = (ww - w - 1) & CMX_BUFF_MASK;
1801 if (space <= 0)
1802 space += CMX_BUFF_SIZE;
1803 /* write-pointer should not overrun nor reach read pointer */ 1820 /* write-pointer should not overrun nor reach read pointer */
1804 if (space-1 < skb->len) 1821 if (space < skb->len) {
1805 /* write to the space we have left */ 1822 /* write to the space we have left */
1806 ww = (ww - 1) & CMX_BUFF_MASK; 1823 ww = (ww - 1) & CMX_BUFF_MASK; /* end one byte prior tx_R */
1807 else 1824 printk(KERN_DEBUG "%s: buffer overflow\n", __func__);
1825 } else
1808 /* write until all byte are copied */ 1826 /* write until all byte are copied */
1809 ww = (w + skb->len) & CMX_BUFF_MASK; 1827 ww = (w + skb->len) & CMX_BUFF_MASK;
1810 dsp->tx_W = ww; 1828 dsp->tx_W = ww;
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)
191 struct mISDN_ctrl_req cq; 191 struct mISDN_ctrl_req cq;
192 int rx_off = 1; 192 int rx_off = 1;
193 193
194 memset(&cq, 0, sizeof(cq));
195
194 if (!dsp->features_rx_off) 196 if (!dsp->features_rx_off)
195 return; 197 return;
196 198
@@ -249,6 +251,32 @@ dsp_rx_off(struct dsp *dsp)
249 } 251 }
250} 252}
251 253
254/* enable "fill empty" feature */
255static void
256dsp_fill_empty(struct dsp *dsp)
257{
258 struct mISDN_ctrl_req cq;
259
260 memset(&cq, 0, sizeof(cq));
261
262 if (!dsp->ch.peer) {
263 if (dsp_debug & DEBUG_DSP_CORE)
264 printk(KERN_DEBUG "%s: no peer, no fill_empty\n",
265 __func__);
266 return;
267 }
268 cq.op = MISDN_CTRL_FILL_EMPTY;
269 cq.p1 = 1;
270 if (dsp->ch.peer->ctrl(dsp->ch.peer, CONTROL_CHANNEL, &cq)) {
271 printk(KERN_DEBUG "%s: CONTROL_CHANNEL failed\n",
272 __func__);
273 return;
274 }
275 if (dsp_debug & DEBUG_DSP_CORE)
276 printk(KERN_DEBUG "%s: %s set fill_empty = 1\n",
277 __func__, dsp->name);
278}
279
252static int 280static int
253dsp_control_req(struct dsp *dsp, struct mISDNhead *hh, struct sk_buff *skb) 281dsp_control_req(struct dsp *dsp, struct mISDNhead *hh, struct sk_buff *skb)
254{ 282{
@@ -593,8 +621,6 @@ get_features(struct mISDNchannel *ch)
593 struct dsp *dsp = container_of(ch, struct dsp, ch); 621 struct dsp *dsp = container_of(ch, struct dsp, ch);
594 struct mISDN_ctrl_req cq; 622 struct mISDN_ctrl_req cq;
595 623
596 if (dsp_options & DSP_OPT_NOHARDWARE)
597 return;
598 if (!ch->peer) { 624 if (!ch->peer) {
599 if (dsp_debug & DEBUG_DSP_CORE) 625 if (dsp_debug & DEBUG_DSP_CORE)
600 printk(KERN_DEBUG "%s: no peer, no features\n", 626 printk(KERN_DEBUG "%s: no peer, no features\n",
@@ -610,6 +636,10 @@ get_features(struct mISDNchannel *ch)
610 } 636 }
611 if (cq.op & MISDN_CTRL_RX_OFF) 637 if (cq.op & MISDN_CTRL_RX_OFF)
612 dsp->features_rx_off = 1; 638 dsp->features_rx_off = 1;
639 if (cq.op & MISDN_CTRL_FILL_EMPTY)
640 dsp->features_fill_empty = 1;
641 if (dsp_options & DSP_OPT_NOHARDWARE)
642 return;
613 if ((cq.op & MISDN_CTRL_HW_FEATURES_OP)) { 643 if ((cq.op & MISDN_CTRL_HW_FEATURES_OP)) {
614 cq.op = MISDN_CTRL_HW_FEATURES; 644 cq.op = MISDN_CTRL_HW_FEATURES;
615 *((u_long *)&cq.p1) = (u_long)&dsp->features; 645 *((u_long *)&cq.p1) = (u_long)&dsp->features;
@@ -865,6 +895,9 @@ dsp_function(struct mISDNchannel *ch, struct sk_buff *skb)
865 if (dsp->dtmf.hardware || dsp->dtmf.software) 895 if (dsp->dtmf.hardware || dsp->dtmf.software)
866 dsp_dtmf_goertzel_init(dsp); 896 dsp_dtmf_goertzel_init(dsp);
867 get_features(ch); 897 get_features(ch);
898 /* enable fill_empty feature */
899 if (dsp->features_fill_empty)
900 dsp_fill_empty(dsp);
868 /* send ph_activate */ 901 /* send ph_activate */
869 hh->prim = PH_ACTIVATE_REQ; 902 hh->prim = PH_ACTIVATE_REQ;
870 if (ch->peer) 903 if (ch->peer)