^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0-or-later
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * dsp_hwec.c:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) * builtin mISDN dsp pipeline element for enabling the hw echocanceller
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) * Copyright (C) 2007, Nadi Sarrar
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) * Nadi Sarrar <nadi@beronet.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) #include <linux/kernel.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) #include <linux/string.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #include <linux/mISDNdsp.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #include <linux/mISDNif.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) #include "core.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) #include "dsp.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) #include "dsp_hwec.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) static struct mISDN_dsp_element_arg args[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) { "deftaps", "128", "Set the number of taps of cancellation." },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) static struct mISDN_dsp_element dsp_hwec_p = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) .name = "hwec",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) .new = NULL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) .free = NULL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) .process_tx = NULL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) .process_rx = NULL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) .num_args = ARRAY_SIZE(args),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) .args = args,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) struct mISDN_dsp_element *dsp_hwec = &dsp_hwec_p;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) void dsp_hwec_enable(struct dsp *dsp, const char *arg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) int deftaps = 128,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) struct mISDN_ctrl_req cq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) if (!dsp) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) printk(KERN_ERR "%s: failed to enable hwec: dsp is NULL\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) if (!arg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) goto _do;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) len = strlen(arg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) if (!len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) goto _do;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) char *dup, *tok, *name, *val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) int tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) dup = kstrdup(arg, GFP_ATOMIC);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) if (!dup)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) while ((tok = strsep(&dup, ","))) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) if (!strlen(tok))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) name = strsep(&tok, "=");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) val = tok;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) if (!val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) if (!strcmp(name, "deftaps")) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) if (sscanf(val, "%d", &tmp) == 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) deftaps = tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) kfree(dup);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) _do:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) printk(KERN_DEBUG "%s: enabling hwec with deftaps=%d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) __func__, deftaps);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) memset(&cq, 0, sizeof(cq));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) cq.op = MISDN_CTRL_HFC_ECHOCAN_ON;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) cq.p1 = deftaps;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) if (!dsp->ch.peer->ctrl(&dsp->ch, CONTROL_CHANNEL, &cq)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) printk(KERN_DEBUG "%s: CONTROL_CHANNEL failed\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) void dsp_hwec_disable(struct dsp *dsp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) struct mISDN_ctrl_req cq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) if (!dsp) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) printk(KERN_ERR "%s: failed to disable hwec: dsp is NULL\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) printk(KERN_DEBUG "%s: disabling hwec\n", __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) memset(&cq, 0, sizeof(cq));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) cq.op = MISDN_CTRL_HFC_ECHOCAN_OFF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) if (!dsp->ch.peer->ctrl(&dsp->ch, CONTROL_CHANNEL, &cq)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) printk(KERN_DEBUG "%s: CONTROL_CHANNEL failed\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) int dsp_hwec_init(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) mISDN_dsp_element_register(dsp_hwec);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) void dsp_hwec_exit(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) mISDN_dsp_element_unregister(dsp_hwec);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) }