Skip to content

Commit b5cee8f

Browse files
ranj063broonie
authored andcommitted
ASoC: SOF: topology: Make control parsing IPC agnostic
Make the control parser in topology IPC agnostic by introducing 2 new topology IPC ops, control_setup and control_free. These ops handle setting up/freeing the control data in the IPC format based on the IPC version. Along with this, modify the struct snd_sof_control to remove the IPC-specific field, control_data and replace it with the void pointer to ipc_control_data. Also, add a few new fields to store all the information parsed from topology. Finally, define and set the control setup/free ops for IPC3. Signed-off-by: Ranjani Sridharan <ranjani.sridharan@linux.intel.com> Reviewed-by: Bard Liao <yung-chuan.liao@linux.intel.com> Reviewed-by: Péter Ujfalusi <peter.ujfalusi@linux.intel.com> Reviewed-by: Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com> Link: https://lore.kernel.org/r/20220314200520.1233427-18-ranjani.sridharan@linux.intel.com Signed-off-by: Mark Brown <broonie@kernel.org>
1 parent 909dadf commit b5cee8f

5 files changed

Lines changed: 235 additions & 141 deletions

File tree

sound/soc/sof/control.c

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@ static inline u32 ipc_to_mixer(u32 value, u32 *volume_map, int size)
6767

6868
static void snd_sof_refresh_control(struct snd_sof_control *scontrol)
6969
{
70-
struct sof_ipc_ctrl_data *cdata = scontrol->control_data;
70+
struct sof_ipc_ctrl_data *cdata = scontrol->ipc_control_data;
7171
struct snd_soc_component *scomp = scontrol->scomp;
7272
int ret;
7373

@@ -97,7 +97,7 @@ int snd_sof_volume_get(struct snd_kcontrol *kcontrol,
9797
struct soc_mixer_control *sm =
9898
(struct soc_mixer_control *)kcontrol->private_value;
9999
struct snd_sof_control *scontrol = sm->dobj.private;
100-
struct sof_ipc_ctrl_data *cdata = scontrol->control_data;
100+
struct sof_ipc_ctrl_data *cdata = scontrol->ipc_control_data;
101101
unsigned int i, channels = scontrol->num_channels;
102102

103103
snd_sof_refresh_control(scontrol);
@@ -118,7 +118,7 @@ int snd_sof_volume_put(struct snd_kcontrol *kcontrol,
118118
(struct soc_mixer_control *)kcontrol->private_value;
119119
struct snd_sof_control *scontrol = sm->dobj.private;
120120
struct snd_soc_component *scomp = scontrol->scomp;
121-
struct sof_ipc_ctrl_data *cdata = scontrol->control_data;
121+
struct sof_ipc_ctrl_data *cdata = scontrol->ipc_control_data;
122122
unsigned int i, channels = scontrol->num_channels;
123123
bool change = false;
124124
u32 value;
@@ -166,7 +166,7 @@ int snd_sof_switch_get(struct snd_kcontrol *kcontrol,
166166
struct soc_mixer_control *sm =
167167
(struct soc_mixer_control *)kcontrol->private_value;
168168
struct snd_sof_control *scontrol = sm->dobj.private;
169-
struct sof_ipc_ctrl_data *cdata = scontrol->control_data;
169+
struct sof_ipc_ctrl_data *cdata = scontrol->ipc_control_data;
170170
unsigned int i, channels = scontrol->num_channels;
171171

172172
snd_sof_refresh_control(scontrol);
@@ -185,7 +185,7 @@ int snd_sof_switch_put(struct snd_kcontrol *kcontrol,
185185
(struct soc_mixer_control *)kcontrol->private_value;
186186
struct snd_sof_control *scontrol = sm->dobj.private;
187187
struct snd_soc_component *scomp = scontrol->scomp;
188-
struct sof_ipc_ctrl_data *cdata = scontrol->control_data;
188+
struct sof_ipc_ctrl_data *cdata = scontrol->ipc_control_data;
189189
unsigned int i, channels = scontrol->num_channels;
190190
bool change = false;
191191
u32 value;
@@ -214,7 +214,7 @@ int snd_sof_enum_get(struct snd_kcontrol *kcontrol,
214214
struct soc_enum *se =
215215
(struct soc_enum *)kcontrol->private_value;
216216
struct snd_sof_control *scontrol = se->dobj.private;
217-
struct sof_ipc_ctrl_data *cdata = scontrol->control_data;
217+
struct sof_ipc_ctrl_data *cdata = scontrol->ipc_control_data;
218218
unsigned int i, channels = scontrol->num_channels;
219219

220220
snd_sof_refresh_control(scontrol);
@@ -233,7 +233,7 @@ int snd_sof_enum_put(struct snd_kcontrol *kcontrol,
233233
(struct soc_enum *)kcontrol->private_value;
234234
struct snd_sof_control *scontrol = se->dobj.private;
235235
struct snd_soc_component *scomp = scontrol->scomp;
236-
struct sof_ipc_ctrl_data *cdata = scontrol->control_data;
236+
struct sof_ipc_ctrl_data *cdata = scontrol->ipc_control_data;
237237
unsigned int i, channels = scontrol->num_channels;
238238
bool change = false;
239239
u32 value;
@@ -260,7 +260,7 @@ int snd_sof_bytes_get(struct snd_kcontrol *kcontrol,
260260
(struct soc_bytes_ext *)kcontrol->private_value;
261261
struct snd_sof_control *scontrol = be->dobj.private;
262262
struct snd_soc_component *scomp = scontrol->scomp;
263-
struct sof_ipc_ctrl_data *cdata = scontrol->control_data;
263+
struct sof_ipc_ctrl_data *cdata = scontrol->ipc_control_data;
264264
struct sof_abi_hdr *data = cdata->data;
265265
size_t size;
266266

@@ -296,7 +296,7 @@ int snd_sof_bytes_put(struct snd_kcontrol *kcontrol,
296296
(struct soc_bytes_ext *)kcontrol->private_value;
297297
struct snd_sof_control *scontrol = be->dobj.private;
298298
struct snd_soc_component *scomp = scontrol->scomp;
299-
struct sof_ipc_ctrl_data *cdata = scontrol->control_data;
299+
struct sof_ipc_ctrl_data *cdata = scontrol->ipc_control_data;
300300
struct sof_abi_hdr *data = cdata->data;
301301
size_t size;
302302

@@ -335,7 +335,7 @@ int snd_sof_bytes_ext_put(struct snd_kcontrol *kcontrol,
335335
(struct soc_bytes_ext *)kcontrol->private_value;
336336
struct snd_sof_control *scontrol = be->dobj.private;
337337
struct snd_soc_component *scomp = scontrol->scomp;
338-
struct sof_ipc_ctrl_data *cdata = scontrol->control_data;
338+
struct sof_ipc_ctrl_data *cdata = scontrol->ipc_control_data;
339339
struct snd_ctl_tlv header;
340340
const struct snd_ctl_tlv __user *tlvd =
341341
(const struct snd_ctl_tlv __user *)binary_data;
@@ -409,7 +409,7 @@ int snd_sof_bytes_ext_volatile_get(struct snd_kcontrol *kcontrol, unsigned int _
409409
struct soc_bytes_ext *be = (struct soc_bytes_ext *)kcontrol->private_value;
410410
struct snd_sof_control *scontrol = be->dobj.private;
411411
struct snd_soc_component *scomp = scontrol->scomp;
412-
struct sof_ipc_ctrl_data *cdata = scontrol->control_data;
412+
struct sof_ipc_ctrl_data *cdata = scontrol->ipc_control_data;
413413
struct snd_ctl_tlv header;
414414
struct snd_ctl_tlv __user *tlvd = (struct snd_ctl_tlv __user *)binary_data;
415415
size_t data_size;
@@ -482,7 +482,7 @@ int snd_sof_bytes_ext_get(struct snd_kcontrol *kcontrol,
482482
(struct soc_bytes_ext *)kcontrol->private_value;
483483
struct snd_sof_control *scontrol = be->dobj.private;
484484
struct snd_soc_component *scomp = scontrol->scomp;
485-
struct sof_ipc_ctrl_data *cdata = scontrol->control_data;
485+
struct sof_ipc_ctrl_data *cdata = scontrol->ipc_control_data;
486486
struct snd_ctl_tlv header;
487487
struct snd_ctl_tlv __user *tlvd =
488488
(struct snd_ctl_tlv __user *)binary_data;
@@ -534,7 +534,7 @@ static void snd_sof_update_control(struct snd_sof_control *scontrol,
534534
struct sof_ipc_ctrl_data *local_cdata;
535535
int i;
536536

537-
local_cdata = scontrol->control_data;
537+
local_cdata = scontrol->ipc_control_data;
538538

539539
if (cdata->cmd == SOF_CTRL_CMD_BINARY) {
540540
if (cdata->num_elems != local_cdata->data->size) {

sound/soc/sof/ipc.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -812,7 +812,7 @@ static int sof_set_get_large_ctrl_data(struct snd_sof_dev *sdev,
812812
int snd_sof_ipc_set_get_comp_data(struct snd_sof_control *scontrol, bool set)
813813
{
814814
struct snd_soc_component *scomp = scontrol->scomp;
815-
struct sof_ipc_ctrl_data *cdata = scontrol->control_data;
815+
struct sof_ipc_ctrl_data *cdata = scontrol->ipc_control_data;
816816
struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(scomp);
817817
struct sof_ipc_fw_ready *ready = &sdev->fw_ready;
818818
struct sof_ipc_fw_version *v = &ready->version;

sound/soc/sof/ipc3-topology.c

Lines changed: 149 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,9 @@
1212
#include "sof-audio.h"
1313
#include "ops.h"
1414

15+
/* Full volume for default values */
16+
#define VOL_ZERO_DB BIT(VOLUME_FWL)
17+
1518
struct sof_widget_data {
1619
int ctrl_type;
1720
int ipc_cmd;
@@ -743,6 +746,7 @@ static int sof_get_control_data(struct snd_soc_component *scomp,
743746
struct sof_widget_data *wdata, size_t *size)
744747
{
745748
const struct snd_kcontrol_new *kc;
749+
struct sof_ipc_ctrl_data *cdata;
746750
struct soc_mixer_control *sm;
747751
struct soc_bytes_ext *sbe;
748752
struct soc_enum *se;
@@ -777,7 +781,8 @@ static int sof_get_control_data(struct snd_soc_component *scomp,
777781
return -EINVAL;
778782
}
779783

780-
wdata[i].pdata = wdata[i].control->control_data->data;
784+
cdata = wdata[i].control->ipc_control_data;
785+
wdata[i].pdata = cdata->data;
781786
if (!wdata[i].pdata)
782787
return -EINVAL;
783788

@@ -789,7 +794,7 @@ static int sof_get_control_data(struct snd_soc_component *scomp,
789794
*size += wdata[i].pdata->size;
790795

791796
/* get data type */
792-
switch (wdata[i].control->control_data->cmd) {
797+
switch (cdata->cmd) {
793798
case SOF_CTRL_CMD_VOLUME:
794799
case SOF_CTRL_CMD_ENUM:
795800
case SOF_CTRL_CMD_SWITCH:
@@ -1553,6 +1558,146 @@ static int sof_ipc3_route_setup(struct snd_sof_dev *sdev, struct snd_sof_route *
15531558
return ret;
15541559
}
15551560

1561+
static int sof_ipc3_control_load_bytes(struct snd_sof_dev *sdev, struct snd_sof_control *scontrol)
1562+
{
1563+
struct sof_ipc_ctrl_data *cdata;
1564+
int ret;
1565+
1566+
scontrol->ipc_control_data = kzalloc(scontrol->max_size, GFP_KERNEL);
1567+
if (!scontrol->ipc_control_data)
1568+
return -ENOMEM;
1569+
1570+
if (scontrol->max_size < sizeof(*cdata) ||
1571+
scontrol->max_size < sizeof(struct sof_abi_hdr)) {
1572+
ret = -EINVAL;
1573+
goto err;
1574+
}
1575+
1576+
/* init the get/put bytes data */
1577+
if (scontrol->priv_size > scontrol->max_size - sizeof(*cdata)) {
1578+
dev_err(sdev->dev, "err: bytes data size %zu exceeds max %zu.\n",
1579+
scontrol->priv_size, scontrol->max_size - sizeof(*cdata));
1580+
ret = -EINVAL;
1581+
goto err;
1582+
}
1583+
1584+
scontrol->size = sizeof(struct sof_ipc_ctrl_data) + scontrol->priv_size;
1585+
1586+
cdata = scontrol->ipc_control_data;
1587+
cdata->cmd = SOF_CTRL_CMD_BINARY;
1588+
cdata->index = scontrol->index;
1589+
1590+
if (scontrol->priv_size > 0) {
1591+
memcpy(cdata->data, scontrol->priv, scontrol->priv_size);
1592+
kfree(scontrol->priv);
1593+
1594+
if (cdata->data->magic != SOF_ABI_MAGIC) {
1595+
dev_err(sdev->dev, "Wrong ABI magic 0x%08x.\n", cdata->data->magic);
1596+
ret = -EINVAL;
1597+
goto err;
1598+
}
1599+
1600+
if (SOF_ABI_VERSION_INCOMPATIBLE(SOF_ABI_VERSION, cdata->data->abi)) {
1601+
dev_err(sdev->dev, "Incompatible ABI version 0x%08x.\n",
1602+
cdata->data->abi);
1603+
ret = -EINVAL;
1604+
goto err;
1605+
}
1606+
1607+
if (cdata->data->size + sizeof(struct sof_abi_hdr) != scontrol->priv_size) {
1608+
dev_err(sdev->dev, "Conflict in bytes vs. priv size.\n");
1609+
ret = -EINVAL;
1610+
goto err;
1611+
}
1612+
}
1613+
1614+
return 0;
1615+
err:
1616+
kfree(scontrol->ipc_control_data);
1617+
return ret;
1618+
}
1619+
1620+
static int sof_ipc3_control_load_volume(struct snd_sof_dev *sdev, struct snd_sof_control *scontrol)
1621+
{
1622+
struct sof_ipc_ctrl_data *cdata;
1623+
int i;
1624+
1625+
/* init the volume get/put data */
1626+
scontrol->size = struct_size(cdata, chanv, scontrol->num_channels);
1627+
1628+
scontrol->ipc_control_data = kzalloc(scontrol->size, GFP_KERNEL);
1629+
if (!scontrol->ipc_control_data)
1630+
return -ENOMEM;
1631+
1632+
cdata = scontrol->ipc_control_data;
1633+
cdata->index = scontrol->index;
1634+
1635+
/* set cmd for mixer control */
1636+
if (scontrol->max == 1) {
1637+
cdata->cmd = SOF_CTRL_CMD_SWITCH;
1638+
return 0;
1639+
}
1640+
1641+
cdata->cmd = SOF_CTRL_CMD_VOLUME;
1642+
1643+
/* set default volume values to 0dB in control */
1644+
for (i = 0; i < scontrol->num_channels; i++) {
1645+
cdata->chanv[i].channel = i;
1646+
cdata->chanv[i].value = VOL_ZERO_DB;
1647+
}
1648+
1649+
return 0;
1650+
}
1651+
1652+
static int sof_ipc3_control_load_enum(struct snd_sof_dev *sdev, struct snd_sof_control *scontrol)
1653+
{
1654+
struct sof_ipc_ctrl_data *cdata;
1655+
1656+
/* init the enum get/put data */
1657+
scontrol->size = struct_size(cdata, chanv, scontrol->num_channels);
1658+
1659+
scontrol->ipc_control_data = kzalloc(scontrol->size, GFP_KERNEL);
1660+
if (!scontrol->ipc_control_data)
1661+
return -ENOMEM;
1662+
1663+
cdata = scontrol->ipc_control_data;
1664+
cdata->index = scontrol->index;
1665+
cdata->cmd = SOF_CTRL_CMD_ENUM;
1666+
1667+
return 0;
1668+
}
1669+
1670+
static int sof_ipc3_control_setup(struct snd_sof_dev *sdev, struct snd_sof_control *scontrol)
1671+
{
1672+
switch (scontrol->info_type) {
1673+
case SND_SOC_TPLG_CTL_VOLSW:
1674+
case SND_SOC_TPLG_CTL_VOLSW_SX:
1675+
case SND_SOC_TPLG_CTL_VOLSW_XR_SX:
1676+
return sof_ipc3_control_load_volume(sdev, scontrol);
1677+
case SND_SOC_TPLG_CTL_BYTES:
1678+
return sof_ipc3_control_load_bytes(sdev, scontrol);
1679+
case SND_SOC_TPLG_CTL_ENUM:
1680+
case SND_SOC_TPLG_CTL_ENUM_VALUE:
1681+
return sof_ipc3_control_load_enum(sdev, scontrol);
1682+
default:
1683+
break;
1684+
}
1685+
1686+
return 0;
1687+
}
1688+
1689+
static int sof_ipc3_control_free(struct snd_sof_dev *sdev, struct snd_sof_control *scontrol)
1690+
{
1691+
struct sof_ipc_free fcomp;
1692+
1693+
fcomp.hdr.cmd = SOF_IPC_GLB_TPLG_MSG | SOF_IPC_TPLG_COMP_FREE;
1694+
fcomp.hdr.size = sizeof(fcomp);
1695+
fcomp.id = scontrol->comp_id;
1696+
1697+
/* send IPC to the DSP */
1698+
return sof_ipc_tx_message(sdev->ipc, fcomp.hdr.cmd, &fcomp, sizeof(fcomp), NULL, 0);
1699+
}
1700+
15561701
/* token list for each topology object */
15571702
static enum sof_tokens host_token_list[] = {
15581703
SOF_CORE_TOKENS,
@@ -1651,6 +1796,8 @@ static const struct sof_ipc_tplg_widget_ops tplg_ipc3_widget_ops[SND_SOC_DAPM_TY
16511796
static const struct sof_ipc_tplg_ops ipc3_tplg_ops = {
16521797
.widget = tplg_ipc3_widget_ops,
16531798
.route_setup = sof_ipc3_route_setup,
1799+
.control_setup = sof_ipc3_control_setup,
1800+
.control_free = sof_ipc3_control_free,
16541801
.token_list = ipc3_token_list,
16551802
};
16561803

sound/soc/sof/sof-audio.h

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,8 +30,15 @@
3030

3131
#define WIDGET_IS_DAI(id) ((id) == snd_soc_dapm_dai_in || (id) == snd_soc_dapm_dai_out)
3232

33+
/*
34+
* Volume fractional word length define to 16 sets
35+
* the volume linear gain value to use Qx.16 format
36+
*/
37+
#define VOLUME_FWL 16
38+
3339
struct snd_sof_widget;
3440
struct snd_sof_route;
41+
struct snd_sof_control;
3542

3643
/**
3744
* struct sof_ipc_tplg_widget_ops - IPC-specific ops for topology widgets
@@ -59,11 +66,15 @@ struct sof_ipc_tplg_widget_ops {
5966
* @token_list: List of all tokens supported by the IPC version. The size of the token_list
6067
* array should be SOF_TOKEN_COUNT. The unused elements in the array will be
6168
* initialized to 0.
69+
* @control_setup: Function pointer for setting up kcontrol IPC-specific data
70+
* @control_free: Function pointer for freeing kcontrol IPC-specific data
6271
*/
6372
struct sof_ipc_tplg_ops {
6473
const struct sof_ipc_tplg_widget_ops *widget;
6574
int (*route_setup)(struct snd_sof_dev *sdev, struct snd_sof_route *sroute);
6675
const struct sof_token_info *token_list;
76+
int (*control_setup)(struct snd_sof_dev *sdev, struct snd_sof_control *scontrol);
77+
int (*control_free)(struct snd_sof_dev *sdev, struct snd_sof_control *scontrol);
6778
};
6879

6980
/** struct snd_sof_tuple - Tuple info
@@ -165,13 +176,20 @@ struct snd_sof_led_control {
165176
/* ALSA SOF Kcontrol device */
166177
struct snd_sof_control {
167178
struct snd_soc_component *scomp;
179+
const char *name;
168180
int comp_id;
169181
int min_volume_step; /* min volume step for volume_table */
170182
int max_volume_step; /* max volume step for volume_table */
171183
int num_channels;
172184
unsigned int access;
173185
u32 readback_offset; /* offset to mmapped data if used */
174-
struct sof_ipc_ctrl_data *control_data;
186+
int info_type;
187+
int index; /* pipeline ID */
188+
void *priv; /* private data copied from topology */
189+
size_t priv_size; /* size of private data */
190+
size_t max_size;
191+
void *ipc_control_data;
192+
int max; /* applicable to volume controls */
175193
u32 size; /* cdata size */
176194
u32 *volume_table; /* volume table computed from tlv data*/
177195

0 commit comments

Comments
 (0)