Uh oh!
There was an error while loading. Please reload this page.
- Notifications
You must be signed in to change notification settings - Fork 150
Add multicore support#350
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Uh oh!
There was an error while loading. Please reload this page.
Changes from all commits
c0727d21bd442ecc7def2c3a0929cbe6b10d589c42da91011File filter
Filter by extension
Conversations
Uh oh!
There was an error while loading. Please reload this page.
Jump to
Uh oh!
There was an error while loading. Please reload this page.
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -70,6 +70,7 @@ static int sof_restore_pipelines(struct snd_sof_dev *sdev) | ||
| { | ||
| struct snd_sof_widget *swidget = NULL; | ||
| struct snd_sof_route *sroute = NULL; | ||
| struct sof_ipc_pipe_new *pipeline; | ||
| struct snd_sof_dai *dai; | ||
| struct sof_ipc_comp_dai *comp_dai; | ||
| struct sof_ipc_hdr *hdr; | ||
| @@ -94,6 +95,17 @@ static int sof_restore_pipelines(struct snd_sof_dev *sdev) | ||
| comp_dai, sizeof(*comp_dai), | ||
| &r, sizeof(r)); | ||
| break; | ||
| case snd_soc_dapm_scheduler: | ||
| /* | ||
| * During suspend, all DSP cores are powered off. | ||
| * Therefore upon resume, create the pipeline comp | ||
| * and power up the core that the pipeline is | ||
| * scheduled on. | ||
| */ | ||
| pipeline = (struct sof_ipc_pipe_new *)swidget->private; | ||
| ret = sof_load_pipeline_ipc(sdev, pipeline, &r); | ||
| break; | ||
plbossart marked this conversation as resolved.
Outdated
Uh oh!There was an error while loading. Please reload this page. | ||
| default: | ||
| hdr = (struct sof_ipc_hdr *)swidget->private; | ||
| ret = sof_ipc_tx_message(sdev->ipc, hdr->cmd, | ||
| @@ -338,7 +350,7 @@ static int sof_suspend(struct device *dev, int runtime_suspend) | ||
| /* drop all ipc */ | ||
| sof_ipc_drop_all(sdev->ipc); | ||
| /* power down DSP */ | ||
| /* power down all DSP cores */ | ||
| if (runtime_suspend) | ||
| ret = snd_sof_dsp_runtime_suspend(sdev, 0); | ||
| else | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -85,6 +85,10 @@ struct snd_sof_dsp_ops { | ||
| int (*run)(struct snd_sof_dev *sof_dev); | ||
| int (*stall)(struct snd_sof_dev *sof_dev); | ||
| int (*reset)(struct snd_sof_dev *sof_dev); | ||
| int (*core_power_up)(struct snd_sof_dev *sof_dev, | ||
| unsigned int core_mask); | ||
| int (*core_power_down)(struct snd_sof_dev *sof_dev, | ||
| unsigned int core_mask); | ||
| /* pre/post firmware run */ | ||
| int (*pre_fw_run)(struct snd_sof_dev *sof_dev); | ||
| @@ -489,6 +493,10 @@ void snd_sof_free_topology(struct snd_sof_dev *sdev); | ||
| int snd_sof_complete_pipeline(struct snd_sof_dev *sdev, | ||
| struct snd_sof_widget *swidget); | ||
| int sof_load_pipeline_ipc(struct snd_sof_dev *sdev, | ||
| struct sof_ipc_pipe_new *pipeline, | ||
| struct sof_ipc_comp_reply *r); | ||
plbossart marked this conversation as resolved.
Outdated
Uh oh!There was an error while loading. Please reload this page. | ||
| /* | ||
| * Trace/debug | ||
| */ | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -24,6 +24,7 @@ | ||
| #include <uapi/sound/tlv.h> | ||
| #include <uapi/sound/sof/tokens.h> | ||
| #include "sof-priv.h" | ||
| #include "ops.h" | ||
| #define COMP_ID_UNASSIGNED 0xffffffff | ||
| /* Constants used in the computation of linear volume gain from dB gain */ | ||
| @@ -1088,6 +1089,48 @@ static int sof_widget_load_pcm(struct snd_soc_component *scomp, int index, | ||
| /* | ||
| * Pipeline Topology | ||
| */ | ||
| int sof_load_pipeline_ipc(struct snd_sof_dev *sdev, | ||
| struct sof_ipc_pipe_new *pipeline, | ||
| struct sof_ipc_comp_reply *r) | ||
| { | ||
| struct sof_ipc_pm_core_config pm_core_config; | ||
| int ret = 0; | ||
| ret = sof_ipc_tx_message(sdev->ipc, pipeline->hdr.cmd, pipeline, | ||
| sizeof(*pipeline), r, sizeof(*r)); | ||
| if (ret < 0) { | ||
| dev_err(sdev->dev, "error: load pipeline ipc failure\n"); | ||
| return ret; | ||
| } | ||
| /* power up the core that this pipeline is scheduled on */ | ||
| ret = snd_sof_dsp_core_power_up(sdev, 1 << pipeline->core); | ||
| if (ret < 0) { | ||
| dev_err(sdev->dev, "error: powering up pipeline schedule core %d\n", | ||
| pipeline->core); | ||
| return ret; | ||
| } | ||
| /* | ||
| * Now notify DSP that the core that this pipeline is scheduled on | ||
| * has been powered up | ||
| */ | ||
| memset(&pm_core_config, 0, sizeof(pm_core_config)); | ||
| pm_core_config.enable_mask = 1 << pipeline->core; | ||
| /* configure CORE_ENABLE ipc message */ | ||
| pm_core_config.hdr.size = sizeof(pm_core_config); | ||
| pm_core_config.hdr.cmd = SOF_IPC_GLB_PM_MSG | SOF_IPC_PM_CORE_ENABLE; | ||
| /* send ipc */ | ||
| ret = sof_ipc_tx_message(sdev->ipc, pm_core_config.hdr.cmd, | ||
| &pm_core_config, sizeof(pm_core_config), | ||
| &pm_core_config, sizeof(pm_core_config)); | ||
| if (ret < 0) | ||
| dev_err(sdev->dev, "error: core enable ipc failure\n"); | ||
| return ret; | ||
| } | ||
| static int sof_widget_load_pipeline(struct snd_soc_component *scomp, | ||
| int index, struct snd_sof_widget *swidget, | ||
| @@ -1139,8 +1182,8 @@ static int sof_widget_load_pipeline(struct snd_soc_component *scomp, | ||
| swidget->private = (void *)pipeline; | ||
| ret = sof_ipc_tx_message(sdev->ipc, pipeline->hdr.cmd, pipeline, | ||
| sizeof(*pipeline), r, sizeof(*r)); | ||
| /* send ipc's to create pipeline comp and power up schedule core */ | ||
| ret = sof_load_pipeline_ipc(sdev, pipeline, r); | ||
| if (ret >= 0) | ||
| return ret; | ||
| err: | ||
| @@ -1742,12 +1785,15 @@ static int sof_widget_ready(struct snd_soc_component *scomp, int index, | ||
| static int sof_widget_unload(struct snd_soc_component *scomp, | ||
| struct snd_soc_dobj *dobj) | ||
| { | ||
| struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(scomp); | ||
| const struct snd_kcontrol_new *kc = NULL; | ||
| struct snd_soc_dapm_widget *widget; | ||
| struct sof_ipc_pipe_new *pipeline; | ||
| struct snd_sof_control *scontrol; | ||
| struct snd_sof_widget *swidget; | ||
| struct soc_mixer_control *sm; | ||
| struct snd_sof_dai *dai; | ||
| int ret = 0; | ||
| swidget = dobj->private; | ||
| if (!swidget) | ||
| @@ -1758,17 +1804,23 @@ static int sof_widget_unload(struct snd_soc_component *scomp, | ||
| switch (swidget->id) { | ||
| case snd_soc_dapm_dai_in: | ||
| case snd_soc_dapm_dai_out: | ||
| dai = swidget->private; | ||
| /* free dai config */ | ||
| kfree(dai->dai_config); | ||
| dai = (struct snd_sof_dai *)swidget->private; | ||
| /* remove and free dai object */ | ||
| if (dai) { | ||
| /* free dai config */ | ||
| kfree(dai->dai_config); | ||
plbossart marked this conversation as resolved.
Outdated
Uh oh!There was an error while loading. Please reload this page. | ||
| list_del(&dai->list); | ||
| kfree(dai); | ||
| } | ||
| break; | ||
| case snd_soc_dapm_scheduler: | ||
| /* power down the pipeline schedule core */ | ||
| pipeline = (struct sof_ipc_pipe_new *)swidget->private; | ||
| ret = snd_sof_dsp_core_power_down(sdev, 1 << pipeline->core); | ||
| if (ret < 0) | ||
| dev_err(sdev->dev, "error: powering down pipeline schedule core %d\n", | ||
| pipeline->core); | ||
| break; | ||
plbossart marked this conversation as resolved.
Outdated
Uh oh!There was an error while loading. Please reload this page. | ||
| case snd_soc_dapm_pga: | ||
| /* get volume kcontrol */ | ||
| @@ -1778,19 +1830,19 @@ static int sof_widget_unload(struct snd_soc_component *scomp, | ||
| /* free volume table */ | ||
| kfree(scontrol->volume_table); | ||
| /* fallthrough */ | ||
| break; | ||
plbossart marked this conversation as resolved.
Outdated
Uh oh!There was an error while loading. Please reload this page. | ||
| default: | ||
| /* free private value */ | ||
| kfree(swidget->private); | ||
| break; | ||
| } | ||
| /* free private value */ | ||
| kfree(swidget->private); | ||
| /* remove and free swidget object */ | ||
| list_del(&swidget->list); | ||
| kfree(swidget); | ||
| return 0; | ||
| return ret; | ||
| } | ||
| /* | ||
Uh oh!
There was an error while loading. Please reload this page.