+static struct audioreach_module *audioreach_tplg_alloc_module(struct q6apm *apm,
struct audioreach_container *cont,
struct snd_soc_dapm_widget *w,
uint32_t module_id, bool *found)
+{
- struct audioreach_module *mod;
- int ret;
- mutex_lock(&apm->lock);
- mod = idr_find(&apm->modules_idr, module_id);
- mutex_unlock(&apm->lock);
- if (mod) {
*found = true;
return mod;
- }
- *found = false;
- mod = kzalloc(sizeof(*mod), GFP_KERNEL);
- if (!mod)
return ERR_PTR(-ENOMEM);
- mutex_lock(&apm->lock);
- if (!module_id) { /* alloc module id dynamically */
ret = idr_alloc_cyclic(&apm->modules_idr, mod,
AR_MODULE_DYNAMIC_INSTANCE_ID_START,
AR_MODULE_DYNAMIC_INSTANCE_ID_END, GFP_KERNEL);
- } else {
ret = idr_alloc(&apm->modules_idr, mod, module_id, module_id + 1, GFP_KERNEL);
- }
- mutex_unlock(&apm->lock);
- if (ret < 0) {
dev_err(apm->dev,
"Failed to allocate Module Instance ID (%x)\n", module_id);
kfree(mod);
return ERR_PTR(ret);
- }
- mod->instance_id = ret;
- dev_err(apm->dev, "Module Instance ID (0x%08x) allocated\n", ret);
dev_dbg?
- /* add to module list */
- list_add_tail(&mod->node, &cont->modules_list);
- mod->container = cont;
- mod->widget = w;
- cont->num_modules++;
- return mod;
+}
+static struct audioreach_sub_graph *audioreach_parse_sg_tokens(struct q6apm *apm,
struct snd_soc_tplg_private *private)
+{
- struct snd_soc_tplg_vendor_value_elem *sg_elem;
- struct snd_soc_tplg_vendor_array *sg_array;
- struct audioreach_graph_info *info = NULL;
- int graph_id, sub_graph_id, tkn_count = 0;
- struct audioreach_sub_graph *sg;
- bool found;
- sg_array = audioreach_get_sg_array(private);
- sg_elem = sg_array->value;
- while (tkn_count <= (le32_to_cpu(sg_array->num_elems) - 1)) {
switch (le32_to_cpu(sg_elem->token)) {
case AR_TKN_U32_SUB_GRAPH_INSTANCE_ID:
sub_graph_id = le32_to_cpu(sg_elem->value);
sg = audioreach_tplg_alloc_sub_graph(apm, sub_graph_id, &found);
if (IS_ERR(sg)) {
return sg;
} else if (found) {
/* Already parsed data for this sub-graph */
return sg;
}
dev_err(apm->dev, "%s: New subgraph id : 0x%08x\n", __func__,
sub_graph_id);
dev_dbg()
break;
case AR_TKN_DAI_INDEX:
/* Sub graph is associated with predefined graph */
graph_id = le32_to_cpu(sg_elem->value);
info = audioreach_tplg_alloc_graph_info(apm, graph_id, &found);
if (IS_ERR(info))
return ERR_CAST(info);
break;
case AR_TKN_U32_SUB_GRAPH_PERF_MODE:
sg->perf_mode = le32_to_cpu(sg_elem->value);
break;
case AR_TKN_U32_SUB_GRAPH_DIRECTION:
sg->direction = le32_to_cpu(sg_elem->value);
break;
case AR_TKN_U32_SUB_GRAPH_SCENARIO_ID:
sg->scenario_id = le32_to_cpu(sg_elem->value);
break;
default:
dev_err(apm->dev, "Not a valid token %d for graph\n",
sg_elem->token);
break;
}
tkn_count++;
sg_elem++;
- }
- /* Sub graph is associated with predefined graph */
- if (info) {
dev_err(apm->dev, "%s: adding subgraph id : 0x%08x -> %d\n", __func__,
sub_graph_id, graph_id);
dev_dbg
audioreach_tplg_add_sub_graph(sg, info);
- }
- return sg;
+}
+static int audioreach_widget_ready(struct snd_soc_component *component,
int index, struct snd_soc_dapm_widget *w,
struct snd_soc_tplg_dapm_widget *tplg_w)
+{
- switch (w->id) {
- case snd_soc_dapm_aif_in:
- case snd_soc_dapm_aif_out:
audioreach_widget_load_buffer(component, index, w, tplg_w);
break;
- case snd_soc_dapm_decoder:
- case snd_soc_dapm_encoder:
- case snd_soc_dapm_src:
audioreach_widget_load_enc_dec_cnv(component, index, w, tplg_w);
break;
- case snd_soc_dapm_buffer:
audioreach_widget_load_buffer(component, index, w, tplg_w);
break;
- case snd_soc_dapm_mixer:
return audioreach_widget_load_mixer(component, index, w, tplg_w);
- case snd_soc_dapm_pga:
return audioreach_widget_load_pga(component, index, w, tplg_w);
- case snd_soc_dapm_dai_link:
- case snd_soc_dapm_scheduler:
- case snd_soc_dapm_out_drv:
- default:
dev_err(component->dev, "Widget type (0x%x) not yet supported\n", w->id);
break;
- }
- return 0;
+}
spurious newline
+static int audioreach_widget_unload(struct snd_soc_component *scomp,
struct snd_soc_dobj *dobj)
+{
- struct snd_soc_dapm_widget *w = container_of(dobj, struct snd_soc_dapm_widget, dobj);
- struct q6apm *apm = dev_get_drvdata(scomp->dev);
- struct audioreach_container *cont;
- struct audioreach_module *mod;
- mod = dobj->private;
- cont = mod->container;
- if (w->id == snd_soc_dapm_mixer) {
/* virtual widget */
kfree(dobj->private);
return 0;
- }
- mutex_lock(&apm->lock);
- idr_remove(&apm->modules_idr, mod->instance_id);
- cont->num_modules--;
- list_del(&mod->node);
- kfree(mod);
- if (list_empty(&cont->modules_list)) { /* remove container */
struct audioreach_sub_graph *sg = cont->sub_graph;
idr_remove(&apm->containers_idr, cont->container_id);
list_del(&cont->node);
sg->num_containers--;
kfree(cont);
if (list_empty(&sg->container_list)) { /* remove sg */
struct audioreach_graph_info *info = sg->info;
idr_remove(&apm->sub_graphs_idr, sg->sub_graph_id);
list_del(&sg->node);
info->num_sub_graphs--;
kfree(sg);
if (list_empty(&info->sg_list)) { /* remove graph info */
idr_remove(&apm->graph_info_idr, info->id);
kfree(info);
}
}
- }
It's not very clear if the nested removes actually free-up everything? You may want to add a comment on the hierarchy.
- mutex_unlock(&apm->lock);
- return 0;
+}
+int audioreach_tplg_init(struct snd_soc_component *component) +{
- struct snd_soc_card *card = component->card;
- struct device *dev = component->dev;
- const struct firmware *fw;
- char tplg_fw_name[128];
- int ret;
- /* Inline with Qualcomm UCM configs and linux-firmware path */
- snprintf(tplg_fw_name, sizeof(tplg_fw_name), "qcom/%s/%s-tplg.bin", card->driver_name,
card->name);
use kasprintf instead of fixed 128-char array?
Also you should use a qcom/audioreach/ prefix to possible interference with other parts of qcom...
- ret = request_firmware(&fw, tplg_fw_name, dev);
- if (ret < 0) {
dev_info(dev, "loading %s failed %d, falling back to dfw-audioreach-tplg.bin\n",
tplg_fw_name, ret);
/* default firmware */
ret = request_firmware(&fw, "dfw-audioreach-tplg.bin", dev);
if (ret < 0) {
dev_err(dev, "tplg fw dfw-audioreach-tplg.bin load failed with %d\n", ret);
the dfw prefix isn't very helpful...Intel's example of "dfw_sst.bin" is a historical reference, not something you should reuse.
return ret;
}
- }
- ret = snd_soc_tplg_component_load(component, &audioreach_tplg_ops, fw);
- if (ret < 0) {
dev_err(dev, "tplg component load failed%d\n", ret);
ret = -EINVAL;
- }
- release_firmware(fw);
- return ret;
+} +EXPORT_SYMBOL_GPL(audioreach_tplg_init);