mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2024-11-26 05:34:13 +08:00
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:
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;
|
||||
}
|
||||
|
||||
/*
|
||||
* 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.
|
||||
* 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);
|
||||
}
|
||||
|
||||
/*
|
||||
* 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 */
|
||||
static int sof_control_load(struct snd_soc_component *scomp, int index,
|
||||
struct snd_kcontrol_new *kc,
|
||||
|
Loading…
Reference in New Issue
Block a user