[zaptel-commits] mattf: branch 1.4 r2762 - in /branches/1.4: ./ wctdm24xxp/
SVN commits to the Zaptel project
zaptel-commits at lists.digium.com
Fri Jul 20 13:54:21 CDT 2007
Author: mattf
Date: Fri Jul 20 13:54:20 2007
New Revision: 2762
URL: http://svn.digium.com/view/zaptel?view=rev&rev=2762
Log:
Merged revisions 2761 via svnmerge from
https://origsvn.digium.com/svn/zaptel/branches/1.2
........
r2761 | mattf | 2007-07-20 11:19:47 -0500 (Fri, 20 Jul 2007) | 1 line
New product support, new echo canceler and new boards
........
Added:
branches/1.4/wctdm24xxp/
- copied from r2761, branches/1.2/wctdm24xxp/
branches/1.4/wctdm24xxp/GpakApi.c
- copied unchanged from r2761, branches/1.2/wctdm24xxp/GpakApi.c
branches/1.4/wctdm24xxp/GpakApi.h
- copied unchanged from r2761, branches/1.2/wctdm24xxp/GpakApi.h
branches/1.4/wctdm24xxp/GpakCust.c
- copied unchanged from r2761, branches/1.2/wctdm24xxp/GpakCust.c
branches/1.4/wctdm24xxp/GpakCust.h
- copied unchanged from r2761, branches/1.2/wctdm24xxp/GpakCust.h
branches/1.4/wctdm24xxp/GpakHpi.h
- copied unchanged from r2761, branches/1.2/wctdm24xxp/GpakHpi.h
branches/1.4/wctdm24xxp/Makefile
- copied unchanged from r2761, branches/1.2/wctdm24xxp/Makefile
branches/1.4/wctdm24xxp/Makefile.kernel26
- copied unchanged from r2761, branches/1.2/wctdm24xxp/Makefile.kernel26
branches/1.4/wctdm24xxp/base.c
- copied, changed from r2761, branches/1.2/wctdm24xxp/base.c
branches/1.4/wctdm24xxp/gpakErrs.h
- copied unchanged from r2761, branches/1.2/wctdm24xxp/gpakErrs.h
branches/1.4/wctdm24xxp/gpakenum.h
- copied unchanged from r2761, branches/1.2/wctdm24xxp/gpakenum.h
branches/1.4/wctdm24xxp/wctdm24xxp.h
- copied, changed from r2761, branches/1.2/wctdm24xxp/wctdm24xxp.h
Removed:
branches/1.4/wctdm24xxp.c
Modified:
branches/1.4/ (props changed)
branches/1.4/Makefile
branches/1.4/zaptel-base.c
Propchange: branches/1.4/
------------------------------------------------------------------------------
Binary property 'branch-1.2-merged' - no diff available.
Modified: branches/1.4/Makefile
URL: http://svn.digium.com/view/zaptel/branches/1.4/Makefile?view=diff&rev=2762&r1=2761&r2=2762
==============================================================================
--- branches/1.4/Makefile (original)
+++ branches/1.4/Makefile Fri Jul 20 13:54:20 2007
@@ -98,8 +98,8 @@
BUILD_XPP:=yes
endif
-TOPDIR_MODULES:=pciradio tor2 torisa wcfxo wct1xxp wctdm wctdm24xxp wcte11xp wcusb zaptel ztd-eth ztd-loc ztdummy ztdynamic zttranscode wcte12xp
-SUBDIR_MODULES:=wct4xxp wctc4xxp xpp
+TOPDIR_MODULES:=pciradio tor2 torisa wcfxo wct1xxp wctdm wcte11xp wcusb zaptel ztd-eth ztd-loc ztdummy ztdynamic zttranscode wcte12xp
+SUBDIR_MODULES:=wct4xxp wctc4xxp xpp wctdm24xxp
BUILD_TOPDIR_MODULES:=$(filter-out $(MENUSELECT_MODULES),$(TOPDIR_MODULES))
BUILD_SUBDIR_MODULES:=$(filter-out $(MENUSELECT_MODULES),$(SUBDIR_MODULES))
BUILD_MODULES:=$(BUILD_TOPDIR_MODULES) $(BUILD_SUBDIR_MODULES)
Copied: branches/1.4/wctdm24xxp/base.c (from r2761, branches/1.2/wctdm24xxp/base.c)
URL: http://svn.digium.com/view/zaptel/branches/1.4/wctdm24xxp/base.c?view=diff&rev=2762&p1=branches/1.2/wctdm24xxp/base.c&r1=2761&p2=branches/1.4/wctdm24xxp/base.c&r2=2762
==============================================================================
--- branches/1.2/wctdm24xxp/base.c (original)
+++ branches/1.4/wctdm24xxp/base.c Fri Jul 20 13:54:20 2007
@@ -4,8 +4,11 @@
* Written by Mark Spencer <markster at digium.com>
* Support for TDM800P and VPM150M by Matthew Fredrickson <creslin at digium.com>
*
- * Copyright (C) 2005, 2006, Digium, Inc.
+ * Copyright (C) 2005,2006, Digium, Inc.
+ * All rights reserved.
*
+ * Sections for QRV cards written by Jim Dixon <jim at lambdatel.com>
+ * Copyright (C) 2006, Jim Dixon and QRV Communications
* All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
@@ -23,6 +26,13 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
*/
+/* For QRV DRI cards, gain is signed short, expressed in hundredths of
+db (in reference to 1v Peak @ 1000Hz) , as follows:
+
+Rx Gain: -11.99 to 15.52 db
+Tx Gain - No Pre-Emphasis: -35.99 to 12.00 db
+Tx Gain - W/Pre-Emphasis: -23.99 to 0.00 db
+*/
#include <linux/version.h>
#include <linux/kernel.h>
@@ -225,7 +235,7 @@
#ifdef STANDALONE_ZAPATA
#include "zaptel.h"
#else
-#include <linux/zaptel.h>
+#include <zaptel/zaptel.h>
#endif
#ifdef LINUX26
@@ -266,6 +276,11 @@
static int fxshonormode = 0;
static int alawoverride = 0;
static int fxo_addrs[4] = { 0x00, 0x08, 0x04, 0x0c };
+static int fxotxgain = 0;
+static int fxorxgain = 0;
+static int fxstxgain = 0;
+static int fxsrxgain = 0;
+static int nativebridge = 1;
#ifdef VPM_SUPPORT
static int vpmsupport = 1;
static int vpmdtmfsupport = 0;
@@ -470,8 +485,14 @@
ecval = ecval % EC_SIZE;
#endif
+ /* if a QRV card, map it to its first channel */
+ if ((wc->modtype[card] == MOD_TYPE_QRV) && (card & 3))
+ {
+ return;
+ }
if (wc->altcs[card])
subaddr = 0;
+
/* Skip audio */
@@ -497,6 +518,8 @@
curcmd = CMD_RD(64);
else if (wc->modtype[card] == MOD_TYPE_FXO)
curcmd = CMD_RD(12);
+ else if (wc->modtype[card] == MOD_TYPE_QRV)
+ curcmd = CMD_RD(3);
else if (wc->modtype[card] == MOD_TYPE_VPM) {
#ifdef FANCY_ECHOCAN
if (wc->blinktimer >= 0xf) {
@@ -543,6 +566,22 @@
writechunk[CMD_BYTE(card, 2, wc->altcs[card])] = curcmd & 0xff;
} else if (wc->modtype[card] == MOD_TYPE_VPM150M) {
#endif
+ } else if (wc->modtype[card] == MOD_TYPE_QRV) {
+
+ writechunk[CMD_BYTE(card, 0, wc->altcs[card])] = 0x00;
+ if (!curcmd)
+ {
+ writechunk[CMD_BYTE(card, 1, wc->altcs[card])] = 0x00;
+ writechunk[CMD_BYTE(card, 2, wc->altcs[card])] = 0x00;
+ }
+ else
+ {
+ if (curcmd & __CMD_WR)
+ writechunk[CMD_BYTE(card, 1, wc->altcs[card])] = 0x40 | ((curcmd >> 8) & 0x3f);
+ else
+ writechunk[CMD_BYTE(card, 1, wc->altcs[card])] = 0xc0 | ((curcmd >> 8) & 0x3f);
+ writechunk[CMD_BYTE(card, 2, wc->altcs[card])] = curcmd & 0xff;
+ }
} else if (wc->modtype[card] == MOD_TYPE_NONE) {
writechunk[CMD_BYTE(card, 0, wc->altcs[card])] = 0x00;
writechunk[CMD_BYTE(card, 1, wc->altcs[card])] = 0x00;
@@ -601,6 +640,11 @@
unsigned char ident;
int x;
+ /* if a QRV card, map it to its first channel */
+ if ((wc->modtype[card] == MOD_TYPE_QRV) && (card & 3))
+ {
+ return;
+ }
/* Skip audio */
readchunk += 24;
spin_lock_irqsave(&wc->reglock, flags);
@@ -644,6 +688,8 @@
wc->cmdq[card].cmds[USER_COMMANDS + 0] = CMD_RD(68); /* Hook state */
} else if (wc->modtype[card] == MOD_TYPE_FXO) {
wc->cmdq[card].cmds[USER_COMMANDS + 0] = CMD_RD(5); /* Hook/Ring state */
+ } else if (wc->modtype[card] == MOD_TYPE_QRV) {
+ wc->cmdq[card & 0xfc].cmds[USER_COMMANDS + 0] = CMD_RD(3); /* COR/CTCSS state */
#ifdef VPM_SUPPORT
} else if (wc->modtype[card] == MOD_TYPE_VPM) {
wc->cmdq[card].cmds[USER_COMMANDS + 0] = CMD_RD(0xb9); /* DTMF interrupt */
@@ -659,6 +705,8 @@
#endif
} else if (wc->modtype[card] == MOD_TYPE_FXO) {
wc->cmdq[card].cmds[USER_COMMANDS + 1] = CMD_RD(29); /* Battery */
+ } else if (wc->modtype[card] == MOD_TYPE_QRV) {
+ wc->cmdq[card & 0xfc].cmds[USER_COMMANDS + 1] = CMD_RD(3); /* Battery */
#ifdef VPM_SUPPORT
} else if (wc->modtype[card] == MOD_TYPE_VPM) {
wc->cmdq[card].cmds[USER_COMMANDS + 1] = CMD_RD(0xbd); /* DTMF interrupt */
@@ -742,6 +790,12 @@
unsigned long flags;
int hit=0;
int ret;
+
+ /* if a QRV card, use only its first channel */
+ if (wc->modtype[card] == MOD_TYPE_QRV)
+ {
+ if (card & 3) return(0);
+ }
do {
spin_lock_irqsave(&wc->reglock, flags);
hit = empty_slot(wc, card);
@@ -773,6 +827,12 @@
unsigned long flags;
int hit;
int ret=0;
+
+ /* if a QRV card, use only its first channel */
+ if (wc->modtype[card] == MOD_TYPE_QRV)
+ {
+ if (card & 3) return(0);
+ }
do {
spin_lock_irqsave(&wc->reglock, flags);
hit = empty_slot(wc, card);
@@ -1162,6 +1222,60 @@
}
}
#endif
+}
+
+static inline void wctdm_qrvdri_check_hook(struct wctdm *wc, int card)
+{
+ signed char b,b1;
+ int qrvcard = card & 0xfc;
+
+
+ if (wc->qrvdebtime[card] >= 2) wc->qrvdebtime[card]--;
+ b = wc->cmdq[qrvcard].isrshadow[0]; /* Hook/Ring state */
+ b &= 0xcc; /* use bits 3-4 and 6-7 only */
+
+ if (wc->radmode[qrvcard] & RADMODE_IGNORECOR) b &= ~4;
+ else if (!(wc->radmode[qrvcard] & RADMODE_INVERTCOR)) b ^= 4;
+ if (wc->radmode[qrvcard + 1] | RADMODE_IGNORECOR) b &= ~0x40;
+ else if (!(wc->radmode[qrvcard + 1] | RADMODE_INVERTCOR)) b ^= 0x40;
+
+ if ((wc->radmode[qrvcard] & RADMODE_IGNORECT) ||
+ (!(wc->radmode[qrvcard] & RADMODE_EXTTONE))) b &= ~8;
+ else if (!(wc->radmode[qrvcard] & RADMODE_EXTINVERT)) b ^= 8;
+ if ((wc->radmode[qrvcard + 1] & RADMODE_IGNORECT) ||
+ (!(wc->radmode[qrvcard + 1] & RADMODE_EXTTONE))) b &= ~0x80;
+ else if (!(wc->radmode[qrvcard + 1] & RADMODE_EXTINVERT)) b ^= 0x80;
+ /* now b & MASK should be zero, if its active */
+ /* check for change in chan 0 */
+ if ((!(b & 0xc)) != wc->qrvhook[qrvcard + 2])
+ {
+ wc->qrvdebtime[qrvcard] = wc->debouncetime[qrvcard];
+ wc->qrvhook[qrvcard + 2] = !(b & 0xc);
+ }
+ /* if timed-out and ready */
+ if (wc->qrvdebtime[qrvcard] == 1)
+ {
+ b1 = wc->qrvhook[qrvcard + 2];
+if (debug) printk("QRV channel %d rx state changed to %d\n",qrvcard,wc->qrvhook[qrvcard + 2]);
+ zt_hooksig(&wc->chans[qrvcard],
+ (b1) ? ZT_RXSIG_OFFHOOK : ZT_RXSIG_ONHOOK);
+ wc->qrvdebtime[card] = 0;
+ }
+ /* check for change in chan 1 */
+ if ((!(b & 0xc0)) != wc->qrvhook[qrvcard + 3])
+ {
+ wc->qrvdebtime[qrvcard + 1] = QRV_DEBOUNCETIME;
+ wc->qrvhook[qrvcard + 3] = !(b & 0xc0);
+ }
+ if (wc->qrvdebtime[qrvcard + 1] == 1)
+ {
+ b1 = wc->qrvhook[qrvcard + 3];
+if (debug) printk("QRV channel %d rx state changed to %d\n",qrvcard + 1,wc->qrvhook[qrvcard + 3]);
+ zt_hooksig(&wc->chans[qrvcard + 1],
+ (b1) ? ZT_RXSIG_OFFHOOK : ZT_RXSIG_ONHOOK);
+ wc->qrvdebtime[card] = 0;
+ }
+ return;
}
static inline void wctdm_voicedaa_check_hook(struct wctdm *wc, int card)
@@ -1408,6 +1522,7 @@
static inline void wctdm_isr_misc(struct wctdm *wc)
{
int x;
+
for (x=0;x<wc->cards;x++) {
if (wc->cardflag & (1 << x)) {
if (wc->modtype[x] == MOD_TYPE_FXS) {
@@ -1439,6 +1554,8 @@
}
} else if (wc->modtype[x] == MOD_TYPE_FXO) {
wctdm_voicedaa_check_hook(wc, x);
+ } else if (wc->modtype[x] == MOD_TYPE_QRV) {
+ wctdm_qrvdri_check_hook(wc, x);
}
}
}
@@ -1846,6 +1963,8 @@
unsigned char reg16=0, reg26=0, reg30=0, reg31=0;
long newjiffies;
+ if (wc->modtype[card & 0xfc] == MOD_TYPE_QRV) return -2;
+
wc->modtype[card] = MOD_TYPE_NONE;
/* Wait just a bit */
wait_just_a_bit(HZ/10);
@@ -1923,6 +2042,40 @@
/* Apply negative Rx gain of 4.5db to DAA */
wctdm_setreg(wc, card, 39, 0x14); /* 4db */
wctdm_setreg(wc, card, 41, 0x15); /* 0.5db */
+
+
+ /* Take values for fxotxgain and fxorxgain and apply them to module */
+ if (fxotxgain) {
+ if (fxotxgain >= -150 && fxotxgain < 0) {
+ wctdm_setreg(wc, card, 38, 16 + (fxotxgain/-10));
+ if(fxotxgain % 10) {
+ wctdm_setreg(wc, card, 40, 16 + (-fxotxgain%10));
+ }
+ }
+ else if (fxotxgain <= 120 && fxotxgain > 0) {
+ wctdm_setreg(wc, card, 38, fxotxgain/10);
+ if(fxotxgain % 10) {
+ wctdm_setreg(wc, card, 40, (fxotxgain%10));
+ }
+ }
+ }
+ if (fxorxgain) {
+ if (fxorxgain >= -150 && fxorxgain < 0) {
+ wctdm_setreg(wc, card, 39, 16+ (fxorxgain/-10));
+ if(fxotxgain % 10) {
+ wctdm_setreg(wc, card, 41, 16 + (-fxorxgain%10));
+ }
+ }
+ else if (fxorxgain <= 120 && fxorxgain > 0) {
+ wctdm_setreg(wc, card, 39, fxorxgain/10);
+ if(fxorxgain % 10) {
+ wctdm_setreg(wc, card, 41, (fxorxgain%10));
+ }
+ }
+ }
+
+ if(debug)
+ printk("DEBUG fxotxgain:%i.%i fxorxgain:%i.%i\n", (wctdm_getreg(wc, card, 38)/16) ? -(wctdm_getreg(wc, card, 38) - 16) : wctdm_getreg(wc, card, 38), (wctdm_getreg(wc, card, 40)/16) ? -(wctdm_getreg(wc, card, 40) - 16) : wctdm_getreg(wc, card, 40), (wctdm_getreg(wc, card, 39)/16) ? -(wctdm_getreg(wc, card, 39) - 16): wctdm_getreg(wc, card, 39), (wctdm_getreg(wc, card, 41)/16)?-(wctdm_getreg(wc, card, 41) - 16) : wctdm_getreg(wc, card, 41));
return 0;
@@ -1932,9 +2085,11 @@
{
unsigned short tmp[5];
- unsigned char r19;
+ unsigned char r19,r9;
int x;
int fxsmode=0;
+
+ if (wc->modtype[card & 0xfc] == MOD_TYPE_QRV) return -2;
/* By default, don't send on hook */
wc->mods[card].fxs.idletxhookstate = 1;
@@ -2125,11 +2280,174 @@
printk("Reducing ring power on slot %d (50V peak)\n", card + 1);
}
}
+
+ if(fxstxgain || fxsrxgain) {
+ r9 = wctdm_getreg(wc, card, 9);
+ switch (fxstxgain) {
+
+ case 35:
+ r9+=8;
+ break;
+ case -35:
+ r9+=4;
+ break;
+ case 0:
+ break;
+ }
+
+ switch (fxsrxgain) {
+
+ case 35:
+ r9+=2;
+ break;
+ case -35:
+ r9+=1;
+ break;
+ case 0:
+ break;
+ }
+ wctdm_setreg(wc,card,9,r9);
+ }
+
+ if(debug)
+ printk("DEBUG: fxstxgain:%s fxsrxgain:%s\n",((wctdm_getreg(wc, card, 9)/8) == 1)?"3.5":(((wctdm_getreg(wc,card,9)/4) == 1)?"-3.5":"0.0"),((wctdm_getreg(wc, card, 9)/2) == 1)?"3.5":((wctdm_getreg(wc,card,9)%2)?"-3.5":"0.0"));
+
wctdm_setreg(wc, card, 64, 0x01);
wc->mods[card].fxs.lasttxhook = 1;
return 0;
}
+static int wctdm_init_qrvdri(struct wctdm *wc, int card)
+{
+ unsigned char x,y;
+ unsigned long endjif;
+
+ /* have to set this, at least for now */
+ wc->modtype[card] = MOD_TYPE_QRV;
+ if (!(card & 3)) /* if at base of card, reset and write it */
+ {
+ wctdm_setreg(wc,card,0,0x80);
+ wctdm_setreg(wc,card,0,0x55);
+ wctdm_setreg(wc,card,1,0x69);
+ wc->qrvhook[card] = wc->qrvhook[card + 1] = 0;
+ wc->qrvhook[card + 2] = wc->qrvhook[card + 3] = 0xff;
+ wc->debouncetime[card] = wc->debouncetime[card + 1] = QRV_DEBOUNCETIME;
+ wc->qrvdebtime[card] = wc->qrvdebtime[card + 1] = 0;
+ wc->radmode[card] = wc->radmode[card + 1] = 0;
+ wc->txgain[card] = wc->txgain[card + 1] = 3599;
+ wc->rxgain[card] = wc->rxgain[card + 1] = 1199;
+ } else { /* channel is on same card as base, no need to test */
+ if (wc->modtype[card & 0x7c] == MOD_TYPE_QRV)
+ {
+ /* only lower 2 are valid */
+ if (!(card & 2)) return 0;
+ }
+ wc->modtype[card] = MOD_TYPE_NONE;
+ return 1;
+ }
+ x = wctdm_getreg(wc,card,0);
+ y = wctdm_getreg(wc,card,1);
+ /* if not a QRV card, return as such */
+ if ((x != 0x55) || (y != 0x69))
+ {
+ wc->modtype[card] = MOD_TYPE_NONE;
+ return 1;
+ }
+ for(x = 0; x < 0x30; x++)
+ {
+ if ((x >= 0x1c) && (x <= 0x1e)) wctdm_setreg(wc,card,x,0xff);
+ else wctdm_setreg(wc,card,x,0);
+ }
+ wctdm_setreg(wc,card,0,0x80);
+ endjif = jiffies + (HZ/10);
+ while(endjif > jiffies);
+ wctdm_setreg(wc,card,0,0x10);
+ wctdm_setreg(wc,card,0,0x10);
+ endjif = jiffies + (HZ/10);
+ while(endjif > jiffies);
+ /* set up modes */
+ wctdm_setreg(wc,card,0,0x1c);
+ /* set up I/O directions */
+ wctdm_setreg(wc,card,1,0x33);
+ wctdm_setreg(wc,card,2,0x0f);
+ wctdm_setreg(wc,card,5,0x0f);
+ /* set up I/O to quiescent state */
+ wctdm_setreg(wc,card,3,0x11); /* D0-7 */
+ wctdm_setreg(wc,card,4,0xa); /* D8-11 */
+ wctdm_setreg(wc,card,7,0); /* CS outputs */
+ /* set up timeslots */
+ wctdm_setreg(wc,card,0x13,card + 0x80); /* codec 2 tx, ts0 */
+ wctdm_setreg(wc,card,0x17,card + 0x80); /* codec 0 rx, ts0 */
+ wctdm_setreg(wc,card,0x14,card + 0x81); /* codec 1 tx, ts1 */
+ wctdm_setreg(wc,card,0x18,card + 0x81); /* codec 1 rx, ts1 */
+ /* set up for max gains */
+ wctdm_setreg(wc,card,0x26,0x24);
+ wctdm_setreg(wc,card,0x27,0x24);
+ wctdm_setreg(wc,card,0x0b,0x01); /* "Transmit" gain codec 0 */
+ wctdm_setreg(wc,card,0x0c,0x01); /* "Transmit" gain codec 1 */
+ wctdm_setreg(wc,card,0x0f,0xff); /* "Receive" gain codec 0 */
+ wctdm_setreg(wc,card,0x10,0xff); /* "Receive" gain codec 1 */
+ return 0;
+}
+
+static void qrv_dosetup(struct zt_chan *chan,struct wctdm *wc)
+{
+int qrvcard;
+unsigned char r;
+long l;
+
+ /* actually do something with the values */
+ qrvcard = (chan->chanpos - 1) & 0xfc;
+ if (debug) printk("@@@@@ radmodes: %d,%d rxgains: %d,%d txgains: %d,%d\n",
+ wc->radmode[qrvcard],wc->radmode[qrvcard + 1],
+ wc->rxgain[qrvcard],wc->rxgain[qrvcard + 1],
+ wc->txgain[qrvcard],wc->txgain[qrvcard + 1]);
+ r = 0;
+ if (wc->radmode[qrvcard] & RADMODE_DEEMP) r |= 4;
+ if (wc->radmode[qrvcard + 1] & RADMODE_DEEMP) r |= 8;
+ if (wc->rxgain[qrvcard] < 1200) r |= 1;
+ if (wc->rxgain[qrvcard + 1] < 1200) r |= 2;
+ wctdm_setreg(wc, qrvcard, 7, r);
+ if (debug) printk("@@@@@ setting reg 7 to %02x hex\n",r);
+ r = 0;
+ if (wc->radmode[qrvcard] & RADMODE_PREEMP) r |= 3;
+ else if (wc->txgain[qrvcard] >= 3600) r |= 1;
+ else if (wc->txgain[qrvcard] >= 1200) r |= 2;
+ if (wc->radmode[qrvcard + 1] & RADMODE_PREEMP) r |= 0xc;
+ else if (wc->txgain[qrvcard + 1] >= 3600) r |= 4;
+ else if (wc->txgain[qrvcard + 1] >= 1200) r |= 8;
+ wctdm_setreg(wc, qrvcard, 4, r);
+ if (debug) printk("@@@@@ setting reg 4 to %02x hex\n",r);
+ r = 0;
+ if (wc->rxgain[qrvcard] >= 2400) r |= 1;
+ if (wc->rxgain[qrvcard + 1] >= 2400) r |= 2;
+ wctdm_setreg(wc, qrvcard, 0x25, r);
+ if (debug) printk("@@@@@ setting reg 0x25 to %02x hex\n",r);
+ r = 0;
+ if (wc->txgain[qrvcard] < 2400) r |= 1; else r |= 4;
+ if (wc->txgain[qrvcard + 1] < 2400) r |= 8; else r |= 0x20;
+ wctdm_setreg(wc, qrvcard, 0x26, r);
+ if (debug) printk("@@@@@ setting reg 0x26 to %02x hex\n",r);
+ l = ((long)(wc->rxgain[qrvcard] % 1200) * 10000) / 46875;
+ if (l == 0) l = 1;
+ if (wc->rxgain[qrvcard] >= 2400) l += 181;
+ wctdm_setreg(wc, qrvcard, 0x0b, (unsigned char)l);
+ if (debug) printk("@@@@@ setting reg 0x0b to %02x hex\n",(unsigned char)l);
+ l = ((long)(wc->rxgain[qrvcard + 1] % 1200) * 10000) / 46875;
+ if (l == 0) l = 1;
+ if (wc->rxgain[qrvcard + 1] >= 2400) l += 181;
+ wctdm_setreg(wc, qrvcard, 0x0c, (unsigned char)l);
+ if (debug) printk("@@@@@ setting reg 0x0c to %02x hex\n",(unsigned char)l);
+ l = ((long)(wc->txgain[qrvcard] % 1200) * 10000) / 46875;
+ if (l == 0) l = 1;
+ wctdm_setreg(wc, qrvcard, 0x0f, (unsigned char)l);
+ if (debug) printk("@@@@@ setting reg 0x0f to %02x hex\n", (unsigned char)l);
+ l = ((long)(wc->txgain[qrvcard + 1] % 1200) * 10000) / 46875;
+ if (l == 0) l = 1;
+ wctdm_setreg(wc, qrvcard, 0x10,(unsigned char)l);
+ if (debug) printk("@@@@@ setting reg 0x10 to %02x hex\n",(unsigned char)l);
+ return;
+}
static int wctdm_ioctl(struct zt_chan *chan, unsigned int cmd, unsigned long data)
{
@@ -2139,6 +2457,10 @@
struct wctdm_echo_coefs echoregs;
struct wctdm *wc = chan->pvt;
int x;
+ union {
+ struct zt_radio_stat s;
+ struct zt_radio_param p;
+ } stack;
#if 0
/* XXX */
@@ -2202,6 +2524,10 @@
regs.indirect[x] = wctdm_proslic_getreg_indirect(wc, chan->chanpos -1, x);
for (x=0;x<NUM_REGS;x++)
regs.direct[x] = wctdm_getreg(wc, chan->chanpos - 1, x);
+ } else if (wc->modtype[chan->chanpos - 1] == MOD_TYPE_QRV) {
+ memset(®s, 0, sizeof(regs));
+ for (x=0;x<0x32;x++)
+ regs.direct[x] = wctdm_getreg(wc, chan->chanpos - 1, x);
} else {
memset(®s, 0, sizeof(regs));
for (x=0;x<NUM_FXO_REGS;x++)
@@ -2275,12 +2601,150 @@
}
return 0;
#endif
+ case ZT_RADIO_GETPARAM:
+ if (wc->modtype[chan->chanpos - 1] != MOD_TYPE_QRV)
+ return -ENOTTY;
+ if (copy_from_user(&stack.p,(struct zt_radio_param *)data,sizeof(struct zt_radio_param))) return -EFAULT;
+ stack.p.data = 0; /* start with 0 value in output */
+ switch(stack.p.radpar) {
+ case ZT_RADPAR_INVERTCOR:
+ if (wc->radmode[chan->chanpos - 1] & RADMODE_INVERTCOR)
+ stack.p.data = 1;
+ break;
+ case ZT_RADPAR_IGNORECOR:
+ if (wc->radmode[chan->chanpos - 1] & RADMODE_IGNORECOR)
+ stack.p.data = 1;
+ break;
+ case ZT_RADPAR_IGNORECT:
+ if (wc->radmode[chan->chanpos - 1] & RADMODE_IGNORECT)
+ stack.p.data = 1;
+ break;
+ case ZT_RADPAR_EXTRXTONE:
+ stack.p.data = 0;
+ if (wc->radmode[chan->chanpos - 1] & RADMODE_EXTTONE)
+ {
+ stack.p.data = 1;
+ if (wc->radmode[chan->chanpos - 1] & RADMODE_EXTINVERT)
+ {
+ stack.p.data = 2;
+ }
+ }
+ break;
+ case ZT_RADPAR_DEBOUNCETIME:
+ stack.p.data = wc->debouncetime[chan->chanpos - 1];
+ break;
+ case ZT_RADPAR_RXGAIN:
+ stack.p.data = wc->rxgain[chan->chanpos - 1] - 1199;
+ break;
+ case ZT_RADPAR_TXGAIN:
+ stack.p.data = wc->txgain[chan->chanpos - 1] - 3599;
+ break;
+ case ZT_RADPAR_DEEMP:
+ stack.p.data = 0;
+ if (wc->radmode[chan->chanpos - 1] & RADMODE_DEEMP)
+ {
+ stack.p.data = 1;
+ }
+ break;
+ case ZT_RADPAR_PREEMP:
+ stack.p.data = 0;
+ if (wc->radmode[chan->chanpos - 1] & RADMODE_PREEMP)
+ {
+ stack.p.data = 1;
+ }
+ break;
+ default:
+ return -EINVAL;
+ }
+ if (copy_to_user((struct zt_radio_param *)data,&stack.p,sizeof(struct zt_radio_param))) return -EFAULT;
+ break;
+ case ZT_RADIO_SETPARAM:
+ if (wc->modtype[chan->chanpos - 1] != MOD_TYPE_QRV)
+ return -ENOTTY;
+ if (copy_from_user(&stack.p,(struct zt_radio_param *)data,sizeof(struct zt_radio_param))) return -EFAULT;
+ switch(stack.p.radpar) {
+ case ZT_RADPAR_INVERTCOR:
+ if (stack.p.data)
+ wc->radmode[chan->chanpos - 1] |= RADMODE_INVERTCOR;
+ else
+ wc->radmode[chan->chanpos - 1] &= ~RADMODE_INVERTCOR;
+ return 0;
+ case ZT_RADPAR_IGNORECOR:
+ if (stack.p.data)
+ wc->radmode[chan->chanpos - 1] |= RADMODE_IGNORECOR;
+ else
+ wc->radmode[chan->chanpos - 1] &= ~RADMODE_IGNORECOR;
+ return 0;
+ case ZT_RADPAR_IGNORECT:
+ if (stack.p.data)
+ wc->radmode[chan->chanpos - 1] |= RADMODE_IGNORECT;
+ else
+ wc->radmode[chan->chanpos - 1] &= ~RADMODE_IGNORECT;
+ return 0;
+ case ZT_RADPAR_EXTRXTONE:
+ if (stack.p.data)
+ wc->radmode[chan->chanpos - 1] |= RADMODE_EXTTONE;
+ else
+ wc->radmode[chan->chanpos - 1] &= ~RADMODE_EXTTONE;
+ if (stack.p.data > 1)
+ wc->radmode[chan->chanpos - 1] |= RADMODE_EXTINVERT;
+ else
+ wc->radmode[chan->chanpos - 1] &= ~RADMODE_EXTINVERT;
+ return 0;
+ case ZT_RADPAR_DEBOUNCETIME:
+ wc->debouncetime[chan->chanpos - 1] = stack.p.data;
+ return 0;
+ case ZT_RADPAR_RXGAIN:
+ /* if out of range */
+ if ((stack.p.data <= -1200) || (stack.p.data > 1552))
+ {
+ return -EINVAL;
+ }
+ wc->rxgain[chan->chanpos - 1] = stack.p.data + 1199;
+ break;
+ case ZT_RADPAR_TXGAIN:
+ /* if out of range */
+ if (wc->radmode[chan->chanpos -1] & RADMODE_PREEMP)
+ {
+ if ((stack.p.data <= -2400) || (stack.p.data > 0))
+ {
+ return -EINVAL;
+ }
+ }
+ else
+ {
+ if ((stack.p.data <= -3600) || (stack.p.data > 1200))
+ {
+ return -EINVAL;
+ }
+ }
+ wc->txgain[chan->chanpos - 1] = stack.p.data + 3599;
+ break;
+ case ZT_RADPAR_DEEMP:
+ if (stack.p.data)
+ wc->radmode[chan->chanpos - 1] |= RADMODE_DEEMP;
+ else
+ wc->radmode[chan->chanpos - 1] &= ~RADMODE_DEEMP;
+ wc->rxgain[chan->chanpos - 1] = 1199;
+ break;
+ case ZT_RADPAR_PREEMP:
+ if (stack.p.data)
+ wc->radmode[chan->chanpos - 1] |= RADMODE_PREEMP;
+ else
+ wc->radmode[chan->chanpos - 1] &= ~RADMODE_PREEMP;
+ wc->txgain[chan->chanpos - 1] = 3599;
+ break;
+ default:
+ return -EINVAL;
+ }
+ qrv_dosetup(chan,wc);
+ return 0;
default:
return -ENOTTY;
}
return 0;
-
-}
+}
+
static int wctdm_open(struct zt_chan *chan)
{
struct wctdm *wc = chan->pvt;
@@ -2308,6 +2772,7 @@
{
struct wctdm *wc = chan->pvt;
int x;
+ signed char reg;
wc->usecount--;
#ifndef LINUX26
MOD_DEC_USE_COUNT;
@@ -2317,6 +2782,23 @@
for (x=0;x<wc->cards;x++) {
if (wc->modtype[x] == MOD_TYPE_FXS)
wc->mods[x].fxs.idletxhookstate = 1;
+ if (wc->modtype[x] == MOD_TYPE_QRV)
+ {
+ int qrvcard = x & 0xfc;
+
+ wc->qrvhook[x] = 0;
+ wc->qrvhook[x + 2] = 0xff;
+ wc->debouncetime[x] = QRV_DEBOUNCETIME;
+ wc->qrvdebtime[x] = 0;
+ wc->radmode[x] = 0;
+ wc->txgain[x] = 3599;
+ wc->rxgain[x] = 1199;
+ reg = 0;
+ if (!wc->qrvhook[qrvcard]) reg |= 1;
+ if (!wc->qrvhook[qrvcard + 1]) reg |= 0x10;
+ wc->sethook[qrvcard] = CMD_WR(3, reg);
+ qrv_dosetup(chan,wc);
+ }
}
/* If we're dead, release us now */
if (!wc->usecount && wc->dead)
@@ -2327,8 +2809,26 @@
static int wctdm_hooksig(struct zt_chan *chan, zt_txsig_t txsig)
{
struct wctdm *wc = chan->pvt;
- int reg=0;
- if (wc->modtype[chan->chanpos - 1] == MOD_TYPE_FXO) {
+ int reg=0,qrvcard;
+ if (wc->modtype[chan->chanpos - 1] == MOD_TYPE_QRV) {
+ qrvcard = (chan->chanpos - 1) & 0xfc;
+ switch(txsig) {
+ case ZT_TXSIG_START:
+ case ZT_TXSIG_OFFHOOK:
+ wc->qrvhook[chan->chanpos - 1] = 1;
+ break;
+ case ZT_TXSIG_ONHOOK:
+ wc->qrvhook[chan->chanpos - 1] = 0;
+ break;
+ default:
+ printk("wctdm24xxp: Can't set tx state to %d\n", txsig);
+ }
+ reg = 0;
+ if (!wc->qrvhook[qrvcard]) reg |= 1;
+ if (!wc->qrvhook[qrvcard + 1]) reg |= 0x10;
+ wc->sethook[qrvcard] = CMD_WR(3, reg);
+ /* wctdm_setreg(wc, qrvcard, 3, reg); */
+ } else if (wc->modtype[chan->chanpos - 1] == MOD_TYPE_FXO) {
switch(txsig) {
case ZT_TXSIG_START:
case ZT_TXSIG_OFFHOOK:
@@ -2387,6 +2887,102 @@
return 0;
}
+static void wctdm_dacs_connect(struct wctdm *wc, int srccard, int dstcard)
+{
+
+ if (wc->dacssrc[dstcard] > - 1) {
+ printk("wctdm_dacs_connect: Can't have double sourcing yet!\n");
+ return;
+ }
+ if (!((wc->modtype[srccard] == MOD_TYPE_FXS)||(wc->modtype[srccard] == MOD_TYPE_FXO))){
+ printk("wctdm_dacs_connect: Unsupported modtype for card %d\n", srccard);
+ return;
+ }
+ if (!((wc->modtype[dstcard] == MOD_TYPE_FXS)||(wc->modtype[dstcard] == MOD_TYPE_FXO))){
+ printk("wctdm_dacs_connect: Unsupported modtype for card %d\n", dstcard);
+ return;
+ }
+ if (debug)
+ printk("connect %d => %d\n", srccard, dstcard);
+ wc->dacssrc[dstcard] = srccard;
+
+ /* make srccard transmit to srccard+24 on the TDM bus */
+ if (wc->modtype[srccard] == MOD_TYPE_FXS) {
+ /* proslic */
+ wctdm_setreg(wc, srccard, PCM_XMIT_START_COUNT_LSB, ((srccard+24) * 8) & 0xff);
+ wctdm_setreg(wc, srccard, PCM_XMIT_START_COUNT_MSB, ((srccard+24) * 8) >> 8);
+ } else if(wc->modtype[srccard] == MOD_TYPE_FXO) {
+ /* daa */
+ wctdm_setreg(wc, srccard, 34, ((srccard+24) * 8) & 0xff); /* TX */
+ wctdm_setreg(wc, srccard, 35, ((srccard+24) * 8) >> 8); /* TX */
+ }
+
+ /* have dstcard receive from srccard+24 on the TDM bus */
+ if (wc->modtype[dstcard] == MOD_TYPE_FXS) {
+ /* proslic */
+ wctdm_setreg(wc, dstcard, PCM_RCV_START_COUNT_LSB, ((srccard+24) * 8) & 0xff);
+ wctdm_setreg(wc, dstcard, PCM_RCV_START_COUNT_MSB, ((srccard+24) * 8) >> 8);
+ } else if(wc->modtype[dstcard] == MOD_TYPE_FXO) {
+ /* daa */
+ wctdm_setreg(wc, dstcard, 36, ((srccard+24) * 8) & 0xff); /* RX */
+ wctdm_setreg(wc, dstcard, 37, ((srccard+24) * 8) >> 8); /* RX */
+ }
+
+}
+
+static void wctdm_dacs_disconnect(struct wctdm *wc, int card)
+{
+ if (wc->dacssrc[card] > -1) {
+ if (debug)
+ printk("wctdm_dacs_disconnect: restoring TX for %d and RX for %d\n",wc->dacssrc[card], card);
+
+ /* restore TX (source card) */
+ if(wc->modtype[wc->dacssrc[card]] == MOD_TYPE_FXS){
+ wctdm_setreg(wc, wc->dacssrc[card], PCM_XMIT_START_COUNT_LSB, (wc->dacssrc[card] * 8) & 0xff);
+ wctdm_setreg(wc, wc->dacssrc[card], PCM_XMIT_START_COUNT_MSB, (wc->dacssrc[card] * 8) >> 8);
+ } else if(wc->modtype[wc->dacssrc[card]] == MOD_TYPE_FXO){
+ wctdm_setreg(wc, card, 34, (card * 8) & 0xff);
+ wctdm_setreg(wc, card, 35, (card * 8) >> 8);
+ } else {
+ printk("WARNING: wctdm_dacs_disconnect() called on unsupported modtype\n");
+ }
+
+ /* restore RX (this card) */
+ if(wc->modtype[card] == MOD_TYPE_FXS){
+ wctdm_setreg(wc, card, PCM_RCV_START_COUNT_LSB, (card * 8) & 0xff);
+ wctdm_setreg(wc, card, PCM_RCV_START_COUNT_MSB, (card * 8) >> 8);
+ } else if(wc->modtype[card] == MOD_TYPE_FXO){
+ wctdm_setreg(wc, card, 36, (card * 8) & 0xff);
+ wctdm_setreg(wc, card, 37, (card * 8) >> 8);
+ } else {
+ printk("WARNING: wctdm_dacs_disconnect() called on unsupported modtype\n");
+ }
+
+ wc->dacssrc[card] = -1;
+ }
+}
+
+static int wctdm_dacs(struct zt_chan *dst, struct zt_chan *src)
+{
+ struct wctdm *wc;
+
+ if(!nativebridge)
+ return 0; /* should this return -1 since unsuccessful? */
+
+ wc = dst->pvt;
+
+ if(src) {
+ wctdm_dacs_connect(wc, src->chanpos - 1, dst->chanpos - 1);
+ if (debug)
+ printk("dacs connecct: %d -> %d!\n\n", src->chanpos, dst->chanpos);
+ } else {
+ wctdm_dacs_disconnect(wc, dst->chanpos - 1);
+ if (debug)
+ printk("dacs disconnect: %d!\n", dst->chanpos);
+ }
+ return 0;
+}
+
static int wctdm_initialize(struct wctdm *wc)
{
int x;
@@ -2414,6 +3010,7 @@
wc->span.flags = ZT_FLAG_RBS;
wc->span.ioctl = wctdm_ioctl;
wc->span.watchdog = wctdm_watchdog;
+ wc->span.dacs= wctdm_dacs;
#ifdef VPM_SUPPORT
wc->span.echocan = wctdm_echocan;
#endif
@@ -2437,6 +3034,8 @@
wc->chans[x].sigcap = ZT_SIG_FXSKS | ZT_SIG_FXSLS | ZT_SIG_SF | ZT_SIG_CLEAR;
else if (wc->modtype[x] == MOD_TYPE_FXS)
wc->chans[x].sigcap = ZT_SIG_FXOKS | ZT_SIG_FXOLS | ZT_SIG_FXOGS | ZT_SIG_SF | ZT_SIG_EM | ZT_SIG_CLEAR;
+ else if (wc->modtype[x] == MOD_TYPE_QRV)
+ wc->chans[x].sigcap = ZT_SIG_SF | ZT_SIG_EM | ZT_SIG_CLEAR;
}
}
}
@@ -3237,7 +3836,7 @@
if (debug & DEBUG_CARD) {
readi = wctdm_getreg(wc,x,LOOP_I_LIMIT);
printk("Proslic module %d loop current is %dmA\n",x,
- ((readi*3)+20));
+ ((readi*3)+20));
}
printk("Port %d: Installed -- AUTO FXS/DPO\n", x + 1);
} else {
@@ -3249,7 +3848,7 @@
if (debug & DEBUG_CARD) {
readi = wctdm_getreg(wc,x,LOOP_I_LIMIT);
printk("Proslic module %d loop current is %dmA\n",x,
- ((readi*3)+20));
+ ((readi*3)+20));
}
printk("Port %d: Installed -- MANUAL FXS\n",x + 1);
} else {
@@ -3258,6 +3857,9 @@
} else if (!(ret = wctdm_init_voicedaa(wc, x, 0, 0, sane))) {
wc->cardflag |= (1 << x);
printk("Port %d: Installed -- AUTO FXO (%s mode)\n",x + 1, fxo_modes[_opermode].name);
+ } else if (!wctdm_init_qrvdri(wc,x)) {
+ wc->cardflag |= 1 << x;
+ printk("Port %d: Installed -- QRV DRI card\n",x + 1);
} else {
if ((wc->type == 8) && ((x & 0x3) == 1) && !wc->altcs[x]) {
spin_lock_irqsave(&wc->reglock, flags);
@@ -3327,8 +3929,10 @@
wc->dev = pdev;
wc->pos = x;
wc->variety = d->name;
- for (y=0;y<NUM_CARDS;y++)
+ for (y=0;y<NUM_CARDS;y++) {
wc->flags[y] = d->flags;
+ wc->dacssrc[y] = -1;
+ }
/* Keep track of whether we need to free the region */
if (request_region(wc->iobase, 0xff, "wctdm24xxp"))
wc->freeregion = 1;
@@ -3509,6 +4113,7 @@
{
int res;
int x;
+
for (x=0;x<(sizeof(fxo_modes) / sizeof(fxo_modes[0])); x++) {
if (!strcmp(fxo_modes[x].name, opermode))
break;
@@ -3549,6 +4154,11 @@
module_param(battdebounce, int, 0600);
module_param(battthresh, int, 0600);
module_param(alawoverride, int, 0600);
+module_param(nativebridge, int, 0600);
+module_param(fxotxgain, int, 0600);
+module_param(fxorxgain, int, 0600);
+module_param(fxstxgain, int, 0600);
+module_param(fxsrxgain, int, 0600);
#ifdef VPM_SUPPORT
module_param(vpmsupport, int, 0600);
module_param(vpmdtmfsupport, int, 0600);
@@ -3567,6 +4177,11 @@
MODULE_PARM(battdebounce, "i");
MODULE_PARM(battthresh, "i");
MODULE_PARM(alawoverride, "i");
+MODULE_PARM(nativebridge, "i");
+MODULE_PARM(fxotxgain, "i");
+MODULE_PARM(fxorxgain, "i");
+MODULE_PARM(fxstxgain, "i");
+MODULE_PARM(fxsrxgain, "i");
#ifdef VPM_SUPPORT
MODULE_PARM(vpmsupport, "i");
MODULE_PARM(vpmdtmfsupport, "i");
Copied: branches/1.4/wctdm24xxp/wctdm24xxp.h (from r2761, branches/1.2/wctdm24xxp/wctdm24xxp.h)
URL: http://svn.digium.com/view/zaptel/branches/1.4/wctdm24xxp/wctdm24xxp.h?view=diff&rev=2762&p1=branches/1.2/wctdm24xxp/wctdm24xxp.h&r1=2761&p2=branches/1.4/wctdm24xxp/wctdm24xxp.h&r2=2762
==============================================================================
--- branches/1.2/wctdm24xxp/wctdm24xxp.h (original)
+++ branches/1.4/wctdm24xxp/wctdm24xxp.h Fri Jul 20 13:54:20 2007
@@ -29,7 +29,8 @@
#define MOD_TYPE_FXO 2
#define MOD_TYPE_FXSINIT 3
#define MOD_TYPE_VPM 4
-#define MOD_TYPE_VPM150M 5
+#define MOD_TYPE_QRV 5
+#define MOD_TYPE_VPM150M 6
#define MINPEGTIME 10 * 8 /* 30 ms peak to peak gets us no more than 100 Hz */
#define PEGTIME 50 * 8 /* 50ms peak to peak gets us rings of 10 Hz or more */
@@ -61,6 +62,7 @@
#define USER_COMMANDS 8
#define ISR_COMMANDS 2
+#define QRV_DEBOUNCETIME 20
#define MAX_COMMANDS (USER_COMMANDS + ISR_COMMANDS)
@@ -154,6 +156,19 @@
int cards;
int cardflag; /* Bit-map of present cards */
int altcs[NUM_CARDS + NUM_EC];
+ char qrvhook[NUM_CARDS];
+ unsigned short qrvdebtime[NUM_CARDS];
+ int radmode[NUM_CARDS];
+#define RADMODE_INVERTCOR 1
+#define RADMODE_IGNORECOR 2
+#define RADMODE_EXTTONE 4
+#define RADMODE_EXTINVERT 8
+#define RADMODE_IGNORECT 16
+#define RADMODE_PREEMP 32
+#define RADMODE_DEEMP 64
+ unsigned short debouncetime[NUM_CARDS];
+ signed short rxgain[NUM_CARDS];
+ signed short txgain[NUM_CARDS];
spinlock_t reglock;
wait_queue_head_t regq;
/* FXO Stuff */
@@ -186,6 +201,7 @@
int modtype[NUM_CARDS + NUM_EC];
/* Set hook */
int sethook[NUM_CARDS + NUM_EC];
+ int dacssrc[NUM_CARDS];
int type;
#ifdef VPM_SUPPORT
Modified: branches/1.4/zaptel-base.c
URL: http://svn.digium.com/view/zaptel/branches/1.4/zaptel-base.c?view=diff&rev=2762&r1=2761&r2=2762
==============================================================================
--- branches/1.4/zaptel-base.c (original)
+++ branches/1.4/zaptel-base.c Fri Jul 20 13:54:20 2007
@@ -1049,12 +1049,13 @@
memset(chan->conflast1, 0, sizeof(chan->conflast1));
memset(chan->conflast2, 0, sizeof(chan->conflast2));
+ if (chan->span && chan->span->dacs && oldconf)
+ chan->span->dacs(chan, NULL);
+
+ spin_unlock_irqrestore(&chan->lock, flags);
+
if (chan->span && chan->span->echocan)
chan->span->echocan(chan, 0);
- if (chan->span && chan->span->dacs && oldconf)
- chan->span->dacs(chan, NULL);
-
- spin_unlock_irqrestore(&chan->lock, flags);
if (rxgain)
kfree(rxgain);
@@ -2279,9 +2280,11 @@
chan->ringcadence[0] = chan->starttime;
chan->ringcadence[1] = ZT_RINGOFFTIME;
}
+
+ spin_unlock_irqrestore(&chan->lock, flags);
+
if (chan->span && chan->span->echocan)
chan->span->echocan(chan, 0);
- spin_unlock_irqrestore(&chan->lock, flags);
if (rxgain)
kfree(rxgain);
@@ -4283,9 +4286,10 @@
chan->txgain = defgain;
chan->gainalloc = 0;
/* Disable any native echo cancellation as well */
+ spin_unlock_irqrestore(&chan->lock, flags);
+
if (chan->span && chan->span->echocan)
chan->span->echocan(chan, 0);
- spin_unlock_irqrestore(&chan->lock, flags);
if (rxgain)
kfree(rxgain);
@@ -4389,10 +4393,13 @@
tec = chan->ec;
chan->ec = NULL;
/* Attempt hardware native echo can */
+ spin_unlock_irqrestore(&chan->lock, flags);
+
if (chan->span && chan->span->echocan)
ret = chan->span->echocan(chan, j);
else
ret = -ENOTTY;
+
if (ret) {
/* Use built-in echo can */
if ((j == 32) ||
@@ -4405,7 +4412,6 @@
} else {
j = deftaps;
}
- spin_unlock_irqrestore(&chan->lock, flags);
ec = echo_can_create(j, 0);
if (!ec)
return -ENOMEM;
@@ -4417,8 +4423,8 @@
chan->echotimer = 0;
echo_can_disable_detector_init(&chan->txecdis);
echo_can_disable_detector_init(&chan->rxecdis);
- }
- spin_unlock_irqrestore(&chan->lock, flags);
+ spin_unlock_irqrestore(&chan->lock, flags);
+ }
if (tec)
echo_can_free(tec);
} else {
@@ -4429,10 +4435,10 @@
chan->echostate = ECHO_STATE_IDLE;
chan->echolastupdate = 0;
chan->echotimer = 0;
+ spin_unlock_irqrestore(&chan->lock, flags);
/* Attempt hardware native echo can */
if (chan->span && chan->span->echocan)
chan->span->echocan(chan, 0);
- spin_unlock_irqrestore(&chan->lock, flags);
if (tec)
echo_can_free(tec);
}
More information about the zaptel-commits
mailing list