xref: /linux/drivers/isdn/mISDN/dsp_hwec.c (revision 58e16d792a6a8c6b750f637a4649967fcac853dc)
1*9e567af4SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-or-later
2960366cfSKarsten Keil /*
3960366cfSKarsten Keil  * dsp_hwec.c:
4960366cfSKarsten Keil  * builtin mISDN dsp pipeline element for enabling the hw echocanceller
5960366cfSKarsten Keil  *
6960366cfSKarsten Keil  * Copyright (C) 2007, Nadi Sarrar
7960366cfSKarsten Keil  *
8960366cfSKarsten Keil  * Nadi Sarrar <nadi@beronet.com>
9960366cfSKarsten Keil  */
10960366cfSKarsten Keil 
11960366cfSKarsten Keil #include <linux/kernel.h>
12960366cfSKarsten Keil #include <linux/string.h>
13960366cfSKarsten Keil #include <linux/mISDNdsp.h>
14960366cfSKarsten Keil #include <linux/mISDNif.h>
15960366cfSKarsten Keil #include "core.h"
16960366cfSKarsten Keil #include "dsp.h"
17960366cfSKarsten Keil #include "dsp_hwec.h"
18960366cfSKarsten Keil 
19960366cfSKarsten Keil static struct mISDN_dsp_element_arg args[] = {
20960366cfSKarsten Keil 	{ "deftaps", "128", "Set the number of taps of cancellation." },
21960366cfSKarsten Keil };
22960366cfSKarsten Keil 
23960366cfSKarsten Keil static struct mISDN_dsp_element dsp_hwec_p = {
24960366cfSKarsten Keil 	.name = "hwec",
25960366cfSKarsten Keil 	.new = NULL,
26960366cfSKarsten Keil 	.free = NULL,
27960366cfSKarsten Keil 	.process_tx = NULL,
28960366cfSKarsten Keil 	.process_rx = NULL,
29fd568fc3SJulia Lawall 	.num_args = ARRAY_SIZE(args),
30960366cfSKarsten Keil 	.args = args,
31960366cfSKarsten Keil };
32960366cfSKarsten Keil struct mISDN_dsp_element *dsp_hwec = &dsp_hwec_p;
33960366cfSKarsten Keil 
dsp_hwec_enable(struct dsp * dsp,const char * arg)34960366cfSKarsten Keil void dsp_hwec_enable(struct dsp *dsp, const char *arg)
35960366cfSKarsten Keil {
36960366cfSKarsten Keil 	int deftaps = 128,
37960366cfSKarsten Keil 		len;
38960366cfSKarsten Keil 	struct mISDN_ctrl_req	cq;
39960366cfSKarsten Keil 
40960366cfSKarsten Keil 	if (!dsp) {
41960366cfSKarsten Keil 		printk(KERN_ERR "%s: failed to enable hwec: dsp is NULL\n",
42960366cfSKarsten Keil 		       __func__);
43960366cfSKarsten Keil 		return;
44960366cfSKarsten Keil 	}
45960366cfSKarsten Keil 
46960366cfSKarsten Keil 	if (!arg)
47960366cfSKarsten Keil 		goto _do;
48960366cfSKarsten Keil 
49960366cfSKarsten Keil 	len = strlen(arg);
50960366cfSKarsten Keil 	if (!len)
51960366cfSKarsten Keil 		goto _do;
52960366cfSKarsten Keil 
53960366cfSKarsten Keil 	{
54960366cfSKarsten Keil 		char *dup, *tok, *name, *val;
55960366cfSKarsten Keil 		int tmp;
56960366cfSKarsten Keil 
579a438161SLaura Abbott 		dup = kstrdup(arg, GFP_ATOMIC);
589a438161SLaura Abbott 		if (!dup)
599a438161SLaura Abbott 			return;
60960366cfSKarsten Keil 
61960366cfSKarsten Keil 		while ((tok = strsep(&dup, ","))) {
62960366cfSKarsten Keil 			if (!strlen(tok))
63960366cfSKarsten Keil 				continue;
64960366cfSKarsten Keil 			name = strsep(&tok, "=");
65960366cfSKarsten Keil 			val = tok;
66960366cfSKarsten Keil 
67960366cfSKarsten Keil 			if (!val)
68960366cfSKarsten Keil 				continue;
69960366cfSKarsten Keil 
70960366cfSKarsten Keil 			if (!strcmp(name, "deftaps")) {
71960366cfSKarsten Keil 				if (sscanf(val, "%d", &tmp) == 1)
72960366cfSKarsten Keil 					deftaps = tmp;
73960366cfSKarsten Keil 			}
74960366cfSKarsten Keil 		}
759a438161SLaura Abbott 
769a438161SLaura Abbott 		kfree(dup);
77960366cfSKarsten Keil 	}
78960366cfSKarsten Keil 
79960366cfSKarsten Keil _do:
80960366cfSKarsten Keil 	printk(KERN_DEBUG "%s: enabling hwec with deftaps=%d\n",
81960366cfSKarsten Keil 	       __func__, deftaps);
82960366cfSKarsten Keil 	memset(&cq, 0, sizeof(cq));
83960366cfSKarsten Keil 	cq.op = MISDN_CTRL_HFC_ECHOCAN_ON;
84960366cfSKarsten Keil 	cq.p1 = deftaps;
85960366cfSKarsten Keil 	if (!dsp->ch.peer->ctrl(&dsp->ch, CONTROL_CHANNEL, &cq)) {
86960366cfSKarsten Keil 		printk(KERN_DEBUG "%s: CONTROL_CHANNEL failed\n",
87960366cfSKarsten Keil 		       __func__);
88960366cfSKarsten Keil 		return;
89960366cfSKarsten Keil 	}
90960366cfSKarsten Keil }
91960366cfSKarsten Keil 
dsp_hwec_disable(struct dsp * dsp)92960366cfSKarsten Keil void dsp_hwec_disable(struct dsp *dsp)
93960366cfSKarsten Keil {
94960366cfSKarsten Keil 	struct mISDN_ctrl_req	cq;
95960366cfSKarsten Keil 
96960366cfSKarsten Keil 	if (!dsp) {
97960366cfSKarsten Keil 		printk(KERN_ERR "%s: failed to disable hwec: dsp is NULL\n",
98960366cfSKarsten Keil 		       __func__);
99960366cfSKarsten Keil 		return;
100960366cfSKarsten Keil 	}
101960366cfSKarsten Keil 
102960366cfSKarsten Keil 	printk(KERN_DEBUG "%s: disabling hwec\n", __func__);
103960366cfSKarsten Keil 	memset(&cq, 0, sizeof(cq));
104960366cfSKarsten Keil 	cq.op = MISDN_CTRL_HFC_ECHOCAN_OFF;
105960366cfSKarsten Keil 	if (!dsp->ch.peer->ctrl(&dsp->ch, CONTROL_CHANNEL, &cq)) {
106960366cfSKarsten Keil 		printk(KERN_DEBUG "%s: CONTROL_CHANNEL failed\n",
107960366cfSKarsten Keil 		       __func__);
108960366cfSKarsten Keil 		return;
109960366cfSKarsten Keil 	}
110960366cfSKarsten Keil }
111960366cfSKarsten Keil 
dsp_hwec_init(void)112960366cfSKarsten Keil int dsp_hwec_init(void)
113960366cfSKarsten Keil {
114960366cfSKarsten Keil 	mISDN_dsp_element_register(dsp_hwec);
115960366cfSKarsten Keil 
116960366cfSKarsten Keil 	return 0;
117960366cfSKarsten Keil }
118960366cfSKarsten Keil 
dsp_hwec_exit(void)119960366cfSKarsten Keil void dsp_hwec_exit(void)
120960366cfSKarsten Keil {
121960366cfSKarsten Keil 	mISDN_dsp_element_unregister(dsp_hwec);
122960366cfSKarsten Keil }
123