Skip to content

Commit 9d17c65

Browse files
Jaska Uimonenlgirdwood
authored andcommitted
ASOC: SOF: topology: change eq to use effect type
Parse iir and fir eq from widget data field specifying the effect type. Parse also optional initial eq params sent in the eq control's private data. Signed-off-by: Jaska Uimonen <jaska.uimonen@intel.com>
1 parent 53c732e commit 9d17c65

File tree

2 files changed

+204
-43
lines changed

2 files changed

+204
-43
lines changed

include/uapi/sound/sof-ipc.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -724,12 +724,16 @@ struct sof_ipc_comp_tone {
724724
struct sof_ipc_comp_eq_fir {
725725
struct sof_ipc_comp comp;
726726
struct sof_ipc_comp_config config;
727+
int32_t size;
728+
unsigned char data[0];
727729
} __attribute__((packed));
728730

729731
/* IIR equalizer component */
730732
struct sof_ipc_comp_eq_iir {
731733
struct sof_ipc_comp comp;
732734
struct sof_ipc_comp_config config;
735+
int32_t size;
736+
unsigned char data[0];
733737
} __attribute__((packed));
734738

735739
/** \brief Types of EFFECT */

sound/soc/sof/topology.c

Lines changed: 200 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -298,6 +298,8 @@ static int sof_control_load_bytes(struct snd_soc_component *scomp,
298298
{
299299
struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(scomp);
300300
struct sof_ipc_ctrl_data *cdata;
301+
struct snd_soc_tplg_bytes_control *control =
302+
(struct snd_soc_tplg_bytes_control *)hdr;
301303

302304
/* init the get/put bytes data */
303305
scontrol->size = SOF_IPC_MSG_MAX_SIZE;
@@ -312,6 +314,21 @@ static int sof_control_load_bytes(struct snd_soc_component *scomp,
312314
dev_dbg(sdev->dev, "tplg: load kcontrol index %d chans %d\n",
313315
scontrol->comp_id, scontrol->num_channels);
314316

317+
if (le32_to_cpu(control->priv.size) > SOF_IPC_MSG_MAX_SIZE) {
318+
dev_warn(sdev->dev, "bytes priv data size %d too big\n",
319+
control->priv.size);
320+
return -EINVAL;
321+
}
322+
323+
if (le32_to_cpu(control->priv.size) > 0) {
324+
memcpy(cdata->data->data, control->priv.data,
325+
le32_to_cpu(control->priv.size));
326+
cdata->data->size = control->priv.size;
327+
cdata->data->magic = SOF_ABI_MAGIC;
328+
cdata->data->abi = SOF_ABI_VERSION;
329+
cdata->data->comp_abi = SOF_ABI_VERSION;
330+
}
331+
315332
return 0;
316333
}
317334

@@ -436,16 +453,6 @@ static const struct sof_topology_token src_tokens[] = {
436453
static const struct sof_topology_token tone_tokens[] = {
437454
};
438455

439-
/* EQ FIR */
440-
/*
441-
static const struct sof_topology_token eq_fir_tokens[] = {
442-
};
443-
*/
444-
445-
/* EQ IIR */
446-
static const struct sof_topology_token eq_iir_tokens[] = {
447-
};
448-
449456
/* EFFECT */
450457
static const struct sof_topology_token effect_tokens[] = {
451458
{SOF_TKN_EFFECT_TYPE, SND_SOC_TPLG_TUPLE_TYPE_STRING,
@@ -1383,67 +1390,217 @@ static int sof_widget_load_siggen(struct snd_soc_component *scomp, int index,
13831390
kfree(tone);
13841391
return ret;
13851392
}
1386-
/*
1387-
* Effect Topology. Only IIR equalizer is supported at this moment.
1388-
* TODO: Need to add also FIR support and have a way to add other
1389-
* effects and enhancements.
1390-
*/
13911393

1392-
static int sof_widget_load_effect(struct snd_soc_component *scomp, int index,
1393-
struct snd_sof_widget *swidget,
1394-
struct snd_soc_tplg_dapm_widget *tw,
1395-
struct sof_ipc_comp_reply *r)
1394+
static int sof_effect_fir_load(struct snd_soc_component *scomp, int index,
1395+
struct snd_sof_widget *swidget,
1396+
struct snd_soc_tplg_dapm_widget *tw,
1397+
struct sof_ipc_comp_reply *r)
1398+
13961399
{
13971400
struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(scomp);
13981401
struct snd_soc_tplg_private *private = &tw->priv;
1399-
struct sof_ipc_comp_eq_iir *eq;
1402+
struct snd_sof_control *scontrol = NULL;
1403+
struct snd_soc_dapm_widget *widget = swidget->widget;
1404+
const struct snd_kcontrol_new *kc = NULL;
1405+
struct soc_bytes_ext *sbe;
1406+
struct sof_abi_hdr *pdata = NULL;
1407+
struct sof_ipc_comp_eq_fir *fir;
1408+
size_t ipc_size = 0, fir_data_size = 0;
14001409
int ret;
14011410

1402-
eq = kzalloc(sizeof(*eq), GFP_KERNEL);
1403-
if (!eq)
1411+
/* get possible eq controls */
1412+
kc = &widget->kcontrol_news[0];
1413+
if (kc) {
1414+
sbe = (struct soc_bytes_ext *)kc->private_value;
1415+
scontrol = sbe->dobj.private;
1416+
}
1417+
1418+
/*
1419+
* Check if there's eq parameters in control's private member and set
1420+
* data size accordingly. If there's no parameters eq will use defaults
1421+
* in firmware (which in this case is passthrough).
1422+
*/
1423+
if (scontrol && scontrol->cmd == SOF_CTRL_CMD_BINARY) {
1424+
pdata = scontrol->control_data->data;
1425+
if (pdata->size > 0 && pdata->magic == SOF_ABI_MAGIC)
1426+
fir_data_size = pdata->size;
1427+
}
1428+
1429+
ipc_size = sizeof(struct sof_ipc_comp_eq_fir) +
1430+
le32_to_cpu(private->size) +
1431+
fir_data_size;
1432+
1433+
fir = kzalloc(ipc_size, GFP_KERNEL);
1434+
if (!fir)
14041435
return -ENOMEM;
14051436

1406-
/* configure IIR EQ IPC message */
1407-
eq->comp.hdr.size = sizeof(*eq);
1408-
eq->comp.hdr.cmd = SOF_IPC_GLB_TPLG_MSG | SOF_IPC_TPLG_COMP_NEW;
1409-
eq->comp.id = swidget->comp_id;
1410-
eq->comp.pipeline_id = index;
1437+
/* configure fir IPC message */
1438+
fir->comp.hdr.size = ipc_size;
1439+
fir->comp.hdr.cmd = SOF_IPC_GLB_TPLG_MSG | SOF_IPC_TPLG_COMP_NEW;
1440+
fir->comp.id = swidget->comp_id;
1441+
fir->comp.type = SOF_COMP_EQ_FIR;
1442+
fir->comp.pipeline_id = index;
14111443

1412-
eq->comp.type = SOF_COMP_EQ_IIR;
1413-
ret = sof_parse_tokens(scomp, eq, eq_iir_tokens,
1414-
ARRAY_SIZE(eq_iir_tokens), private->array,
1444+
ret = sof_parse_tokens(scomp, &fir->config, comp_tokens,
1445+
ARRAY_SIZE(comp_tokens), private->array,
14151446
le32_to_cpu(private->size));
1416-
if (ret) {
1417-
dev_err(sdev->dev, "error: parse EQ tokens failed %d\n",
1418-
private->size);
1447+
if (ret != 0) {
1448+
dev_err(sdev->dev, "error: parse fir.cfg tokens failed %d\n",
1449+
le32_to_cpu(private->size));
14191450
goto err;
14201451
}
14211452

1422-
ret = sof_parse_tokens(scomp, &eq->config, comp_tokens,
1453+
sof_dbg_comp_config(scomp, &fir->config);
1454+
1455+
/* we have a private data found in control, so copy it */
1456+
if (fir_data_size > 0) {
1457+
memcpy(&fir->data, pdata->data, pdata->size);
1458+
fir->size = fir_data_size;
1459+
}
1460+
1461+
swidget->private = (void *)fir;
1462+
1463+
ret = sof_ipc_tx_message(sdev->ipc, fir->comp.hdr.cmd, fir,
1464+
ipc_size, r, sizeof(*r));
1465+
if (ret >= 0)
1466+
return ret;
1467+
err:
1468+
kfree(fir);
1469+
return ret;
1470+
}
1471+
1472+
static int sof_effect_iir_load(struct snd_soc_component *scomp, int index,
1473+
struct snd_sof_widget *swidget,
1474+
struct snd_soc_tplg_dapm_widget *tw,
1475+
struct sof_ipc_comp_reply *r)
1476+
{
1477+
struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(scomp);
1478+
struct snd_soc_tplg_private *private = &tw->priv;
1479+
struct snd_soc_dapm_widget *widget = swidget->widget;
1480+
const struct snd_kcontrol_new *kc = NULL;
1481+
struct soc_bytes_ext *sbe;
1482+
struct snd_sof_control *scontrol = NULL;
1483+
struct sof_abi_hdr *pdata = NULL;
1484+
struct sof_ipc_comp_eq_iir *iir;
1485+
size_t ipc_size = 0, iir_data_size = 0;
1486+
int ret;
1487+
1488+
/* get possible eq controls */
1489+
kc = &widget->kcontrol_news[0];
1490+
if (kc) {
1491+
sbe = (struct soc_bytes_ext *)kc->private_value;
1492+
scontrol = sbe->dobj.private;
1493+
}
1494+
1495+
/*
1496+
* Check if there's eq parameters in control's private member and set
1497+
* data size accordingly. If there's no parameters eq will use defaults
1498+
* in firmware (which in this case is passthrough).
1499+
*/
1500+
if (scontrol && scontrol->cmd == SOF_CTRL_CMD_BINARY) {
1501+
pdata = scontrol->control_data->data;
1502+
if (pdata->size > 0 && pdata->magic == SOF_ABI_MAGIC)
1503+
iir_data_size = pdata->size;
1504+
}
1505+
1506+
ipc_size = sizeof(struct sof_ipc_comp_eq_iir) +
1507+
le32_to_cpu(private->size) +
1508+
iir_data_size;
1509+
1510+
iir = kzalloc(ipc_size, GFP_KERNEL);
1511+
if (!iir)
1512+
return -ENOMEM;
1513+
1514+
/* configure iir IPC message */
1515+
iir->comp.hdr.size = ipc_size;
1516+
iir->comp.hdr.cmd = SOF_IPC_GLB_TPLG_MSG | SOF_IPC_TPLG_COMP_NEW;
1517+
iir->comp.id = swidget->comp_id;
1518+
iir->comp.type = SOF_COMP_EQ_IIR;
1519+
iir->comp.pipeline_id = index;
1520+
1521+
ret = sof_parse_tokens(scomp, &iir->config, comp_tokens,
14231522
ARRAY_SIZE(comp_tokens), private->array,
14241523
le32_to_cpu(private->size));
1425-
if (ret) {
1426-
dev_err(sdev->dev, "error: parse EQ.cfg tokens failed %d\n",
1524+
if (ret != 0) {
1525+
dev_err(sdev->dev, "error: parse iir.cfg tokens failed %d\n",
14271526
le32_to_cpu(private->size));
14281527
goto err;
14291528
}
14301529

1431-
dev_dbg(sdev->dev, "eq iir %s created\n", swidget->widget->name);
1530+
sof_dbg_comp_config(scomp, &iir->config);
14321531

1433-
sof_dbg_comp_config(scomp, &eq->config);
1434-
1435-
swidget->private = (void *)eq;
1532+
/* we have a private data found in control, so copy it */
1533+
if (iir_data_size > 0) {
1534+
memcpy(&iir->data, pdata->data, pdata->size);
1535+
iir->size = iir_data_size;
1536+
}
14361537

1437-
ret = sof_ipc_tx_message(sdev->ipc, eq->comp.hdr.cmd, eq,
1438-
sizeof(*eq), r, sizeof(*r));
1538+
swidget->private = (void *)iir;
14391539

1540+
ret = sof_ipc_tx_message(sdev->ipc, iir->comp.hdr.cmd, iir,
1541+
ipc_size, r, sizeof(*r));
14401542
if (ret >= 0)
14411543
return ret;
14421544
err:
1443-
kfree(eq);
1545+
kfree(iir);
14441546
return ret;
14451547
}
14461548

1549+
/*
1550+
* Effect Topology
1551+
*/
1552+
1553+
static int sof_widget_load_effect(struct snd_soc_component *scomp, int index,
1554+
struct snd_sof_widget *swidget,
1555+
struct snd_soc_tplg_dapm_widget *tw,
1556+
struct sof_ipc_comp_reply *r)
1557+
{
1558+
struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(scomp);
1559+
struct snd_soc_tplg_private *private = &tw->priv;
1560+
struct sof_ipc_comp_effect config;
1561+
int ret;
1562+
1563+
/* check we have some tokens - we need at least effect type */
1564+
if (le32_to_cpu(private->size) == 0) {
1565+
dev_err(sdev->dev, "error: effect tokens not found\n");
1566+
return -EINVAL;
1567+
}
1568+
1569+
memset(&config, 0, sizeof(config));
1570+
1571+
/* get the effect token */
1572+
ret = sof_parse_tokens(scomp, &config, effect_tokens,
1573+
ARRAY_SIZE(effect_tokens), private->array,
1574+
le32_to_cpu(private->size));
1575+
if (ret != 0) {
1576+
dev_err(sdev->dev, "error: parse effect tokens failed %d\n",
1577+
le32_to_cpu(private->size));
1578+
return ret;
1579+
}
1580+
1581+
/* now load effect specific data and send IPC */
1582+
switch (config.type) {
1583+
case SOF_EFFECT_INTEL_EQFIR:
1584+
ret = sof_effect_fir_load(scomp, index, swidget, tw, r);
1585+
break;
1586+
case SOF_EFFECT_INTEL_EQIIR:
1587+
ret = sof_effect_iir_load(scomp, index, swidget, tw, r);
1588+
break;
1589+
default:
1590+
dev_err(sdev->dev, "error: invalid effect type %d\n",
1591+
config.type);
1592+
ret = -EINVAL;
1593+
break;
1594+
}
1595+
1596+
if (ret < 0) {
1597+
dev_err(sdev->dev, "error: effect loading failed\n");
1598+
return ret;
1599+
}
1600+
1601+
return 0;
1602+
}
1603+
14471604
/*
14481605
* Generic widget loader.
14491606
*/

0 commit comments

Comments
 (0)