summaryrefslogtreecommitdiff
path: root/sound/soc/sof
diff options
context:
space:
mode:
authorTakashi Iwai <tiwai@suse.de>2019-11-25 14:27:33 +0100
committerTakashi Iwai <tiwai@suse.de>2019-11-25 14:27:41 +0100
commit09578eacaaa44149738267083ccc050990409f86 (patch)
treecf614ee065fe5479e4638abebe12c9e1578b09d9 /sound/soc/sof
parentc6b6fc206586cc07a18595d2a3d815a806a057d0 (diff)
parent8c4d2a0bfbd27d030e4652b714cd5a1598f3559b (diff)
Merge tag 'asoc-v5.5-2' of https://git.kernel.org/pub/scm/linux/kernel/git/broonie/sound into for-linus
ASoC: More updates for v5.5 Some more development work for v5.5. Highlights include: - More cleanups from Morimoto-san. - Trigger word detection for RT5677. Signed-off-by: Takashi Iwai <tiwai@suse.de>
Diffstat (limited to 'sound/soc/sof')
-rw-r--r--sound/soc/sof/core.c13
-rw-r--r--sound/soc/sof/intel/Kconfig10
-rw-r--r--sound/soc/sof/intel/hda-dsp.c15
-rw-r--r--sound/soc/sof/intel/hda.c11
-rw-r--r--sound/soc/sof/intel/hda.h3
-rw-r--r--sound/soc/sof/pm.c39
-rw-r--r--sound/soc/sof/sof-pci-dev.c8
-rw-r--r--sound/soc/sof/sof-priv.h2
-rw-r--r--sound/soc/sof/topology.c72
9 files changed, 142 insertions, 31 deletions
diff --git a/sound/soc/sof/core.c b/sound/soc/sof/core.c
index 8661c2cca76b..805918d3bcc0 100644
--- a/sound/soc/sof/core.c
+++ b/sound/soc/sof/core.c
@@ -132,6 +132,19 @@ struct snd_sof_dai *snd_sof_find_dai(struct snd_sof_dev *sdev,
return NULL;
}
+bool snd_sof_dsp_d0i3_on_suspend(struct snd_sof_dev *sdev)
+{
+ struct snd_sof_pcm *spcm;
+
+ list_for_each_entry(spcm, &sdev->pcm_list, list) {
+ if (spcm->stream[SNDRV_PCM_STREAM_PLAYBACK].suspend_ignored ||
+ spcm->stream[SNDRV_PCM_STREAM_CAPTURE].suspend_ignored)
+ return true;
+ }
+
+ return false;
+}
+
/*
* FW Panic/fault handling.
*/
diff --git a/sound/soc/sof/intel/Kconfig b/sound/soc/sof/intel/Kconfig
index b27fd3fdf335..cc09bb606f7d 100644
--- a/sound/soc/sof/intel/Kconfig
+++ b/sound/soc/sof/intel/Kconfig
@@ -264,16 +264,16 @@ config SND_SOC_SOF_ELKHARTLAKE
config SND_SOC_SOF_JASPERLAKE_SUPPORT
bool "SOF support for JasperLake"
help
- This adds support for Sound Open Firmware for Intel(R) platforms
- using the JasperLake processors.
- Say Y if you have such a device.
- If unsure select "N".
+ This adds support for Sound Open Firmware for Intel(R) platforms
+ using the JasperLake processors.
+ Say Y if you have such a device.
+ If unsure select "N".
config SND_SOC_SOF_JASPERLAKE
tristate
select SND_SOC_SOF_HDA_COMMON
help
- This option is not user-selectable but automagically handled by
+ This option is not user-selectable but automagically handled by
'select' statements at a higher level
config SND_SOC_SOF_HDA_COMMON
diff --git a/sound/soc/sof/intel/hda-dsp.c b/sound/soc/sof/intel/hda-dsp.c
index 8cd5ecc01b62..4a4d318f97ff 100644
--- a/sound/soc/sof/intel/hda-dsp.c
+++ b/sound/soc/sof/intel/hda-dsp.c
@@ -478,9 +478,16 @@ static int hda_resume(struct snd_sof_dev *sdev, bool runtime_resume)
int hda_dsp_resume(struct snd_sof_dev *sdev)
{
+ struct sof_intel_hda_dev *hda = sdev->pdata->hw_pdata;
struct pci_dev *pci = to_pci_dev(sdev->dev);
if (sdev->s0_suspend) {
+ /* restore L1SEN bit */
+ if (hda->l1_support_changed)
+ snd_sof_dsp_update_bits(sdev, HDA_DSP_HDA_BAR,
+ HDA_VS_INTEL_EM2,
+ HDA_VS_INTEL_EM2_L1SEN, 0);
+
/* restore and disable the system wakeup */
pci_restore_state(pci);
disable_irq_wake(pci->irq);
@@ -518,11 +525,19 @@ int hda_dsp_runtime_suspend(struct snd_sof_dev *sdev)
int hda_dsp_suspend(struct snd_sof_dev *sdev)
{
+ struct sof_intel_hda_dev *hda = sdev->pdata->hw_pdata;
struct hdac_bus *bus = sof_to_bus(sdev);
struct pci_dev *pci = to_pci_dev(sdev->dev);
int ret;
if (sdev->s0_suspend) {
+ /* enable L1SEN to make sure the system can enter S0Ix */
+ hda->l1_support_changed =
+ snd_sof_dsp_update_bits(sdev, HDA_DSP_HDA_BAR,
+ HDA_VS_INTEL_EM2,
+ HDA_VS_INTEL_EM2_L1SEN,
+ HDA_VS_INTEL_EM2_L1SEN);
+
/* enable the system waking up via IPC IRQ */
enable_irq_wake(pci->irq);
pci_save_state(pci);
diff --git a/sound/soc/sof/intel/hda.c b/sound/soc/sof/intel/hda.c
index 7dc0018dc4c3..91bd88fddac7 100644
--- a/sound/soc/sof/intel/hda.c
+++ b/sound/soc/sof/intel/hda.c
@@ -415,9 +415,16 @@ static int hda_init_caps(struct snd_sof_dev *sdev)
pdata->tplg_filename =
hda_mach->sof_tplg_filename;
- /* firmware: pick the first in machine list */
+ /*
+ * firmware: pick the first in machine list,
+ * or use nocodec firmware name if list is empty
+ */
mach = pdata->desc->machines;
- pdata->fw_filename = mach->sof_fw_filename;
+ if (mach->id[0])
+ pdata->fw_filename = mach->sof_fw_filename;
+ else
+ pdata->fw_filename =
+ pdata->desc->nocodec_fw_filename;
dev_info(bus->dev, "using HDA machine driver %s now\n",
hda_mach->drv_name);
diff --git a/sound/soc/sof/intel/hda.h b/sound/soc/sof/intel/hda.h
index 5ad73a34b09c..18d7e72bf9b7 100644
--- a/sound/soc/sof/intel/hda.h
+++ b/sound/soc/sof/intel/hda.h
@@ -408,6 +408,9 @@ struct sof_intel_hda_dev {
int irq;
+ /* PM related */
+ bool l1_support_changed;/* during suspend, is L1SEN changed or not */
+
/* DMIC device */
struct platform_device *dmic_dev;
};
diff --git a/sound/soc/sof/pm.c b/sound/soc/sof/pm.c
index 560a937e0484..0fd5567237a8 100644
--- a/sound/soc/sof/pm.c
+++ b/sound/soc/sof/pm.c
@@ -416,6 +416,9 @@ int snd_sof_set_d0_substate(struct snd_sof_dev *sdev,
{
int ret;
+ if (sdev->d0_substate == d0_substate)
+ return 0;
+
/* do platform specific set_state */
ret = snd_sof_dsp_set_power_state(sdev, d0_substate);
if (ret < 0)
@@ -428,12 +431,44 @@ int snd_sof_set_d0_substate(struct snd_sof_dev *sdev,
}
EXPORT_SYMBOL(snd_sof_set_d0_substate);
+/*
+ * Audio DSP states may transform as below:-
+ *
+ * D0I3 compatible stream
+ * Runtime +---------------------+ opened only, timeout
+ * suspend | +--------------------+
+ * +------------+ D0(active) | |
+ * | | <---------------+ |
+ * | +--------> | | |
+ * | |Runtime +--^--+---------^--+--+ The last | |
+ * | |resume | | | | opened D0I3 | |
+ * | | | | | | compatible | |
+ * | | resume| | | | stream closed | |
+ * | | from | | D3 | | | |
+ * | | D3 | |suspend | | d0i3 | |
+ * | | | | | |suspend | |
+ * | | | | | | | |
+ * | | | | | | | |
+ * +-v---+-----------+--v-------+ | | +------+----v----+
+ * | | | +-----------> |
+ * | D3 (suspended) | | | D0I3 +-----+
+ * | | +--------------+ | |
+ * | | resume from | | |
+ * +-------------------^--------+ d0i3 suspend +----------------+ |
+ * | |
+ * | D3 suspend |
+ * +------------------------------------------------+
+ *
+ * d0i3_suspend = s0_suspend && D0I3 stream opened,
+ * D3 suspend = !d0i3_suspend,
+ */
+
int snd_sof_resume(struct device *dev)
{
struct snd_sof_dev *sdev = dev_get_drvdata(dev);
int ret;
- if (sdev->s0_suspend) {
+ if (snd_sof_dsp_d0i3_on_suspend(sdev)) {
/* resume from D0I3 */
dev_dbg(sdev->dev, "DSP will exit from D0i3...\n");
ret = snd_sof_set_d0_substate(sdev, SOF_DSP_D0I0);
@@ -462,7 +497,7 @@ int snd_sof_suspend(struct device *dev)
struct snd_sof_dev *sdev = dev_get_drvdata(dev);
int ret;
- if (sdev->s0_suspend) {
+ if (snd_sof_dsp_d0i3_on_suspend(sdev)) {
/* suspend to D0i3 */
dev_dbg(sdev->dev, "DSP is trying to enter D0i3...\n");
ret = snd_sof_set_d0_substate(sdev, SOF_DSP_D0I3);
diff --git a/sound/soc/sof/sof-pci-dev.c b/sound/soc/sof/sof-pci-dev.c
index 3b58b91e7b9e..bbeffd932de7 100644
--- a/sound/soc/sof/sof-pci-dev.c
+++ b/sound/soc/sof/sof-pci-dev.c
@@ -120,7 +120,7 @@ static const struct sof_dev_desc cnl_desc = {
#if IS_ENABLED(CONFIG_SND_SOC_SOF_COFFEELAKE)
static const struct sof_dev_desc cfl_desc = {
- .machines = snd_soc_acpi_intel_cnl_machines,
+ .machines = snd_soc_acpi_intel_cfl_machines,
.resindex_lpe_base = 0,
.resindex_pcicfg_base = -1,
.resindex_imr_base = -1,
@@ -129,7 +129,7 @@ static const struct sof_dev_desc cfl_desc = {
.chip_info = &cnl_chip_info,
.default_fw_path = "intel/sof",
.default_tplg_path = "intel/sof-tplg",
- .nocodec_fw_filename = "sof-cnl.ri",
+ .nocodec_fw_filename = "sof-cfl.ri",
.nocodec_tplg_filename = "sof-cnl-nocodec.tplg",
.ops = &sof_cnl_ops,
.arch_ops = &sof_xtensa_arch_ops
@@ -140,7 +140,7 @@ static const struct sof_dev_desc cfl_desc = {
IS_ENABLED(CONFIG_SND_SOC_SOF_COMETLAKE_H)
static const struct sof_dev_desc cml_desc = {
- .machines = snd_soc_acpi_intel_cnl_machines,
+ .machines = snd_soc_acpi_intel_cml_machines,
.resindex_lpe_base = 0,
.resindex_pcicfg_base = -1,
.resindex_imr_base = -1,
@@ -149,7 +149,7 @@ static const struct sof_dev_desc cml_desc = {
.chip_info = &cnl_chip_info,
.default_fw_path = "intel/sof",
.default_tplg_path = "intel/sof-tplg",
- .nocodec_fw_filename = "sof-cnl.ri",
+ .nocodec_fw_filename = "sof-cml.ri",
.nocodec_tplg_filename = "sof-cnl-nocodec.tplg",
.ops = &sof_cnl_ops,
.arch_ops = &sof_xtensa_arch_ops
diff --git a/sound/soc/sof/sof-priv.h b/sound/soc/sof/sof-priv.h
index 6408ac88a3e5..c7c2c70ee4d0 100644
--- a/sound/soc/sof/sof-priv.h
+++ b/sound/soc/sof/sof-priv.h
@@ -553,6 +553,8 @@ struct snd_sof_pcm *snd_sof_find_spcm_dai(struct snd_sof_dev *sdev,
return NULL;
}
+bool snd_sof_dsp_d0i3_on_suspend(struct snd_sof_dev *sdev);
+
struct snd_sof_pcm *snd_sof_find_spcm_name(struct snd_sof_dev *sdev,
const char *name);
struct snd_sof_pcm *snd_sof_find_spcm_comp(struct snd_sof_dev *sdev,
diff --git a/sound/soc/sof/topology.c b/sound/soc/sof/topology.c
index 143b8259a70a..d82ab981e840 100644
--- a/sound/soc/sof/topology.c
+++ b/sound/soc/sof/topology.c
@@ -150,6 +150,11 @@ static int sof_keyword_dapm_event(struct snd_soc_dapm_widget *w,
/* get runtime PCM params using widget's stream name */
spcm = snd_sof_find_spcm_name(sdev, swidget->widget->sname);
+ if (!spcm) {
+ dev_err(sdev->dev, "error: cannot find PCM for %s\n",
+ swidget->widget->name);
+ return -EINVAL;
+ }
/* process events */
switch (event) {
@@ -937,18 +942,22 @@ static int sof_control_load_volume(struct snd_soc_component *scomp,
struct sof_ipc_ctrl_data *cdata;
int tlv[TLV_ITEMS];
unsigned int i;
- int ret;
+ int ret = 0;
/* validate topology data */
- if (le32_to_cpu(mc->num_channels) > SND_SOC_TPLG_MAX_CHAN)
- return -EINVAL;
+ if (le32_to_cpu(mc->num_channels) > SND_SOC_TPLG_MAX_CHAN) {
+ ret = -EINVAL;
+ goto out;
+ }
/* 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;
+ if (!scontrol->control_data) {
+ ret = -ENOMEM;
+ goto out;
+ }
scontrol->comp_id = sdev->next_comp_id;
scontrol->min_volume_step = le32_to_cpu(mc->min);
@@ -958,7 +967,7 @@ static int sof_control_load_volume(struct snd_soc_component *scomp,
/* set cmd for mixer control */
if (le32_to_cpu(mc->max) == 1) {
scontrol->cmd = SOF_CTRL_CMD_SWITCH;
- goto out;
+ goto skip;
}
scontrol->cmd = SOF_CTRL_CMD_VOLUME;
@@ -966,14 +975,15 @@ static int sof_control_load_volume(struct snd_soc_component *scomp,
/* extract tlv data */
if (get_tlv_data(kc->tlv.p, tlv) < 0) {
dev_err(sdev->dev, "error: invalid TLV data\n");
- return -EINVAL;
+ ret = -EINVAL;
+ goto out_free;
}
/* 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;
+ goto out_free;
}
/* set default volume values to 0dB in control */
@@ -983,7 +993,7 @@ static int sof_control_load_volume(struct snd_soc_component *scomp,
cdata->chanv[i].value = VOL_ZERO_DB;
}
-out:
+skip:
/* set up possible led control from mixer private data */
ret = sof_parse_tokens(scomp, &scontrol->led_ctl, led_tokens,
ARRAY_SIZE(led_tokens), mc->priv.array,
@@ -991,13 +1001,21 @@ out:
if (ret != 0) {
dev_err(sdev->dev, "error: parse led tokens failed %d\n",
le32_to_cpu(mc->priv.size));
- return ret;
+ goto out_free_table;
}
dev_dbg(sdev->dev, "tplg: load kcontrol index %d chans %d\n",
scontrol->comp_id, scontrol->num_channels);
- return 0;
+ return ret;
+
+out_free_table:
+ if (le32_to_cpu(mc->max) > 1)
+ kfree(scontrol->volume_table);
+out_free:
+ kfree(scontrol->control_data);
+out:
+ return ret;
}
static int sof_control_load_enum(struct snd_soc_component *scomp,
@@ -1042,6 +1060,7 @@ static int sof_control_load_bytes(struct snd_soc_component *scomp,
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;
+ int ret = 0;
/* init the get/put bytes data */
scontrol->size = sizeof(struct sof_ipc_ctrl_data) +
@@ -1050,13 +1069,16 @@ static int sof_control_load_bytes(struct snd_soc_component *scomp,
if (scontrol->size > max_size) {
dev_err(sdev->dev, "err: bytes data size %d exceeds max %d.\n",
scontrol->size, max_size);
- return -EINVAL;
+ ret = -EINVAL;
+ goto out;
}
scontrol->control_data = kzalloc(max_size, GFP_KERNEL);
cdata = scontrol->control_data;
- if (!scontrol->control_data)
- return -ENOMEM;
+ if (!scontrol->control_data) {
+ ret = -ENOMEM;
+ goto out;
+ }
scontrol->comp_id = sdev->next_comp_id;
scontrol->cmd = SOF_CTRL_CMD_BINARY;
@@ -1071,23 +1093,32 @@ static int sof_control_load_bytes(struct snd_soc_component *scomp,
if (cdata->data->magic != SOF_ABI_MAGIC) {
dev_err(sdev->dev, "error: Wrong ABI magic 0x%08x.\n",
cdata->data->magic);
- return -EINVAL;
+ ret = -EINVAL;
+ goto out_free;
}
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;
+ ret = -EINVAL;
+ goto out_free;
}
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;
+ ret = -EINVAL;
+ goto out_free;
}
}
- return 0;
+
+ return ret;
+
+out_free:
+ kfree(scontrol->control_data);
+out:
+ return ret;
}
/* external kcontrol init - used for any driver specific init */
@@ -1145,6 +1176,11 @@ static int sof_control_load(struct snd_soc_component *scomp, int index,
return 0;
}
+ if (ret < 0) {
+ kfree(scontrol);
+ return ret;
+ }
+
dobj->private = scontrol;
list_add(&scontrol->list, &sdev->kcontrol_list);
return ret;