AsoC: SOF: refactor control load code
Move code around to enable token parsing in control load. Signed-off-by: Jaska Uimonen <jaska.uimonen@linux.intel.com> Signed-off-by: Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com> Link: https://lore.kernel.org/r/20191008164443.1358-9-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown <broonie@kernel.org>
This commit is contained in:
committed by
Mark Brown
parent
a68c6b6cc7
commit
acf1b71cb6
@@ -432,163 +432,6 @@ static enum sof_comp_type find_process_comp_type(enum sof_ipc_process_type type)
|
|||||||
return SOF_COMP_NONE;
|
return SOF_COMP_NONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* Standard Kcontrols.
|
|
||||||
*/
|
|
||||||
|
|
||||||
static int sof_control_load_volume(struct snd_soc_component *scomp,
|
|
||||||
struct snd_sof_control *scontrol,
|
|
||||||
struct snd_kcontrol_new *kc,
|
|
||||||
struct snd_soc_tplg_ctl_hdr *hdr)
|
|
||||||
{
|
|
||||||
struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(scomp);
|
|
||||||
struct snd_soc_tplg_mixer_control *mc =
|
|
||||||
container_of(hdr, struct snd_soc_tplg_mixer_control, hdr);
|
|
||||||
struct sof_ipc_ctrl_data *cdata;
|
|
||||||
int tlv[TLV_ITEMS];
|
|
||||||
unsigned int i;
|
|
||||||
int ret;
|
|
||||||
|
|
||||||
/* validate topology data */
|
|
||||||
if (le32_to_cpu(mc->num_channels) > SND_SOC_TPLG_MAX_CHAN)
|
|
||||||
return -EINVAL;
|
|
||||||
|
|
||||||
/* init the volume get/put data */
|
|
||||||
scontrol->size = struct_size(scontrol->control_data, chanv,
|
|
||||||
le32_to_cpu(mc->num_channels));
|
|
||||||
scontrol->control_data = kzalloc(scontrol->size, GFP_KERNEL);
|
|
||||||
if (!scontrol->control_data)
|
|
||||||
return -ENOMEM;
|
|
||||||
|
|
||||||
scontrol->comp_id = sdev->next_comp_id;
|
|
||||||
scontrol->min_volume_step = le32_to_cpu(mc->min);
|
|
||||||
scontrol->max_volume_step = le32_to_cpu(mc->max);
|
|
||||||
scontrol->num_channels = le32_to_cpu(mc->num_channels);
|
|
||||||
|
|
||||||
/* set cmd for mixer control */
|
|
||||||
if (le32_to_cpu(mc->max) == 1) {
|
|
||||||
scontrol->cmd = SOF_CTRL_CMD_SWITCH;
|
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
|
|
||||||
scontrol->cmd = SOF_CTRL_CMD_VOLUME;
|
|
||||||
|
|
||||||
/* extract tlv data */
|
|
||||||
if (get_tlv_data(kc->tlv.p, tlv) < 0) {
|
|
||||||
dev_err(sdev->dev, "error: invalid TLV data\n");
|
|
||||||
return -EINVAL;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* set up volume table */
|
|
||||||
ret = set_up_volume_table(scontrol, tlv, le32_to_cpu(mc->max) + 1);
|
|
||||||
if (ret < 0) {
|
|
||||||
dev_err(sdev->dev, "error: setting up volume table\n");
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* set default volume values to 0dB in control */
|
|
||||||
cdata = scontrol->control_data;
|
|
||||||
for (i = 0; i < scontrol->num_channels; i++) {
|
|
||||||
cdata->chanv[i].channel = i;
|
|
||||||
cdata->chanv[i].value = VOL_ZERO_DB;
|
|
||||||
}
|
|
||||||
|
|
||||||
out:
|
|
||||||
dev_dbg(sdev->dev, "tplg: load kcontrol index %d chans %d\n",
|
|
||||||
scontrol->comp_id, scontrol->num_channels);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int sof_control_load_enum(struct snd_soc_component *scomp,
|
|
||||||
struct snd_sof_control *scontrol,
|
|
||||||
struct snd_kcontrol_new *kc,
|
|
||||||
struct snd_soc_tplg_ctl_hdr *hdr)
|
|
||||||
{
|
|
||||||
struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(scomp);
|
|
||||||
struct snd_soc_tplg_enum_control *ec =
|
|
||||||
container_of(hdr, struct snd_soc_tplg_enum_control, hdr);
|
|
||||||
|
|
||||||
/* validate topology data */
|
|
||||||
if (le32_to_cpu(ec->num_channels) > SND_SOC_TPLG_MAX_CHAN)
|
|
||||||
return -EINVAL;
|
|
||||||
|
|
||||||
/* init the enum get/put data */
|
|
||||||
scontrol->size = struct_size(scontrol->control_data, chanv,
|
|
||||||
le32_to_cpu(ec->num_channels));
|
|
||||||
scontrol->control_data = kzalloc(scontrol->size, GFP_KERNEL);
|
|
||||||
if (!scontrol->control_data)
|
|
||||||
return -ENOMEM;
|
|
||||||
|
|
||||||
scontrol->comp_id = sdev->next_comp_id;
|
|
||||||
scontrol->num_channels = le32_to_cpu(ec->num_channels);
|
|
||||||
|
|
||||||
scontrol->cmd = SOF_CTRL_CMD_ENUM;
|
|
||||||
|
|
||||||
dev_dbg(sdev->dev, "tplg: load kcontrol index %d chans %d comp_id %d\n",
|
|
||||||
scontrol->comp_id, scontrol->num_channels, scontrol->comp_id);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int sof_control_load_bytes(struct snd_soc_component *scomp,
|
|
||||||
struct snd_sof_control *scontrol,
|
|
||||||
struct snd_kcontrol_new *kc,
|
|
||||||
struct snd_soc_tplg_ctl_hdr *hdr)
|
|
||||||
{
|
|
||||||
struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(scomp);
|
|
||||||
struct sof_ipc_ctrl_data *cdata;
|
|
||||||
struct snd_soc_tplg_bytes_control *control =
|
|
||||||
container_of(hdr, struct snd_soc_tplg_bytes_control, hdr);
|
|
||||||
struct soc_bytes_ext *sbe = (struct soc_bytes_ext *)kc->private_value;
|
|
||||||
int max_size = sbe->max;
|
|
||||||
|
|
||||||
if (le32_to_cpu(control->priv.size) > max_size) {
|
|
||||||
dev_err(sdev->dev, "err: bytes data size %d exceeds max %d.\n",
|
|
||||||
control->priv.size, max_size);
|
|
||||||
return -EINVAL;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* init the get/put bytes data */
|
|
||||||
scontrol->size = sizeof(struct sof_ipc_ctrl_data) +
|
|
||||||
le32_to_cpu(control->priv.size);
|
|
||||||
scontrol->control_data = kzalloc(max_size, GFP_KERNEL);
|
|
||||||
cdata = scontrol->control_data;
|
|
||||||
if (!scontrol->control_data)
|
|
||||||
return -ENOMEM;
|
|
||||||
|
|
||||||
scontrol->comp_id = sdev->next_comp_id;
|
|
||||||
scontrol->cmd = SOF_CTRL_CMD_BINARY;
|
|
||||||
|
|
||||||
dev_dbg(sdev->dev, "tplg: load kcontrol index %d chans %d\n",
|
|
||||||
scontrol->comp_id, scontrol->num_channels);
|
|
||||||
|
|
||||||
if (le32_to_cpu(control->priv.size) > 0) {
|
|
||||||
memcpy(cdata->data, control->priv.data,
|
|
||||||
le32_to_cpu(control->priv.size));
|
|
||||||
|
|
||||||
if (cdata->data->magic != SOF_ABI_MAGIC) {
|
|
||||||
dev_err(sdev->dev, "error: Wrong ABI magic 0x%08x.\n",
|
|
||||||
cdata->data->magic);
|
|
||||||
return -EINVAL;
|
|
||||||
}
|
|
||||||
if (SOF_ABI_VERSION_INCOMPATIBLE(SOF_ABI_VERSION,
|
|
||||||
cdata->data->abi)) {
|
|
||||||
dev_err(sdev->dev,
|
|
||||||
"error: Incompatible ABI version 0x%08x.\n",
|
|
||||||
cdata->data->abi);
|
|
||||||
return -EINVAL;
|
|
||||||
}
|
|
||||||
if (cdata->data->size + sizeof(const struct sof_abi_hdr) !=
|
|
||||||
le32_to_cpu(control->priv.size)) {
|
|
||||||
dev_err(sdev->dev,
|
|
||||||
"error: Conflict in bytes vs. priv size.\n");
|
|
||||||
return -EINVAL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Topology Token Parsing.
|
* Topology Token Parsing.
|
||||||
* New tokens should be added to headers and parsing tables below.
|
* New tokens should be added to headers and parsing tables below.
|
||||||
@@ -1039,6 +882,163 @@ static void sof_dbg_comp_config(struct snd_soc_component *scomp,
|
|||||||
config->frame_fmt);
|
config->frame_fmt);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Standard Kcontrols.
|
||||||
|
*/
|
||||||
|
|
||||||
|
static int sof_control_load_volume(struct snd_soc_component *scomp,
|
||||||
|
struct snd_sof_control *scontrol,
|
||||||
|
struct snd_kcontrol_new *kc,
|
||||||
|
struct snd_soc_tplg_ctl_hdr *hdr)
|
||||||
|
{
|
||||||
|
struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(scomp);
|
||||||
|
struct snd_soc_tplg_mixer_control *mc =
|
||||||
|
container_of(hdr, struct snd_soc_tplg_mixer_control, hdr);
|
||||||
|
struct sof_ipc_ctrl_data *cdata;
|
||||||
|
int tlv[TLV_ITEMS];
|
||||||
|
unsigned int i;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
/* validate topology data */
|
||||||
|
if (le32_to_cpu(mc->num_channels) > SND_SOC_TPLG_MAX_CHAN)
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
/* init the volume get/put data */
|
||||||
|
scontrol->size = struct_size(scontrol->control_data, chanv,
|
||||||
|
le32_to_cpu(mc->num_channels));
|
||||||
|
scontrol->control_data = kzalloc(scontrol->size, GFP_KERNEL);
|
||||||
|
if (!scontrol->control_data)
|
||||||
|
return -ENOMEM;
|
||||||
|
|
||||||
|
scontrol->comp_id = sdev->next_comp_id;
|
||||||
|
scontrol->min_volume_step = le32_to_cpu(mc->min);
|
||||||
|
scontrol->max_volume_step = le32_to_cpu(mc->max);
|
||||||
|
scontrol->num_channels = le32_to_cpu(mc->num_channels);
|
||||||
|
|
||||||
|
/* set cmd for mixer control */
|
||||||
|
if (le32_to_cpu(mc->max) == 1) {
|
||||||
|
scontrol->cmd = SOF_CTRL_CMD_SWITCH;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
scontrol->cmd = SOF_CTRL_CMD_VOLUME;
|
||||||
|
|
||||||
|
/* extract tlv data */
|
||||||
|
if (get_tlv_data(kc->tlv.p, tlv) < 0) {
|
||||||
|
dev_err(sdev->dev, "error: invalid TLV data\n");
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* set up volume table */
|
||||||
|
ret = set_up_volume_table(scontrol, tlv, le32_to_cpu(mc->max) + 1);
|
||||||
|
if (ret < 0) {
|
||||||
|
dev_err(sdev->dev, "error: setting up volume table\n");
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* set default volume values to 0dB in control */
|
||||||
|
cdata = scontrol->control_data;
|
||||||
|
for (i = 0; i < scontrol->num_channels; i++) {
|
||||||
|
cdata->chanv[i].channel = i;
|
||||||
|
cdata->chanv[i].value = VOL_ZERO_DB;
|
||||||
|
}
|
||||||
|
|
||||||
|
out:
|
||||||
|
dev_dbg(sdev->dev, "tplg: load kcontrol index %d chans %d\n",
|
||||||
|
scontrol->comp_id, scontrol->num_channels);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int sof_control_load_enum(struct snd_soc_component *scomp,
|
||||||
|
struct snd_sof_control *scontrol,
|
||||||
|
struct snd_kcontrol_new *kc,
|
||||||
|
struct snd_soc_tplg_ctl_hdr *hdr)
|
||||||
|
{
|
||||||
|
struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(scomp);
|
||||||
|
struct snd_soc_tplg_enum_control *ec =
|
||||||
|
container_of(hdr, struct snd_soc_tplg_enum_control, hdr);
|
||||||
|
|
||||||
|
/* validate topology data */
|
||||||
|
if (le32_to_cpu(ec->num_channels) > SND_SOC_TPLG_MAX_CHAN)
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
/* init the enum get/put data */
|
||||||
|
scontrol->size = struct_size(scontrol->control_data, chanv,
|
||||||
|
le32_to_cpu(ec->num_channels));
|
||||||
|
scontrol->control_data = kzalloc(scontrol->size, GFP_KERNEL);
|
||||||
|
if (!scontrol->control_data)
|
||||||
|
return -ENOMEM;
|
||||||
|
|
||||||
|
scontrol->comp_id = sdev->next_comp_id;
|
||||||
|
scontrol->num_channels = le32_to_cpu(ec->num_channels);
|
||||||
|
|
||||||
|
scontrol->cmd = SOF_CTRL_CMD_ENUM;
|
||||||
|
|
||||||
|
dev_dbg(sdev->dev, "tplg: load kcontrol index %d chans %d comp_id %d\n",
|
||||||
|
scontrol->comp_id, scontrol->num_channels, scontrol->comp_id);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int sof_control_load_bytes(struct snd_soc_component *scomp,
|
||||||
|
struct snd_sof_control *scontrol,
|
||||||
|
struct snd_kcontrol_new *kc,
|
||||||
|
struct snd_soc_tplg_ctl_hdr *hdr)
|
||||||
|
{
|
||||||
|
struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(scomp);
|
||||||
|
struct sof_ipc_ctrl_data *cdata;
|
||||||
|
struct snd_soc_tplg_bytes_control *control =
|
||||||
|
container_of(hdr, struct snd_soc_tplg_bytes_control, hdr);
|
||||||
|
struct soc_bytes_ext *sbe = (struct soc_bytes_ext *)kc->private_value;
|
||||||
|
int max_size = sbe->max;
|
||||||
|
|
||||||
|
if (le32_to_cpu(control->priv.size) > max_size) {
|
||||||
|
dev_err(sdev->dev, "err: bytes data size %d exceeds max %d.\n",
|
||||||
|
control->priv.size, max_size);
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* init the get/put bytes data */
|
||||||
|
scontrol->size = sizeof(struct sof_ipc_ctrl_data) +
|
||||||
|
le32_to_cpu(control->priv.size);
|
||||||
|
scontrol->control_data = kzalloc(max_size, GFP_KERNEL);
|
||||||
|
cdata = scontrol->control_data;
|
||||||
|
if (!scontrol->control_data)
|
||||||
|
return -ENOMEM;
|
||||||
|
|
||||||
|
scontrol->comp_id = sdev->next_comp_id;
|
||||||
|
scontrol->cmd = SOF_CTRL_CMD_BINARY;
|
||||||
|
|
||||||
|
dev_dbg(sdev->dev, "tplg: load kcontrol index %d chans %d\n",
|
||||||
|
scontrol->comp_id, scontrol->num_channels);
|
||||||
|
|
||||||
|
if (le32_to_cpu(control->priv.size) > 0) {
|
||||||
|
memcpy(cdata->data, control->priv.data,
|
||||||
|
le32_to_cpu(control->priv.size));
|
||||||
|
|
||||||
|
if (cdata->data->magic != SOF_ABI_MAGIC) {
|
||||||
|
dev_err(sdev->dev, "error: Wrong ABI magic 0x%08x.\n",
|
||||||
|
cdata->data->magic);
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
if (SOF_ABI_VERSION_INCOMPATIBLE(SOF_ABI_VERSION,
|
||||||
|
cdata->data->abi)) {
|
||||||
|
dev_err(sdev->dev,
|
||||||
|
"error: Incompatible ABI version 0x%08x.\n",
|
||||||
|
cdata->data->abi);
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
if (cdata->data->size + sizeof(const struct sof_abi_hdr) !=
|
||||||
|
le32_to_cpu(control->priv.size)) {
|
||||||
|
dev_err(sdev->dev,
|
||||||
|
"error: Conflict in bytes vs. priv size.\n");
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
/* external kcontrol init - used for any driver specific init */
|
/* external kcontrol init - used for any driver specific init */
|
||||||
static int sof_control_load(struct snd_soc_component *scomp, int index,
|
static int sof_control_load(struct snd_soc_component *scomp, int index,
|
||||||
struct snd_kcontrol_new *kc,
|
struct snd_kcontrol_new *kc,
|
||||||
|
|||||||
Reference in New Issue
Block a user