]> www.pilppa.org Git - linux-2.6-omap-h63xx.git/blobdiff - drivers/isdn/mISDN/dsp_cmx.c
mISDN: Add ISDN sample clock API to mISDN core
[linux-2.6-omap-h63xx.git] / drivers / isdn / mISDN / dsp_cmx.c
index c884511e2d49038a465ab9e550a8e04739463de0..efe4c7430e6d8ea016436cba348f17e309cb0e21 100644 (file)
@@ -744,11 +744,11 @@ conf_software:
                                        if (dsp->pcm_slot_rx >= 0 &&
                                            dsp->pcm_slot_rx <
                                            sizeof(freeslots))
-                                               freeslots[dsp->pcm_slot_tx] = 0;
+                                               freeslots[dsp->pcm_slot_rx] = 0;
                                        if (dsp->pcm_slot_tx >= 0 &&
                                            dsp->pcm_slot_tx <
                                            sizeof(freeslots))
-                                               freeslots[dsp->pcm_slot_rx] = 0;
+                                               freeslots[dsp->pcm_slot_tx] = 0;
                                }
                        }
                        i = 0;
@@ -836,11 +836,11 @@ conf_software:
                                        if (dsp->pcm_slot_rx >= 0 &&
                                            dsp->pcm_slot_rx <
                                            sizeof(freeslots))
-                                               freeslots[dsp->pcm_slot_tx] = 0;
+                                               freeslots[dsp->pcm_slot_rx] = 0;
                                        if (dsp->pcm_slot_tx >= 0 &&
                                            dsp->pcm_slot_tx <
                                            sizeof(freeslots))
-                                               freeslots[dsp->pcm_slot_rx] = 0;
+                                               freeslots[dsp->pcm_slot_tx] = 0;
                                }
                        }
                        i1 = 0;
@@ -1168,11 +1168,18 @@ dsp_cmx_receive(struct dsp *dsp, struct sk_buff *skb)
                dsp->rx_init = 0;
                if (dsp->features.unordered) {
                        dsp->rx_R = (hh->id & CMX_BUFF_MASK);
-                       dsp->rx_W = (dsp->rx_R + dsp->cmx_delay)
-                               & CMX_BUFF_MASK;
+                       if (dsp->cmx_delay)
+                               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 {
                        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 */
@@ -1185,19 +1192,25 @@ dsp_cmx_receive(struct dsp *dsp, struct sk_buff *skb)
         * we set our new read pointer, and write silence to buffer
         */
        if (((dsp->rx_W-dsp->rx_R) & CMX_BUFF_MASK) >= CMX_BUFF_HALF) {
-               if (dsp_debug & DEBUG_DSP_CMX)
+               if (dsp_debug & DEBUG_DSP_CLOCK)
                        printk(KERN_DEBUG
                            "cmx_receive(dsp=%lx): UNDERRUN (or overrun the "
                            "maximum delay), adjusting read pointer! "
                            "(inst %s)\n", (u_long)dsp, dsp->name);
-               /* flush buffer */
+               /* flush rx buffer and set delay to dsp_poll / 2 */
                if (dsp->features.unordered) {
                        dsp->rx_R = (hh->id & CMX_BUFF_MASK);
-                       dsp->rx_W = (dsp->rx_R + dsp->cmx_delay)
-                               & CMX_BUFF_MASK;
+                       if (dsp->cmx_delay)
+                               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 {
                        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));
        }
@@ -1205,7 +1218,7 @@ dsp_cmx_receive(struct dsp *dsp, struct sk_buff *skb)
        if (dsp->cmx_delay)
                if (((dsp->rx_W - dsp->rx_R) & CMX_BUFF_MASK) >=
                    (dsp->cmx_delay << 1)) {
-                       if (dsp_debug & DEBUG_DSP_CMX)
+                       if (dsp_debug & DEBUG_DSP_CLOCK)
                                printk(KERN_DEBUG
                                    "cmx_receive(dsp=%lx): OVERRUN (because "
                                    "twice the delay is reached), adjusting "
@@ -1360,8 +1373,12 @@ dsp_cmx_send_member(struct dsp *dsp, int len, s32 *c, int members)
                                t = (t+1) & CMX_BUFF_MASK;
                                r = (r+1) & CMX_BUFF_MASK;
                        }
-                       if (r != rr)
+                       if (r != rr) {
+                               if (dsp_debug & DEBUG_DSP_CLOCK)
+                                       printk(KERN_DEBUG "%s: RX empty\n",
+                                               __func__);
                                memset(d, dsp_silence, (rr-r)&CMX_BUFF_MASK);
+                       }
                /* -> if echo is enabled */
                } else {
                        /*
@@ -1540,13 +1557,11 @@ send_packet:
        schedule_work(&dsp->workq);
 }
 
-static u32     samplecount;
+static u32     jittercount; /* counter for jitter check */;
 struct timer_list dsp_spl_tl;
 u32    dsp_spl_jiffies; /* calculate the next time to fire */
-#ifdef UNUSED
-static u32     dsp_start_jiffies; /* jiffies at the time, the calculation begins */
-#endif /* UNUSED */
-static struct timeval dsp_start_tv; /* time at start of calculation */
+static u16     dsp_count; /* last sample count */
+static int     dsp_count_valid ; /* if we have last sample count */
 
 void
 dsp_cmx_send(void *arg)
@@ -1560,38 +1575,32 @@ dsp_cmx_send(void *arg)
        int r, rr;
        int jittercheck = 0, delay, i;
        u_long flags;
-       struct timeval tv;
-       u32 elapsed;
-       s16 length;
+       u16 length, count;
 
        /* lock */
        spin_lock_irqsave(&dsp_lock, flags);
 
-       if (!dsp_start_tv.tv_sec) {
-               do_gettimeofday(&dsp_start_tv);
+       if (!dsp_count_valid) {
+               dsp_count = mISDN_clock_get();
                length = dsp_poll;
+               dsp_count_valid = 1;
        } else {
-               do_gettimeofday(&tv);
-               elapsed = ((tv.tv_sec - dsp_start_tv.tv_sec) * 8000)
-                   + ((s32)(tv.tv_usec / 125) - (dsp_start_tv.tv_usec / 125));
-               dsp_start_tv.tv_sec = tv.tv_sec;
-               dsp_start_tv.tv_usec = tv.tv_usec;
-               length = elapsed;
+               count = mISDN_clock_get();
+               length = count - dsp_count;
+               dsp_count = count;
        }
        if (length > MAX_POLL + 100)
                length = MAX_POLL + 100;
-/* printk(KERN_DEBUG "len=%d dsp_count=0x%x.%04x dsp_poll_diff=0x%x.%04x\n",
- length, dsp_count >> 16, dsp_count & 0xffff, dsp_poll_diff >> 16,
- dsp_poll_diff & 0xffff);
- */
+       /* printk(KERN_DEBUG "len=%d dsp_count=0x%x\n", length, dsp_count); */
 
        /*
-        * check if jitter needs to be checked
-        * (this is about every second = 8192 samples)
+        * check if jitter needs to be checked (this is every second)
         */
-       samplecount += length;
-       if ((samplecount & 8191) < length)
+       jittercount += length;
+       if (jittercount >= 8000) {
+               jittercount -= 8000;
                jittercheck = 1;
+       }
 
        /* loop all members that do not require conference mixing */
        list_for_each_entry(dsp, &dsp_ilist, list) {
@@ -1704,17 +1713,19 @@ dsp_cmx_send(void *arg)
                        }
                        /*
                         * 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 (dsp_debug & DEBUG_DSP_CMX)
+                       if (delay > dsp_poll && !dsp->cmx_delay) {
+                               if (dsp_debug & DEBUG_DSP_CLOCK)
                                        printk(KERN_DEBUG
                                            "%s lowest rx_delay of %d bytes for"
                                            " dsp %s are now removed.\n",
                                            __func__, delay,
                                            dsp->name);
                                r = dsp->rx_R;
-                               rr = (r + delay) & CMX_BUFF_MASK;
+                               rr = (r + delay - (dsp_poll >> 1))
+                                       & CMX_BUFF_MASK;
                                /* delete rx-data */
                                while (r != rr) {
                                        p[r] = dsp_silence;
@@ -1736,15 +1747,16 @@ dsp_cmx_send(void *arg)
                         * remove delay only if we have delay AND we
                         * have enabled tx_dejitter
                         */
-                       if (delay && dsp->tx_dejitter) {
-                               if (dsp_debug & DEBUG_DSP_CMX)
+                       if (delay > dsp_poll && dsp->tx_dejitter) {
+                               if (dsp_debug & DEBUG_DSP_CLOCK)
                                        printk(KERN_DEBUG
                                            "%s lowest tx_delay of %d bytes for"
                                            " dsp %s are now removed.\n",
                                            __func__, delay,
                                            dsp->name);
                                r = dsp->tx_R;
-                               rr = (r + delay) & CMX_BUFF_MASK;
+                               rr = (r + delay - (dsp_poll >> 1))
+                                       & CMX_BUFF_MASK;
                                /* delete tx-data */
                                while (r != rr) {
                                        q[r] = dsp_silence;
@@ -1797,14 +1809,16 @@ dsp_cmx_transmit(struct dsp *dsp, struct sk_buff *skb)
        ww = dsp->tx_R;
        p = dsp->tx_buff;
        d = skb->data;
-       space = ww-w;
-       if (space <= 0)
-               space += CMX_BUFF_SIZE;
+       space = (ww - w - 1) & CMX_BUFF_MASK;
        /* 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 */
-               ww = (ww - 1) & CMX_BUFF_MASK;
-       else
+               ww = (ww - 1) & CMX_BUFF_MASK; /* end one byte prior tx_R */
+               if (dsp_debug & DEBUG_DSP_CLOCK)
+                       printk(KERN_DEBUG "%s: TX overflow space=%d skb->len="
+                           "%d, w=0x%04x, ww=0x%04x\n", __func__, space,
+                           skb->len, w, ww);
+       } else
                /* write until all byte are copied */
                ww = (w + skb->len) & CMX_BUFF_MASK;
        dsp->tx_W = ww;