summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorShaun Ruffell <sruffell@digium.com>2009-11-12 20:02:24 +0000
committerShaun Ruffell <sruffell@digium.com>2009-11-12 20:02:24 +0000
commitd9c6c401a232b45b454316700aad63cf5d9f539a (patch)
tree718b76da82f9e08657950cc050c183767cc51f1d
parentecb48ce630aaf4754efb4159e4d9b8256f26148d (diff)
Merged revisions 7309,7348,7565-7571 via svnmerge from
https://origsvn.digium.com/svn/dahdi/linux/trunk ........ r7309 | mattf | 2009-10-02 11:31:58 -0500 (Fri, 02 Oct 2009) | 1 line Implement API update to do per-channel companding selection for VPMADT032 ........ r7348 | mattf | 2009-10-07 16:26:08 -0500 (Wed, 07 Oct 2009) | 1 line Fix a logic error in the companding check. Duh.... ........ r7565 | sruffell | 2009-11-12 13:22:06 -0600 (Thu, 12 Nov 2009) | 7 lines voicebus: Fix race when enabling/disabling hardware echocan. This closes a race condition where it was possible for the driver to believe it has enabled the VPMADT032 when in fact, it really has not. This fixes a regression introduced in dahdi-linux 2.2.0. (issue #15724) ........ r7566 | sruffell | 2009-11-12 13:22:06 -0600 (Thu, 12 Nov 2009) | 1 line wctdm24xxp, wcte12xp: We no longer have any DTMF events to check for. ........ r7567 | sruffell | 2009-11-12 13:22:07 -0600 (Thu, 12 Nov 2009) | 1 line voicebus: Remove unused curtone from 'struct vpmadt032' ........ r7568 | sruffell | 2009-11-12 13:22:07 -0600 (Thu, 12 Nov 2009) | 1 line voicebus: Remove redundant MAX_CHANNELS_FROM_SPAN ........ r7569 | sruffell | 2009-11-12 13:22:08 -0600 (Thu, 12 Nov 2009) | 3 lines voicebus: Use dev_xxx macro when printing vpm messages. We also do not need the unused context member of the vpmadt032 structure. ........ r7570 | sruffell | 2009-11-12 13:22:08 -0600 (Thu, 12 Nov 2009) | 4 lines wcte12xp: Change serial port configuration setting for hw echocan. The wcte12xp, like the wctdm24xpp, should have the PcmOutPortA set to SerialPortNull. ........ r7571 | sruffell | 2009-11-12 13:56:49 -0600 (Thu, 12 Nov 2009) | 1 line kernel.h: Define 'list_replace' for kernels < 2.6.18 ........ git-svn-id: http://svn.asterisk.org/svn/dahdi/linux/branches/2.2@7572 a0bf4364-ded3-4de4-8d8a-66a801d63aff
-rw-r--r--drivers/dahdi/adt_lec.c4
-rw-r--r--drivers/dahdi/adt_lec.h6
-rw-r--r--drivers/dahdi/voicebus/GpakCust.c294
-rw-r--r--drivers/dahdi/voicebus/GpakCust.h11
-rw-r--r--drivers/dahdi/wctdm24xxp/base.c35
-rw-r--r--drivers/dahdi/wcte12xp/base.c18
-rw-r--r--include/dahdi/kernel.h10
7 files changed, 239 insertions, 139 deletions
diff --git a/drivers/dahdi/adt_lec.c b/drivers/dahdi/adt_lec.c
index 02c1322..18de6c0 100644
--- a/drivers/dahdi/adt_lec.c
+++ b/drivers/dahdi/adt_lec.c
@@ -29,8 +29,10 @@
static inline void adt_lec_init_defaults(struct adt_lec_params *params, __u32 tap_length)
{
- memset(params, 0, sizeof(*params));
params->tap_length = tap_length;
+ params->nlp_type = 0;
+ params->nlp_max_suppress = 0;
+ params->nlp_threshold = 0;
}
static int adt_lec_parse_params(struct adt_lec_params *params,
diff --git a/drivers/dahdi/adt_lec.h b/drivers/dahdi/adt_lec.h
index b2f7896..678fb30 100644
--- a/drivers/dahdi/adt_lec.h
+++ b/drivers/dahdi/adt_lec.h
@@ -32,11 +32,17 @@ enum adt_lec_nlp_type {
ADT_LEC_SUPPRESS,
};
+enum adt_companding {
+ ADT_COMP_ULAW = 0,
+ ADT_COMP_ALAW,
+};
+
struct adt_lec_params {
__u32 tap_length;
enum adt_lec_nlp_type nlp_type;
__u32 nlp_threshold;
__u32 nlp_max_suppress;
+ enum adt_companding companding;
};
#endif /* _ADT_LEC_H */
diff --git a/drivers/dahdi/voicebus/GpakCust.c b/drivers/dahdi/voicebus/GpakCust.c
index 00fe603..ec23336 100644
--- a/drivers/dahdi/voicebus/GpakCust.c
+++ b/drivers/dahdi/voicebus/GpakCust.c
@@ -53,6 +53,9 @@
static rwlock_t ifacelock;
static struct vpmadt032 *ifaces[MAX_DSP_CORES];
+#define vpm_info(vpm, format, arg...) \
+ dev_info(&voicebus_get_pci_dev(vpm->vb)->dev , format , ## arg)
+
static inline struct vpmadt032 *find_iface(const unsigned short dspid)
{
struct vpmadt032 *ret;
@@ -212,29 +215,42 @@ static int vpmadt032_setreg(struct vpmadt032 *vpm, unsigned int addr, u16 data)
return res;
}
-static int vpmadt032_enable_ec(struct vpmadt032 *vpm, int channel)
+struct change_order {
+ struct list_head node;
+ unsigned int channel;
+ struct adt_lec_params params;
+};
+
+static struct change_order *alloc_change_order(void)
+{
+ return kzalloc(sizeof(struct change_order), GFP_KERNEL);
+}
+
+static void free_change_order(struct change_order *order)
+{
+ kfree(order);
+}
+
+static int vpmadt032_enable_ec(struct vpmadt032 *vpm, int channel,
+ enum adt_companding companding)
{
int res;
GPAK_AlgControlStat_t pstatus;
GpakAlgCtrl_t control;
- if (vpm->span) {
- control = (DAHDI_LAW_ALAW == vpm->span->deflaw) ?
- EnableALawSwCompanding :
- EnableMuLawSwCompanding;
- } else {
- control = EnableMuLawSwCompanding;
- }
+ control = (ADT_COMP_ALAW == companding) ? EnableALawSwCompanding :
+ EnableMuLawSwCompanding;
+
if (vpm->options.debug & DEBUG_ECHOCAN) {
const char *law;
law = (control == EnableMuLawSwCompanding) ? "MuLaw" : "ALaw";
- printk(KERN_DEBUG "Enabling ecan on channel: %d (%s)\n",
- channel, law);
+ vpm_info(vpm, "Enabling ecan on channel: %d (%s)\n",
+ channel, law);
}
res = gpakAlgControl(vpm->dspid, channel, control, &pstatus);
if (res) {
- printk(KERN_WARNING "Unable to set SW Companding on " \
- "channel %d (reason %d)\n", channel, res);
+ vpm_info(vpm, "Unable to set SW Companding on "
+ "channel %d (reason %d)\n", channel, res);
}
res = gpakAlgControl(vpm->dspid, channel, EnableEcanA, &pstatus);
return res;
@@ -246,18 +262,98 @@ static int vpmadt032_disable_ec(struct vpmadt032 *vpm, int channel)
GPAK_AlgControlStat_t pstatus;
if (vpm->options.debug & DEBUG_ECHOCAN)
- printk(KERN_DEBUG "Disabling ecan on channel: %d\n", channel);
+ vpm_info(vpm, "Disabling ecan on channel: %d\n", channel);
res = gpakAlgControl(vpm->dspid, channel, BypassSwCompanding, &pstatus);
if (res) {
- printk(KERN_WARNING "Unable to disable sw companding on " \
- "echo cancellation channel %d (reason %d)\n",
- channel, res);
+ vpm_info(vpm, "Unable to disable sw companding on "
+ "echo cancellation channel %d (reason %d)\n",
+ channel, res);
}
res = gpakAlgControl(vpm->dspid, channel, BypassEcanA, &pstatus);
return res;
}
+static struct change_order *get_next_order(struct vpmadt032 *vpm)
+{
+ struct change_order *order;
+
+ spin_lock(&vpm->change_list_lock);
+ if (!list_empty(&vpm->change_list)) {
+ order = list_entry(vpm->change_list.next,
+ struct change_order, node);
+ list_del(&order->node);
+ } else {
+ order = NULL;
+ }
+ spin_unlock(&vpm->change_list_lock);
+
+ return order;
+}
+
+static int nlp_settings_changed(const struct adt_lec_params *a,
+ const struct adt_lec_params *b)
+{
+ return ((a->nlp_type != b->nlp_type) ||
+ (a->nlp_threshold != b->nlp_threshold) ||
+ (a->nlp_max_suppress != b->nlp_max_suppress));
+}
+
+static int echocan_on(const struct adt_lec_params *new,
+ const struct adt_lec_params *old)
+{
+ return ((new->tap_length != old->tap_length) &&
+ (new->tap_length > 0));
+}
+
+static int echocan_off(const struct adt_lec_params *new,
+ const struct adt_lec_params *old)
+{
+ return ((new->tap_length != old->tap_length) &&
+ (0 == new->tap_length));
+}
+
+static void update_channel_config(struct vpmadt032 *vpm, unsigned int channel,
+ struct adt_lec_params *desired)
+{
+ int res;
+ GPAK_AlgControlStat_t pstatus;
+ GPAK_ChannelConfigStat_t cstatus;
+ GPAK_TearDownChanStat_t tstatus;
+ GpakChannelConfig_t chanconfig;
+
+ if (vpm->options.debug & DEBUG_ECHOCAN) {
+ vpm_info(vpm, "Reconfiguring chan %d for nlp %d, "
+ "nlp_thresh %d, and max_supp %d\n", channel + 1,
+ desired->nlp_type, desired->nlp_threshold,
+ desired->nlp_max_suppress);
+ }
+
+ vpm->setchanconfig_from_state(vpm, channel, &chanconfig);
+
+ res = gpakTearDownChannel(vpm->dspid, channel, &tstatus);
+ if (res)
+ return;
+
+ res = gpakConfigureChannel(vpm->dspid, channel, tdmToTdm,
+ &chanconfig, &cstatus);
+ if (res)
+ return;
+
+ if (!desired->tap_length) {
+ res = gpakAlgControl(vpm->dspid, channel,
+ BypassSwCompanding, &pstatus);
+ if (res) {
+ vpm_info(vpm, "Unable to disable sw companding on "
+ "echo cancellation channel %d (reason %d)\n",
+ channel, res);
+ }
+ gpakAlgControl(vpm->dspid, channel, BypassEcanA, &pstatus);
+ }
+
+ return;
+}
+
/**
* vpmadt032_bh - Changes the echocan parameters on the vpmadt032 module.
*
@@ -275,97 +371,80 @@ static void vpmadt032_bh(struct work_struct *data)
{
struct vpmadt032 *vpm = container_of(data, struct vpmadt032, work);
#endif
- struct adt_lec_params *curstate, *desiredstate;
- int channel;
-
- /* Sweep through all the echo can channels on the VPMADT032 module,
- * looking for ones where the desired state does not match the current
- * state.
- */
- for (channel = 0; channel < vpm->span->channels; channel++) {
- GPAK_AlgControlStat_t pstatus;
- int res = 1;
- curstate = &vpm->curecstate[channel];
- desiredstate = &vpm->desiredecstate[channel];
-
- if ((desiredstate->nlp_type != curstate->nlp_type) ||
- (desiredstate->nlp_threshold != curstate->nlp_threshold) ||
- (desiredstate->nlp_max_suppress != curstate->nlp_max_suppress)) {
-
- GPAK_ChannelConfigStat_t cstatus;
- GPAK_TearDownChanStat_t tstatus;
- GpakChannelConfig_t chanconfig;
-
- if (vpm->options.debug & DEBUG_ECHOCAN)
- printk(KERN_DEBUG "Reconfiguring chan %d for nlp %d, nlp_thresh %d, and max_supp %d\n", channel + 1, vpm->desiredecstate[channel].nlp_type,
- desiredstate->nlp_threshold, desiredstate->nlp_max_suppress);
-
- vpm->setchanconfig_from_state(vpm, channel, &chanconfig);
-
- res = gpakTearDownChannel(vpm->dspid, channel, &tstatus);
- if (res)
- goto vpm_bh_out;
-
- res = gpakConfigureChannel(vpm->dspid, channel, tdmToTdm, &chanconfig, &cstatus);
- if (res)
- goto vpm_bh_out;
-
- if (!desiredstate->tap_length) {
- res = gpakAlgControl(vpm->dspid, channel, BypassSwCompanding, &pstatus);
- if (res)
- printk("Unable to disable sw companding on echo cancellation channel %d (reason %d)\n", channel, res);
- res = gpakAlgControl(vpm->dspid, channel, BypassEcanA, &pstatus);
- }
+ struct change_order *order;
- } else if (desiredstate->tap_length != curstate->tap_length) {
- if (desiredstate->tap_length)
- res = vpmadt032_enable_ec(vpm, channel);
- else
- res = vpmadt032_disable_ec(vpm, channel);
- }
-vpm_bh_out:
- if (!res)
- *curstate = *desiredstate;
+ while ((order = get_next_order(vpm))) {
+
+ struct adt_lec_params *old;
+ struct adt_lec_params *new;
+ unsigned int channel;
+
+ channel = order->channel;
+ BUG_ON(channel >= ARRAY_SIZE(vpm->curecstate));
+ old = &vpm->curecstate[channel];
+ new = &order->params;
+
+ if (nlp_settings_changed(new, old))
+ update_channel_config(vpm, channel, new);
+ else if (echocan_on(new, old))
+ vpmadt032_enable_ec(vpm, channel, new->companding);
+ else if (echocan_off(new, old))
+ vpmadt032_disable_ec(vpm, channel);
+
+ *old = order->params;
+ free_change_order(order);
}
- return;
}
+
#include "adt_lec.c"
-static void vpmadt032_check_and_schedule_update(struct vpmadt032 *vpm, int channo)
-{
- int update;
- /* Only update the parameters if the new state of the echo canceller
- * is different than the current state. */
- update = memcmp(&vpm->curecstate[channo],
- &vpm->desiredecstate[channo],
- sizeof(vpm->curecstate[channo]));
- if (update && test_bit(VPM150M_ACTIVE, &vpm->control)) {
- /* Since updating the parameters can take a bit of time while
- * the driver sends messages to the VPMADT032 and waits for
- * their responses, we'll push the work of updating the
- * parameters to a work queue so the caller can continue to
- * proceed with setting up the call.
- */
- queue_work(vpm->wq, &vpm->work);
+static void vpmadt032_check_and_schedule_update(struct vpmadt032 *vpm,
+ struct change_order *order)
+{
+ struct change_order *cur;
+ struct change_order *n;
+
+ INIT_LIST_HEAD(&order->node);
+ spin_lock(&vpm->change_list_lock);
+ list_for_each_entry_safe(cur, n, &vpm->change_list, node) {
+ if (cur->channel == order->channel) {
+ list_replace(&cur->node, &order->node);
+ free_change_order(cur);
+ break;
+ }
}
+ if (list_empty(&order->node))
+ list_add_tail(&order->node, &vpm->change_list);
+ spin_unlock(&vpm->change_list_lock);
+
+ queue_work(vpm->wq, &vpm->work);
}
int vpmadt032_echocan_create(struct vpmadt032 *vpm, int channo,
struct dahdi_echocanparams *ecp, struct dahdi_echocanparam *p)
{
unsigned int ret;
+ struct change_order *order = alloc_change_order();
+ if (!order)
+ return -ENOMEM;
- ret = adt_lec_parse_params(&vpm->desiredecstate[channo], ecp, p);
- if (ret)
+ memcpy(&order->params, &vpm->curecstate[channo], sizeof(order->params));
+ ret = adt_lec_parse_params(&order->params, ecp, p);
+ if (ret) {
+ free_change_order(order);
return ret;
+ }
- if (vpm->options.debug & DEBUG_ECHOCAN)
- printk(KERN_DEBUG "echocan: Channel is %d length %d\n", channo, ecp->tap_length);
+ if (vpm->options.debug & DEBUG_ECHOCAN) {
+ vpm_info(vpm, "Channel is %d length %d\n",
+ channo, ecp->tap_length);
+ }
/* The driver cannot control the number of taps on the VPMADT032
* module. Instead, it uses tap_length to enable or disable the echo
* cancellation. */
- vpm->desiredecstate[channo].tap_length = (ecp->tap_length) ? 1 : 0;
+ order->params.tap_length = (ecp->tap_length) ? 1 : 0;
+ order->channel = channo;
- vpmadt032_check_and_schedule_update(vpm, channo);
+ vpmadt032_check_and_schedule_update(vpm, order);
return 0;
}
EXPORT_SYMBOL(vpmadt032_echocan_create);
@@ -373,15 +452,22 @@ EXPORT_SYMBOL(vpmadt032_echocan_create);
void vpmadt032_echocan_free(struct vpmadt032 *vpm, int channo,
struct dahdi_echocan_state *ec)
{
- adt_lec_init_defaults(&vpm->desiredecstate[channo], 0);
- vpm->desiredecstate[channo].nlp_type = vpm->options.vpmnlptype;
- vpm->desiredecstate[channo].nlp_threshold = vpm->options.vpmnlpthresh;
- vpm->desiredecstate[channo].nlp_max_suppress = vpm->options.vpmnlpmaxsupp;
+ struct change_order *order;
+ order = alloc_change_order();
+ WARN_ON(!order);
+ if (!order)
+ return;
+
+ adt_lec_init_defaults(&order->params, 0);
+ order->params.nlp_type = vpm->options.vpmnlptype;
+ order->params.nlp_threshold = vpm->options.vpmnlpthresh;
+ order->params.nlp_max_suppress = vpm->options.vpmnlpmaxsupp;
+ order->channel = channo;
if (vpm->options.debug & DEBUG_ECHOCAN)
- printk(KERN_DEBUG "echocan: Channel is %d length 0\n", channo);
+ vpm_info(vpm, "Channel is %d length 0\n", channo);
- vpmadt032_check_and_schedule_update(vpm, channo);
+ vpmadt032_check_and_schedule_update(vpm, order);
}
EXPORT_SYMBOL(vpmadt032_echocan_free);
@@ -413,6 +499,8 @@ vpmadt032_alloc(struct vpmadt032_options *options, const char *board_name)
/* Init our vpmadt032 struct */
memcpy(&vpm->options, options, sizeof(*options));
spin_lock_init(&vpm->list_lock);
+ spin_lock_init(&vpm->change_list_lock);
+ INIT_LIST_HEAD(&vpm->change_list);
INIT_LIST_HEAD(&vpm->free_cmds);
INIT_LIST_HEAD(&vpm->pending_cmds);
INIT_LIST_HEAD(&vpm->active_cmds);
@@ -446,8 +534,6 @@ vpmadt032_alloc(struct vpmadt032_options *options, const char *board_name)
kfree(vpm);
printk(KERN_NOTICE "Unable to initialize another vpmadt032 modules\n");
vpm = NULL;
- } else if (vpm->options.debug & DEBUG_ECHOCAN) {
- printk(KERN_DEBUG "Setting VPMADT032 DSP ID to %d\n", vpm->dspid);
}
return vpm;
@@ -464,6 +550,9 @@ vpmadt032_init(struct vpmadt032 *vpm, struct voicebus *vb)
BUG_ON(!vpm->setchanconfig_from_state);
BUG_ON(!vpm->wq);
+ BUG_ON(!vb);
+
+ vpm->vb = vb;
might_sleep();
@@ -583,6 +672,7 @@ void vpmadt032_free(struct vpmadt032 *vpm)
{
unsigned long flags;
struct vpmadt032_cmd *cmd;
+ struct change_order *order;
LIST_HEAD(local_list);
BUG_ON(!vpm);
@@ -603,6 +693,16 @@ void vpmadt032_free(struct vpmadt032 *vpm)
kfree(cmd);
}
+ spin_lock(&vpm->change_list_lock);
+ list_splice(&vpm->change_list, &local_list);
+ spin_unlock(&vpm->change_list_lock);
+
+ while (!list_empty(&local_list)) {
+ order = list_entry(local_list.next, struct change_order, node);
+ list_del(&order->node);
+ kfree(order);
+ }
+
BUG_ON(ifaces[vpm->dspid] != vpm);
write_lock(&ifacelock);
ifaces[vpm->dspid] = NULL;
diff --git a/drivers/dahdi/voicebus/GpakCust.h b/drivers/dahdi/voicebus/GpakCust.h
index 0546bfb..3a493e1 100644
--- a/drivers/dahdi/voicebus/GpakCust.h
+++ b/drivers/dahdi/voicebus/GpakCust.h
@@ -105,10 +105,8 @@ struct vpmadt032_options {
struct GpakChannelConfig;
-#define MAX_CHANNELS_PER_SPAN 32
struct vpmadt032 {
- void *context;
- const struct dahdi_span *span;
+ struct voicebus *vb;
struct work_struct work;
struct workqueue_struct *wq;
int dspid;
@@ -116,8 +114,10 @@ struct vpmadt032 {
unsigned long control;
unsigned char curpage;
unsigned short version;
- struct adt_lec_params curecstate[MAX_CHANNELS_PER_SPAN];
- struct adt_lec_params desiredecstate[MAX_CHANNELS_PER_SPAN];
+ enum adt_companding companding;
+ struct adt_lec_params curecstate[MAX_CHANNELS];
+ spinlock_t change_list_lock;
+ struct list_head change_list;
spinlock_t list_lock;
/* Commands that are ready to be used. */
struct list_head free_cmds;
@@ -125,7 +125,6 @@ struct vpmadt032 {
struct list_head pending_cmds;
/* Commands that are currently in progress by the VPM module */
struct list_head active_cmds;
- unsigned char curtone[MAX_CHANNELS_PER_SPAN];
struct vpmadt032_options options;
void (*setchanconfig_from_state)(struct vpmadt032 *vpm, int channel, struct GpakChannelConfig *chanconfig);
/* This must be last */
diff --git a/drivers/dahdi/wctdm24xxp/base.c b/drivers/dahdi/wctdm24xxp/base.c
index 1386e5f..70aa969 100644
--- a/drivers/dahdi/wctdm24xxp/base.c
+++ b/drivers/dahdi/wctdm24xxp/base.c
@@ -312,18 +312,8 @@ void setchanconfig_from_state(struct vpmadt032 *vpm, int channel, GpakChannelCon
chanconfig->MuteToneB = Disabled;
chanconfig->FaxCngDetB = Disabled;
- switch (vpm->span->deflaw) {
- case DAHDI_LAW_MULAW:
- chanconfig->SoftwareCompand = cmpPCMU;
- break;
- case DAHDI_LAW_ALAW:
- chanconfig->SoftwareCompand = cmpPCMA;
- break;
- default:
- chanconfig->SoftwareCompand = cmpPCMU;
- break;
- }
-
+ chanconfig->SoftwareCompand = (ADT_COMP_ALAW == vpm->companding) ?
+ cmpPCMA : cmpPCMU;
chanconfig->FrameRate = rate2ms;
p = &chanconfig->EcanParametersA;
@@ -338,7 +328,7 @@ void setchanconfig_from_state(struct vpmadt032 *vpm, int channel, GpakChannelCon
sizeof(chanconfig->EcanParametersB));
}
-static int config_vpmadt032(struct vpmadt032 *vpm)
+static int config_vpmadt032(struct vpmadt032 *vpm, struct wctdm *wc)
{
int res, i;
GpakPortConfig_t portconfig = {0};
@@ -427,12 +417,12 @@ static int config_vpmadt032(struct vpmadt032 *vpm)
return -1;
}
- for (i = 0; i < vpm->span->channels; ++i) {
+ for (i = 0; i < vpm->options.channels; ++i) {
vpm->curecstate[i].tap_length = 0;
vpm->curecstate[i].nlp_type = vpm->options.vpmnlptype;
vpm->curecstate[i].nlp_threshold = vpm->options.vpmnlpthresh;
vpm->curecstate[i].nlp_max_suppress = vpm->options.vpmnlpmaxsupp;
- memcpy(&vpm->desiredecstate[i], &vpm->curecstate[i], sizeof(vpm->curecstate[i]));
+ vpm->curecstate[i].companding = (wc->span.deflaw == DAHDI_LAW_MULAW) ? ADT_COMP_ULAW : ADT_COMP_ALAW;
/* set_vpmadt032_chanconfig_from_state(&vpm->curecstate[i], &vpm->options, i, &chanconfig); !!! */
vpm->setchanconfig_from_state(vpm, i, &chanconfig);
@@ -449,6 +439,11 @@ static int config_vpmadt032(struct vpmadt032 *vpm)
printk(KERN_NOTICE "Unable to disable echo can on channel %d (reason %d:%d)\n", i + 1, res, algstatus);
return -1;
}
+
+ if ((res = gpakAlgControl(vpm->dspid, i, BypassSwCompanding, &algstatus))) {
+ printk(KERN_NOTICE "Unable to disable echo can on channel %d (reason %d:%d)\n", i + 1, res, algstatus);
+ return -1;
+ }
}
if ((res = gpakPingDsp(vpm->dspid, &vpm->version))) {
@@ -567,11 +562,6 @@ static inline void cmd_dequeue_vpmadt032(struct wctdm *wc, u8 *writechunk, int w
for (x = 24; x < 28; x++) {
writechunk[CMD_BYTE(x, 0, 0)] |= leds;
}
-
- /* Now let's figure out if we need to check for DTMF */
- if (test_bit(VPM150M_ACTIVE, &vpmadt032->control) && !whichframe && !(wc->intcount % 100)) {
- schedule_work(&vpmadt032->work);
- }
}
static inline void cmd_dequeue(struct wctdm *wc, unsigned char *writechunk, int card, int pos)
@@ -3677,8 +3667,7 @@ retry:
return -ENOMEM;
wc->vpmadt032->setchanconfig_from_state = setchanconfig_from_state;
- wc->vpmadt032->context = wc;
- wc->vpmadt032->span = &wc->span;
+ wc->vpmadt032->options.channels = wc->span.channels;
get_default_portconfig(&portconfig);
res = vpmadt032_init(wc->vpmadt032, wc->vb);
if (res) {
@@ -3689,7 +3678,7 @@ retry:
/* Now we need to configure the VPMADT032 module for this
* particular board. */
- res = config_vpmadt032(wc->vpmadt032);
+ res = config_vpmadt032(wc->vpmadt032, wc);
if (res) {
vpmadt032_free(wc->vpmadt032);
wc->vpmadt032 = NULL;
diff --git a/drivers/dahdi/wcte12xp/base.c b/drivers/dahdi/wcte12xp/base.c
index c4856ca..ae9c975 100644
--- a/drivers/dahdi/wcte12xp/base.c
+++ b/drivers/dahdi/wcte12xp/base.c
@@ -260,7 +260,7 @@ inline void cmd_decipher_vpmadt032(struct t1 *wc, unsigned char *readchunk)
}
}
-static int config_vpmadt032(struct vpmadt032 *vpm)
+static int config_vpmadt032(struct vpmadt032 *vpm, struct t1 *wc)
{
int res, channel;
GpakPortConfig_t portconfig = {0};
@@ -349,12 +349,12 @@ static int config_vpmadt032(struct vpmadt032 *vpm)
return -1;
}
- for (channel = 0; channel < MAX_CHANNELS_PER_SPAN; ++channel) {
+ for (channel = 0; channel < ARRAY_SIZE(vpm->curecstate); ++channel) {
vpm->curecstate[channel].tap_length = 0;
vpm->curecstate[channel].nlp_type = vpm->options.vpmnlptype;
vpm->curecstate[channel].nlp_threshold = vpm->options.vpmnlpthresh;
vpm->curecstate[channel].nlp_max_suppress = vpm->options.vpmnlpmaxsupp;
- memcpy(&vpm->desiredecstate[channel], &vpm->curecstate[channel], sizeof(vpm->curecstate[channel]));
+ vpm->curecstate[channel].companding = (wc->spantype == TYPE_T1) ? ADT_COMP_ULAW : ADT_COMP_ALAW;
vpm->setchanconfig_from_state(vpm, channel, &chanconfig);
if ((res = gpakConfigureChannel(vpm->dspid, channel, tdmToTdm, &chanconfig, &cstatus))) {
@@ -528,11 +528,6 @@ static void cmd_dequeue_vpmadt032(struct t1 *wc, unsigned char *writechunk, int
}
#endif
- /* Now let's figure out if we need to check for DTMF */
- /* polling */
- if (test_bit(VPM150M_ACTIVE, &vpm->control) && !whichframe && !(atomic_read(&wc->txints) % 100))
- schedule_work(&vpm->work);
-
#if 0
/* This may be needed sometime in the future to troubleshoot ADT related issues. */
if (test_bit(VPM150M_ACTIVE, &vpm->control) && !whichframe && !(atomic_read(&wc->txints) % 10000))
@@ -1313,7 +1308,7 @@ static void setchanconfig_from_state(struct vpmadt032 *vpm, int channel, GpakCha
chanconfig->PcmInPortA = 3;
chanconfig->PcmInSlotA = (channel + 1) * 2;
- chanconfig->PcmOutPortA = 2;
+ chanconfig->PcmOutPortA = SerialPortNull;
chanconfig->PcmOutSlotA = (channel + 1) * 2;
chanconfig->PcmInPortB = 2;
chanconfig->PcmInSlotB = (channel + 1) * 2;
@@ -1388,14 +1383,13 @@ static int t1_hardware_post_init(struct t1 *wc)
options.vpmnlptype = vpmnlptype;
options.vpmnlpthresh = vpmnlpthresh;
options.vpmnlpmaxsupp = vpmnlpmaxsupp;
+ options.channels = (wc->spantype == TYPE_T1) ? 24 : 32;
wc->vpmadt032 = vpmadt032_alloc(&options, wc->name);
if (!wc->vpmadt032)
return -ENOMEM;
- wc->vpmadt032->context = wc;
wc->vpmadt032->setchanconfig_from_state = setchanconfig_from_state;
- wc->vpmadt032->span = &wc->span;
res = vpmadt032_init(wc->vpmadt032, wc->vb);
if (res) {
@@ -1404,7 +1398,7 @@ static int t1_hardware_post_init(struct t1 *wc)
return -EIO;
}
- config_vpmadt032(wc->vpmadt032);
+ config_vpmadt032(wc->vpmadt032, wc);
set_span_devicetype(wc);
module_printk("VPM present and operational (Firmware version %x)\n", wc->vpmadt032->version);
diff --git a/include/dahdi/kernel.h b/include/dahdi/kernel.h
index 6058779..c07b45a 100644
--- a/include/dahdi/kernel.h
+++ b/include/dahdi/kernel.h
@@ -1172,6 +1172,16 @@ static inline short dahdi_txtone_nextsample(struct dahdi_chan *ss)
#define kzalloc(a, b) kcalloc(1, a, b)
#endif
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 18)
+static inline void list_replace(struct list_head *old, struct list_head *new)
+{
+ new->next = old->next;
+ new->next->prev = new;
+ new->prev = old->prev;
+ new->prev->next = new;
+}
+#endif
+
#ifndef DMA_BIT_MASK
#define DMA_BIT_MASK(n) (((n) == 64) ? ~0ULL : ((1ULL<<(n))-1))
#endif