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