Skip to content

Commit 7cf3630

Browse files
singalsulgirdwood
authored andcommitted
SOF Topology: Add ext bytes put and get feature
This patch adds the binary control into topology parsing and provides for ASoC the SOF ext bytes put and get functions. Signed-off-by: Ranjani Sridharan <ranjani.sridharan@linux.intel.com> Signed-off-by: Seppo Ingalsuo <seppo.ingalsuo@linux.intel.com>
1 parent f0cc5ea commit 7cf3630

3 files changed

Lines changed: 205 additions & 3 deletions

File tree

sound/soc/sof/control.c

Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -268,3 +268,98 @@ int snd_sof_bytes_put(struct snd_kcontrol *kcontrol,
268268
err);
269269
return ret;
270270
}
271+
272+
int snd_sof_bytes_ext_put(struct snd_kcontrol *kcontrol,
273+
const unsigned int __user *binary_data,
274+
unsigned int size)
275+
{
276+
struct soc_bytes_ext *be =
277+
(struct soc_bytes_ext *)kcontrol->private_value;
278+
struct snd_sof_control *scontrol = be->dobj.private;
279+
struct snd_sof_dev *sdev = scontrol->sdev;
280+
struct sof_ipc_ctrl_data *cdata = scontrol->control_data;
281+
u32 header[2];
282+
int ret;
283+
int err;
284+
int length;
285+
const int max_length = SOF_IPC_MSG_MAX_SIZE -
286+
sizeof(struct sof_ipc_ctrl_data) -
287+
sizeof(struct sof_abi_hdr);
288+
289+
ret = pm_runtime_get_sync(sdev->dev);
290+
if (ret < 0) {
291+
dev_err(sdev->dev, "error: bytes put failed to resume %d\n",
292+
ret);
293+
return ret;
294+
}
295+
296+
/* the first two ints of the bytes data contain a dummy tag
297+
* and the size, so copy from the 3rd int
298+
* TODO: or should we send the size as well so the firmware
299+
* can allocate memory accordingly?
300+
*/
301+
if (copy_from_user(&header, binary_data, 2*sizeof(u32)))
302+
return -EFAULT;
303+
304+
length = header[1];
305+
dev_dbg(sdev->dev, "size of bytes put data is %d\n", length);
306+
if (length > max_length) {
307+
dev_err(sdev->dev, "error: size is too large, bytes max is %d\n",
308+
max_length);
309+
ret = -EINVAL;
310+
goto out;
311+
}
312+
313+
if (copy_from_user(cdata->data->data, binary_data + 2, length))
314+
return -EFAULT;
315+
316+
/* set the ABI header values */
317+
cdata->data->magic = SOF_ABI_MAGIC;
318+
cdata->data->abi = SOF_ABI_VERSION;
319+
cdata->data->comp_abi = SOF_ABI_VERSION;
320+
321+
/* notify DSP of mixer updates */
322+
snd_sof_ipc_set_comp_data(sdev->ipc, scontrol, SOF_IPC_COMP_SET_DATA,
323+
SOF_CTRL_TYPE_DATA_SET, scontrol->cmd);
324+
325+
326+
out:
327+
pm_runtime_mark_last_busy(sdev->dev);
328+
err = pm_runtime_put_autosuspend(sdev->dev);
329+
if (err < 0)
330+
dev_err(sdev->dev, "error: failed to idle %d\n", err);
331+
332+
return ret;
333+
}
334+
335+
int snd_sof_bytes_ext_get(struct snd_kcontrol *kcontrol,
336+
unsigned int __user *binary_data,
337+
unsigned int size)
338+
{
339+
struct soc_bytes_ext *be =
340+
(struct soc_bytes_ext *)kcontrol->private_value;
341+
struct snd_sof_control *scontrol = be->dobj.private;
342+
struct snd_sof_dev *sdev = scontrol->sdev;
343+
struct sof_ipc_ctrl_data *cdata = scontrol->control_data;
344+
unsigned int tag = 0;
345+
346+
pm_runtime_get_sync(sdev->dev);
347+
348+
dev_dbg(sdev->dev, "getting data and command is %d\n", scontrol->cmd);
349+
/* get all the mixer data from DSP */
350+
snd_sof_ipc_get_comp_data(sdev->ipc, scontrol, SOF_IPC_COMP_GET_DATA,
351+
SOF_CTRL_TYPE_DATA_GET, scontrol->cmd);
352+
353+
/* TODO: replace 252 with actual size */
354+
if (copy_to_user(binary_data, &tag, sizeof(u32)))
355+
return -EFAULT;
356+
if (copy_to_user(binary_data + 1, &size, sizeof(u32)))
357+
return -EFAULT;
358+
if (copy_to_user(binary_data + 2, cdata->data->data,
359+
SOF_IPC_MSG_MAX_SIZE - sizeof(struct sof_ipc_ctrl_data)))
360+
return -EFAULT;
361+
362+
pm_runtime_mark_last_busy(sdev->dev);
363+
pm_runtime_put_autosuspend(sdev->dev);
364+
return 0;
365+
}

sound/soc/sof/sof-priv.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -501,6 +501,12 @@ int snd_sof_bytes_get(struct snd_kcontrol *kcontrol,
501501
struct snd_ctl_elem_value *ucontrol);
502502
int snd_sof_bytes_put(struct snd_kcontrol *kcontrol,
503503
struct snd_ctl_elem_value *ucontrol);
504+
int snd_sof_bytes_ext_put(struct snd_kcontrol *kcontrol,
505+
const unsigned int __user *bytes,
506+
unsigned int size);
507+
int snd_sof_bytes_ext_get(struct snd_kcontrol *kcontrol,
508+
unsigned int __user *bytes,
509+
unsigned int size);
504510

505511
/*
506512
* DSP Architectures.

sound/soc/sof/topology.c

Lines changed: 104 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -269,6 +269,30 @@ static int sof_control_load_volume(struct snd_soc_component *scomp,
269269
return 0;
270270
}
271271

272+
static int sof_control_load_bytes(struct snd_soc_component *scomp,
273+
struct snd_sof_control *scontrol,
274+
struct snd_kcontrol_new *kc,
275+
struct snd_soc_tplg_ctl_hdr *hdr)
276+
{
277+
struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(scomp);
278+
struct sof_ipc_ctrl_data *cdata;
279+
280+
/* init the get/put bytes data */
281+
scontrol->size = SOF_IPC_MSG_MAX_SIZE;
282+
scontrol->control_data = kzalloc(scontrol->size, GFP_KERNEL);
283+
cdata = scontrol->control_data;
284+
if (!scontrol->control_data)
285+
return -ENOMEM;
286+
287+
scontrol->comp_id = sdev->next_comp_id;
288+
scontrol->cmd = SOF_CTRL_CMD_BINARY;
289+
290+
dev_dbg(sdev->dev, "tplg: load kcontrol index %d chans %d\n",
291+
scontrol->comp_id, scontrol->num_channels);
292+
293+
return 0;
294+
}
295+
272296
/*
273297
* Topology Token Parsing.
274298
* New tokens should be added to headers and parsing tables below.
@@ -381,6 +405,16 @@ static const struct sof_topology_token src_tokens[] = {
381405
static const struct sof_topology_token tone_tokens[] = {
382406
};
383407

408+
/* EQ FIR */
409+
/*
410+
static const struct sof_topology_token eq_fir_tokens[] = {
411+
};
412+
*/
413+
414+
/* EQ IIR */
415+
static const struct sof_topology_token eq_iir_tokens[] = {
416+
};
417+
384418
/* PCM */
385419
static const struct sof_topology_token pcm_tokens[] = {
386420
{SOF_TKN_PCM_DMAC_CONFIG, SND_SOC_TPLG_TUPLE_TYPE_WORD, get_token_u32,
@@ -707,6 +741,7 @@ static int sof_control_load(struct snd_soc_component *scomp, int index,
707741
struct snd_soc_tplg_ctl_hdr *hdr)
708742
{
709743
struct soc_mixer_control *sm;
744+
struct soc_bytes_ext *sbe;
710745
struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(scomp);
711746
struct snd_soc_dobj *dobj = NULL;
712747
struct snd_sof_control *scontrol;
@@ -730,8 +765,12 @@ static int sof_control_load(struct snd_soc_component *scomp, int index,
730765
dobj = &sm->dobj;
731766
ret = sof_control_load_volume(scomp, scontrol, kc, hdr);
732767
break;
733-
case SND_SOC_TPLG_CTL_ENUM:
734768
case SND_SOC_TPLG_CTL_BYTES:
769+
sbe = (struct soc_bytes_ext *)kc->private_value;
770+
dobj = &sbe->dobj;
771+
ret = sof_control_load_bytes(scomp, scontrol, kc, hdr);
772+
break;
773+
case SND_SOC_TPLG_CTL_ENUM:
735774
case SND_SOC_TPLG_CTL_ENUM_VALUE:
736775
case SND_SOC_TPLG_CTL_RANGE:
737776
case SND_SOC_TPLG_CTL_STROBE:
@@ -1306,6 +1345,66 @@ static int sof_widget_load_siggen(struct snd_soc_component *scomp, int index,
13061345
kfree(tone);
13071346
return ret;
13081347
}
1348+
/*
1349+
* Effect Topology. Only IIR equalizer is supported at this moment.
1350+
* TODO: Need to add also FIR support and have a way to add other
1351+
* effects and enhancements.
1352+
*/
1353+
1354+
static int sof_widget_load_effect(struct snd_soc_component *scomp, int index,
1355+
struct snd_sof_widget *swidget,
1356+
struct snd_soc_tplg_dapm_widget *tw,
1357+
struct sof_ipc_comp_reply *r)
1358+
{
1359+
struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(scomp);
1360+
struct snd_soc_tplg_private *private = &tw->priv;
1361+
struct sof_ipc_comp_eq_iir *eq;
1362+
int ret;
1363+
1364+
eq = kzalloc(sizeof(*eq), GFP_KERNEL);
1365+
if (!eq)
1366+
return -ENOMEM;
1367+
1368+
/* configure IIR EQ IPC message */
1369+
eq->comp.hdr.size = sizeof(*eq);
1370+
eq->comp.hdr.cmd = SOF_IPC_GLB_TPLG_MSG | SOF_IPC_TPLG_COMP_NEW;
1371+
eq->comp.id = swidget->comp_id;
1372+
eq->comp.pipeline_id = index;
1373+
1374+
eq->comp.type = SOF_COMP_EQ_IIR;
1375+
ret = sof_parse_tokens(scomp, eq, eq_iir_tokens,
1376+
ARRAY_SIZE(eq_iir_tokens), private->array,
1377+
le32_to_cpu(private->size));
1378+
if (ret) {
1379+
dev_err(sdev->dev, "error: parse EQ tokens failed %d\n",
1380+
private->size);
1381+
goto err;
1382+
}
1383+
1384+
ret = sof_parse_tokens(scomp, &eq->config, comp_tokens,
1385+
ARRAY_SIZE(comp_tokens), private->array,
1386+
le32_to_cpu(private->size));
1387+
if (ret) {
1388+
dev_err(sdev->dev, "error: parse EQ.cfg tokens failed %d\n",
1389+
le32_to_cpu(private->size));
1390+
goto err;
1391+
}
1392+
1393+
dev_dbg(sdev->dev, "eq iir %s created\n", swidget->widget->name);
1394+
1395+
sof_dbg_comp_config(scomp, &eq->config);
1396+
1397+
swidget->private = (void *)eq;
1398+
1399+
ret = sof_ipc_tx_message(sdev->ipc, eq->comp.hdr.cmd, eq,
1400+
sizeof(*eq), r, sizeof(*r));
1401+
1402+
if (ret >= 0)
1403+
return ret;
1404+
err:
1405+
kfree(eq);
1406+
return ret;
1407+
}
13091408

13101409
/*
13111410
* Generic widget loader.
@@ -1403,12 +1502,14 @@ static int sof_widget_ready(struct snd_soc_component *scomp, int index,
14031502
case snd_soc_dapm_siggen:
14041503
ret = sof_widget_load_siggen(scomp, index, swidget, tw, &reply);
14051504
break;
1505+
case snd_soc_dapm_effect:
1506+
ret = sof_widget_load_effect(scomp, index, swidget, tw, &reply);
1507+
break;
14061508
case snd_soc_dapm_mux:
14071509
case snd_soc_dapm_demux:
14081510
case snd_soc_dapm_switch:
14091511
case snd_soc_dapm_dai_link:
14101512
case snd_soc_dapm_kcontrol:
1411-
case snd_soc_dapm_effect:
14121513
default:
14131514
dev_warn(sdev->dev, "warning: widget type %d name %s not handled\n",
14141515
swidget->id, tw->name);
@@ -2110,7 +2211,7 @@ static const struct snd_soc_tplg_kcontrol_ops sof_io_ops[] = {
21102211

21112212
/* vendor specific bytes ext handlers available for binding */
21122213
static const struct snd_soc_tplg_bytes_ext_ops sof_bytes_ext_ops[] = {
2113-
{},
2214+
{SOF_TPLG_KCTL_BYTES_ID, snd_sof_bytes_ext_get, snd_sof_bytes_ext_put},
21142215
};
21152216

21162217
static struct snd_soc_tplg_ops sof_tplg_ops = {

0 commit comments

Comments
 (0)