summaryrefslogtreecommitdiff
path: root/drivers/dahdi/wctdm24xxp
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/dahdi/wctdm24xxp')
-rw-r--r--drivers/dahdi/wctdm24xxp/base.c96
-rw-r--r--drivers/dahdi/wctdm24xxp/wctdm24xxp.h1
2 files changed, 86 insertions, 11 deletions
diff --git a/drivers/dahdi/wctdm24xxp/base.c b/drivers/dahdi/wctdm24xxp/base.c
index 9a6a8ce..0985a57 100644
--- a/drivers/dahdi/wctdm24xxp/base.c
+++ b/drivers/dahdi/wctdm24xxp/base.c
@@ -228,6 +228,32 @@ static int vpmnlpthresh = 24;
/* See vpmnlptype = 4 for more info */
static int vpmnlpmaxsupp = 0;
+static int echocan_create(struct dahdi_chan *chan, struct dahdi_echocanparams *ecp,
+ struct dahdi_echocanparam *p, struct dahdi_echocan_state **ec);
+static void echocan_free(struct dahdi_chan *chan, struct dahdi_echocan_state *ec);
+
+static const struct dahdi_echocan_features vpm100m_ec_features = {
+ .NLP_automatic = 1,
+ .CED_tx_detect = 1,
+ .CED_rx_detect = 1,
+};
+
+static const struct dahdi_echocan_features vpm150m_ec_features = {
+ .NLP_automatic = 1,
+ .CED_tx_detect = 1,
+ .CED_rx_detect = 1,
+};
+
+static const struct dahdi_echocan_ops vpm100m_ec_ops = {
+ .name = "VPM100M",
+ .echocan_free = echocan_free,
+};
+
+static const struct dahdi_echocan_ops vpm150m_ec_ops = {
+ .name = "VPM150M",
+ .echocan_free = echocan_free,
+};
+
static int wctdm_init_proslic(struct wctdm *wc, int card, int fast , int manual, int sane);
static inline int CMD_BYTE(int card, int bit, int altcs)
@@ -1628,10 +1654,32 @@ static inline void wctdm_vpm_check(struct wctdm *wc, int x)
}
}
-static int wctdm_echocan_with_params(struct dahdi_chan *chan,
- struct dahdi_echocanparams *ecp, struct dahdi_echocanparam *p)
+static int echocan_create(struct dahdi_chan *chan, struct dahdi_echocanparams *ecp,
+ struct dahdi_echocanparam *p, struct dahdi_echocan_state **ec)
{
struct wctdm *wc = chan->pvt;
+ const struct dahdi_echocan_ops *ops;
+ const struct dahdi_echocan_features *features;
+
+ if (!wc->vpm100 && !wc->vpmadt032)
+ return -ENODEV;
+
+ if (wc->vpmadt032) {
+ ops = &vpm150m_ec_ops;
+ features = &vpm150m_ec_features;
+ } else {
+ ops = &vpm100m_ec_ops;
+ features = &vpm100m_ec_features;
+ }
+
+ if (wc->vpm100 && (ecp->param_count > 0)) {
+ printk(KERN_WARNING "%s echo canceller does not support parameters; failing request\n", ops->name);
+ return -EINVAL;
+ }
+
+ *ec = wc->ec[chan->chanpos - 1];
+ (*ec)->ops = ops;
+ (*ec)->features = *features;
if (wc->vpm100) {
int channel;
@@ -1642,23 +1690,42 @@ static int wctdm_echocan_with_params(struct dahdi_chan *chan,
if (wc->vpm100 < 2)
channel >>= 2;
- if(debug & DEBUG_ECHOCAN)
- printk(KERN_DEBUG "echocan: Unit is %d, Channel is %d length %d\n",
- unit, channel, ecp->tap_length);
- if (ecp->tap_length)
- wctdm_vpm_out(wc,unit,channel,0x3e);
- else
- wctdm_vpm_out(wc,unit,channel,0x01);
+ if (debug & DEBUG_ECHOCAN)
+ printk(KERN_DEBUG "echocan: Unit is %d, Channel is %d length %d\n", unit, channel, ecp->tap_length);
+ wctdm_vpm_out(wc, unit, channel, 0x3e);
return 0;
} else if (wc->vpmadt032) {
- return vpmadt032_echocan_with_params(wc->vpmadt032,
+ return vpmadt032_echocan_create(wc->vpmadt032,
chan->chanpos-1, ecp, p);
} else {
return -ENODEV;
}
}
+static void echocan_free(struct dahdi_chan *chan, struct dahdi_echocan_state *ec)
+{
+ struct wctdm *wc = chan->pvt;
+
+ memset(ec, 0, sizeof(*ec));
+ if (wc->vpm100) {
+ int channel;
+ int unit;
+
+ channel = (chan->chanpos - 1);
+ unit = (chan->chanpos - 1) & 0x3;
+ if (wc->vpm100 < 2)
+ channel >>= 2;
+
+ if (debug & DEBUG_ECHOCAN)
+ printk(KERN_DEBUG "echocan: Unit is %d, Channel is %d length 0\n",
+ unit, channel);
+ wctdm_vpm_out(wc, unit, channel, 0x01);
+ } else if (wc->vpmadt032) {
+ vpmadt032_echocan_free(wc->vpmadt032, chan, ec);
+ }
+}
+
static inline void wctdm_isr_misc(struct wctdm *wc)
{
int x;
@@ -3187,7 +3254,7 @@ static int wctdm_initialize(struct wctdm *wc)
wc->span.watchdog = wctdm_watchdog;
wc->span.dacs= wctdm_dacs;
#ifdef VPM_SUPPORT
- wc->span.echocan_with_params = wctdm_echocan_with_params;
+ wc->span.echocan_create = echocan_create;
#endif
init_waitqueue_head(&wc->span.maintq);
@@ -3587,6 +3654,8 @@ static void free_wc(struct wctdm *wc)
if (wc->chans[x]) {
kfree(wc->chans[x]);
}
+ if (wc->ec[x])
+ kfree(wc->ec[x]);
}
kfree(wc);
}
@@ -3651,6 +3720,11 @@ retry:
return -ENOMEM;
}
memset(wc->chans[i], 0, sizeof(*wc->chans[i]));
+ if (!(wc->ec[i] = kmalloc(sizeof(*wc->ec[i]), GFP_KERNEL))) {
+ free_wc(wc);
+ return -ENOMEM;
+ }
+ memset(wc->ec[i], 0, sizeof(*wc->ec[i]));
}
diff --git a/drivers/dahdi/wctdm24xxp/wctdm24xxp.h b/drivers/dahdi/wctdm24xxp/wctdm24xxp.h
index 4bb90b7..3d08bef 100644
--- a/drivers/dahdi/wctdm24xxp/wctdm24xxp.h
+++ b/drivers/dahdi/wctdm24xxp/wctdm24xxp.h
@@ -235,6 +235,7 @@ struct wctdm {
#endif
struct voicebus *vb;
struct dahdi_chan *chans[NUM_CARDS];
+ struct dahdi_echocan_state *ec[NUM_CARDS];
int initialized;
};