Skip to content

Commit 08754de

Browse files
ranj063kv2019i
authored andcommitted
plugin: alsaplug: Add kcontrol set up callback
Define the callback for setting up kcontrols in the plugin. Add a few new fields in struct plug_shm_ctl to store the module info and the volume table for converting mixer values to linear volume gain. Signed-off-by: Ranjani Sridharan <ranjani.sridharan@linux.intel.com>
1 parent 58465b8 commit 08754de

8 files changed

Lines changed: 214 additions & 98 deletions

File tree

tools/plugin/README.md

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -70,11 +70,16 @@ arecord -Dsof:plugin:1:default:default:48k2c16b -f dat file.wav
7070
```
7171
Will record audio using the plugin topology and PCM ID 1.
7272

73-
Mixer settings can be adjusted for sof-plugin by (Not functional yet)
73+
Mixer settings can be adjusted for sof-plugin by
7474

7575
```
76-
alsamixer -Dsof:sof-plugin:1
76+
alsamixer -Dsof:plugin
7777
```
78+
or
79+
```
80+
amixer -Dsof:plugin cset numid=1 20
81+
```
82+
Right now, only volume controls are supported. Support for bytes and enum controls is pending.
7883

7984
# Instructions for testing OpenVino noise suppression model with the SOF plugin:
8085
1. Fetch the model from the Open Model zoo repository ex: noise-suppression-poconetlike-0001.xml

tools/plugin/alsaplug/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ add_library(asound_module_pcm_sof MODULE
66
plugin.c
77
../common.c
88
tplg.c
9+
tplg_ctl.c
910
)
1011

1112
sof_append_relative_path_definitions(asound_module_pcm_sof)

tools/plugin/alsaplug/plugin.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,5 +64,6 @@ int plug_parse_topology(snd_sof_plug_t *plug);
6464
int plug_set_up_pipelines(snd_sof_plug_t *plug, int dir);
6565
int plug_free_pipelines(snd_sof_plug_t *plug, struct tplg_pipeline_list *pipeline_list, int dir);
6666
void plug_free_topology(snd_sof_plug_t *plug);
67+
int plug_kcontrol_cb_new(struct snd_soc_tplg_ctl_hdr *tplg_ctl, void *_comp, void *arg);
6768

6869
#endif

tools/plugin/alsaplug/tplg.c

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -750,9 +750,8 @@ int plug_parse_topology(snd_sof_plug_t *plug)
750750

751751
tplg_debug("parsing topology file %s\n", ctx->tplg_file);
752752

753-
/* TODO: ctl callback */
754-
// ctx->ctl_arg = sp;
755-
// ctx->ctl_cb = pipe_kcontrol_cb_new;
753+
ctx->ctl_arg = plug;
754+
ctx->ctl_cb = plug_kcontrol_cb_new;
756755

757756
/* open topology file */
758757
file = fopen(ctx->tplg_file, "rb");

tools/plugin/alsaplug/tplg_ctl.c

Lines changed: 199 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,199 @@
1+
// SPDX-License-Identifier: BSD-3-Clause
2+
//
3+
// Copyright(c) 2024 Intel Corporation. All rights reserved.
4+
//
5+
6+
/* SOF topology kcontrols */
7+
8+
#include <stdio.h>
9+
#include <sys/poll.h>
10+
#include <string.h>
11+
#include <sys/types.h>
12+
#include <unistd.h>
13+
#include <stdlib.h>
14+
#include <sys/wait.h>
15+
#include <sys/stat.h>
16+
#include <mqueue.h>
17+
#include <fcntl.h>
18+
#include <sys/mman.h>
19+
#include <semaphore.h>
20+
#include <assert.h>
21+
#include <errno.h>
22+
#include <math.h>
23+
24+
#include <alsa/asoundlib.h>
25+
#include <alsa/pcm_external.h>
26+
27+
#include <rtos/sof.h>
28+
#include <sof/audio/pipeline.h>
29+
#include <sof/audio/component.h>
30+
#include <ipc/stream.h>
31+
#include <tplg_parser/topology.h>
32+
33+
#include "plugin.h"
34+
#include "common.h"
35+
36+
#define SOF_IPC4_VOL_ZERO_DB 0x7fffffff
37+
#define VOLUME_FWL 16
38+
/*
39+
* Constants used in the computation of linear volume gain
40+
* from dB gain 20th root of 10 in Q1.16 fixed-point notation
41+
*/
42+
#define VOL_TWENTIETH_ROOT_OF_TEN 73533
43+
/* 40th root of 10 in Q1.16 fixed-point notation*/
44+
#define VOL_FORTIETH_ROOT_OF_TEN 69419
45+
46+
/* 0.5 dB step value in topology TLV */
47+
#define VOL_HALF_DB_STEP 50
48+
49+
/*
50+
* Function to truncate an unsigned 64-bit number
51+
* by x bits and return 32-bit unsigned number. This
52+
* function also takes care of rounding while truncating
53+
*/
54+
static uint32_t vol_shift_64(uint64_t i, uint32_t x)
55+
{
56+
if (x == 0)
57+
return (uint32_t)i;
58+
59+
/* do not truncate more than 32 bits */
60+
if (x > 32)
61+
x = 32;
62+
63+
return (uint32_t)(((i >> (x - 1)) + 1) >> 1);
64+
}
65+
66+
/*
67+
* Function to compute a ** exp where,
68+
* a is a fractional number represented by a fixed-point integer with a fractional word length
69+
* of "fwl"
70+
* exp is an integer
71+
* fwl is the fractional word length
72+
* Return value is a fractional number represented by a fixed-point integer with a fractional
73+
* word length of "fwl"
74+
*/
75+
static uint32_t vol_pow32(uint32_t a, int exp, uint32_t fwl)
76+
{
77+
int i, iter;
78+
uint32_t power = 1 << fwl;
79+
unsigned long long numerator;
80+
81+
/* if exponent is 0, return 1 */
82+
if (exp == 0)
83+
return power;
84+
85+
/* determine the number of iterations based on the exponent */
86+
if (exp < 0)
87+
iter = exp * -1;
88+
else
89+
iter = exp;
90+
91+
/* multiply a "iter" times to compute power */
92+
for (i = 0; i < iter; i++) {
93+
/*
94+
* Product of 2 Qx.fwl fixed-point numbers yields a Q2*x.2*fwl
95+
* Truncate product back to fwl fractional bits with rounding
96+
*/
97+
power = vol_shift_64((uint64_t)power * a, fwl);
98+
}
99+
100+
if (exp > 0) {
101+
/* if exp is positive, return the result */
102+
return power;
103+
}
104+
105+
/* if exp is negative, return the multiplicative inverse */
106+
numerator = (uint64_t)1 << (fwl << 1);
107+
numerator /= power;
108+
109+
return (uint32_t)numerator;
110+
}
111+
112+
/*
113+
* Function to calculate volume gain from TLV data.
114+
* This function can only handle gain steps that are multiples of 0.5 dB
115+
*/
116+
static uint32_t vol_compute_gain(uint32_t value, struct snd_soc_tplg_tlv_dbscale *scale)
117+
{
118+
int dB_gain;
119+
uint32_t linear_gain;
120+
int f_step;
121+
122+
/* mute volume */
123+
if (value == 0 && scale->mute)
124+
return 0;
125+
126+
/* compute dB gain from tlv. tlv_step in topology is multiplied by 100 */
127+
dB_gain = (int)scale->min / 100 + (value * scale->step) / 100;
128+
129+
/* compute linear gain represented by fixed-point int with VOLUME_FWL fractional bits */
130+
linear_gain = vol_pow32(VOL_TWENTIETH_ROOT_OF_TEN, dB_gain, VOLUME_FWL);
131+
132+
/* extract the fractional part of volume step */
133+
f_step = scale->step - (scale->step / 100);
134+
135+
/* if volume step is an odd multiple of 0.5 dB */
136+
if (f_step == VOL_HALF_DB_STEP && (value & 1))
137+
linear_gain = vol_shift_64((uint64_t)linear_gain * VOL_FORTIETH_ROOT_OF_TEN,
138+
VOLUME_FWL);
139+
140+
return linear_gain;
141+
}
142+
143+
/* helper function to add new kcontrols to the list of kcontrols in the global context */
144+
int plug_kcontrol_cb_new(struct snd_soc_tplg_ctl_hdr *tplg_ctl, void *_comp, void *arg)
145+
{
146+
snd_sof_plug_t *plug = arg;
147+
struct plug_shm_glb_state *glb = plug->glb_ctx.addr;
148+
struct plug_shm_ctl *ctl;
149+
150+
if (glb->num_ctls >= MAX_CTLS) {
151+
SNDERR("Failed to add a new control. Too many controls already\n");
152+
return -EINVAL;
153+
}
154+
155+
switch (tplg_ctl->type) {
156+
case SND_SOC_TPLG_CTL_VOLSW:
157+
case SND_SOC_TPLG_CTL_VOLSW_SX:
158+
case SND_SOC_TPLG_CTL_VOLSW_XR_SX:
159+
{
160+
struct snd_soc_tplg_mixer_control *tplg_mixer =
161+
(struct snd_soc_tplg_mixer_control *)tplg_ctl;
162+
struct tplg_comp_info *comp_info = _comp;
163+
struct snd_soc_tplg_ctl_tlv *tlv;
164+
struct snd_soc_tplg_tlv_dbscale *scale;
165+
int i;
166+
167+
glb->size += sizeof(struct plug_shm_ctl);
168+
ctl = &glb->ctl[glb->num_ctls++];
169+
ctl->module_id = comp_info->module_id;
170+
ctl->instance_id = comp_info->instance_id;
171+
ctl->mixer_ctl = *tplg_mixer;
172+
tlv = &tplg_ctl->tlv;
173+
scale = &tlv->scale;
174+
175+
/* populate the volume table */
176+
for (i = 0; i < tplg_mixer->max + 1 ; i++) {
177+
uint32_t val = vol_compute_gain(i, scale);
178+
179+
/* Can be over Q1.31, need to saturate */
180+
uint64_t q31val = ((uint64_t)val) << 15;
181+
182+
ctl->volume_table[i] = q31val > SOF_IPC4_VOL_ZERO_DB ?
183+
SOF_IPC4_VOL_ZERO_DB : q31val;
184+
}
185+
break;
186+
}
187+
case SND_SOC_TPLG_CTL_ENUM:
188+
case SND_SOC_TPLG_CTL_ENUM_VALUE:
189+
case SND_SOC_TPLG_CTL_BYTES:
190+
break;
191+
case SND_SOC_TPLG_CTL_RANGE:
192+
case SND_SOC_TPLG_CTL_STROBE:
193+
default:
194+
SNDERR("Invalid ctl type %d\n", tplg_ctl->type);
195+
return -EINVAL;
196+
}
197+
198+
return 0;
199+
}

tools/plugin/common.h

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@
5151
#endif
5252

5353
#define SOF_MAGIC "sofpipe"
54+
#define MAX_VOLUME_SIZE 120
5455

5556
enum plugin_state {
5657
SOF_PLUGIN_STATE_INIT = 0,
@@ -61,8 +62,10 @@ enum plugin_state {
6162
};
6263

6364
struct plug_shm_ctl {
64-
unsigned int comp_id;
65+
unsigned int module_id;
66+
unsigned int instance_id;
6567
unsigned int type;
68+
unsigned int volume_table[MAX_VOLUME_SIZE];
6669
union {
6770
struct snd_soc_tplg_mixer_control mixer_ctl;
6871
struct snd_soc_tplg_enum_control enum_ctl;

tools/plugin/pipe/CMakeLists.txt

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@ add_executable(sof-pipe
44
main.c
55
cpu.c
66
pipeline.c
7-
ctl.c
87
ipc4.c
98
../common.c
109
)

tools/plugin/pipe/ctl.c

Lines changed: 0 additions & 91 deletions
This file was deleted.

0 commit comments

Comments
 (0)