Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 11 additions & 1 deletion sound/soc/sof/core.c
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
* Author: Liam Girdwood <liam.r.girdwood@linux.intel.com>
*/

#include <linux/pm_runtime.h>
#include <linux/mm.h>
#include <linux/module.h>
#include <linux/slab.h>
Expand Down Expand Up @@ -249,6 +250,7 @@ static int sof_probe(struct platform_device *pdev)
INIT_LIST_HEAD(&sdev->kcontrol_list);
INIT_LIST_HEAD(&sdev->widget_list);
INIT_LIST_HEAD(&sdev->dai_list);
INIT_LIST_HEAD(&sdev->route_list);
dev_set_drvdata(&pdev->dev, sdev);
spin_lock_init(&sdev->ipc_lock);
spin_lock_init(&sdev->hw_lock);
Expand Down Expand Up @@ -290,7 +292,7 @@ static int sof_probe(struct platform_device *pdev)
}

/* load the firmware */
ret = snd_sof_load_firmware(sdev, plat_data->fw);
ret = snd_sof_load_firmware(sdev, plat_data->fw, true);
if (ret < 0) {
dev_err(sdev->dev, "error: failed to load DSP firmware %d\n",
ret);
Expand Down Expand Up @@ -330,6 +332,14 @@ static int sof_probe(struct platform_device *pdev)
"warning: failed to initialize trace %d\n", ret);
}

/* autosuspend sof device */
pm_runtime_mark_last_busy(sdev->dev);
pm_runtime_put_autosuspend(sdev->dev);

/* autosuspend pci/acpi/spi device */
pm_runtime_mark_last_busy(plat_data->dev);
pm_runtime_put_autosuspend(plat_data->dev);

return 0;

comp_err:
Expand Down
4 changes: 4 additions & 0 deletions sound/soc/sof/intel/apl.c
Original file line number Diff line number Diff line change
Expand Up @@ -96,5 +96,9 @@ struct snd_sof_dsp_ops sof_apl_ops = {
/* DAI drivers */
.drv = skl_dai,
.num_drv = SOF_SKL_NUM_DAIS,

/* PM */
.suspend = hda_dsp_suspend,
.resume = hda_dsp_resume,
};
EXPORT_SYMBOL(sof_apl_ops);
17 changes: 16 additions & 1 deletion sound/soc/sof/intel/hda-dsp.c
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@
#include <sound/sof.h>
#include <sound/pcm_params.h>
#include <linux/pm_runtime.h>

#include <uapi/sound/sof-ipc.h>
#include "../sof-priv.h"
#include "../ops.h"
#include "hda.h"
Expand Down Expand Up @@ -239,3 +239,18 @@ int hda_dsp_core_reset_power_down(struct snd_sof_dev *sdev,
return ret;
}

int hda_dsp_suspend(struct snd_sof_dev *sdev, int state)
{
const struct sof_intel_dsp_desc *chip = sdev->hda->desc;

/* power down DSP */
return hda_dsp_core_reset_power_down(sdev, chip->cores_mask);
}

int hda_dsp_resume(struct snd_sof_dev *sdev)
{
const struct sof_intel_dsp_desc *chip = sdev->hda->desc;

/* power up the DSP */
return hda_dsp_core_power_up(sdev, chip->cores_mask);
}
3 changes: 2 additions & 1 deletion sound/soc/sof/intel/hda-loader.c
Original file line number Diff line number Diff line change
Expand Up @@ -287,7 +287,8 @@ static int cl_copy_fw(struct snd_sof_dev *sdev, int tag)
return status;
}

int hda_dsp_cl_load_fw(struct snd_sof_dev *sdev, const struct firmware *fw)
int hda_dsp_cl_load_fw(struct snd_sof_dev *sdev, const struct firmware *fw,
bool first_boot)
{
struct snd_sof_pdata *plat_data = dev_get_platdata(sdev->dev);
int ret;
Expand Down
5 changes: 4 additions & 1 deletion sound/soc/sof/intel/hda.h
Original file line number Diff line number Diff line change
Expand Up @@ -405,6 +405,8 @@ bool hda_dsp_core_is_enabled(struct snd_sof_dev *sdev,
unsigned int core_mask);
int hda_dsp_core_reset_power_down(struct snd_sof_dev *sdev,
unsigned int core_mask);
int hda_dsp_suspend(struct snd_sof_dev *sdev, int state);
int hda_dsp_resume(struct snd_sof_dev *sdev);
void hda_dsp_dump(struct snd_sof_dev *sdev, u32 flags);

/*
Expand Down Expand Up @@ -481,7 +483,8 @@ int hda_dsp_ipc_cmd_done(struct snd_sof_dev *sdev, int dir);
/*
* DSP Code loader.
*/
int hda_dsp_cl_load_fw(struct snd_sof_dev *sdev, const struct firmware *fw);
int hda_dsp_cl_load_fw(struct snd_sof_dev *sdev, const struct firmware *fw,
bool first_boot);
int hda_dsp_cl_boot_firmware(struct snd_sof_dev *sdev);

/*
Expand Down
6 changes: 3 additions & 3 deletions sound/soc/sof/loader.c
Original file line number Diff line number Diff line change
Expand Up @@ -208,7 +208,7 @@ static int load_modules(struct snd_sof_dev *sdev, const struct firmware *fw)
}

int snd_sof_load_firmware_memcpy(struct snd_sof_dev *sdev,
const struct firmware *fw)
const struct firmware *fw, bool first_boot)
{
int ret;

Expand Down Expand Up @@ -238,12 +238,12 @@ int snd_sof_load_firmware_memcpy(struct snd_sof_dev *sdev,
EXPORT_SYMBOL(snd_sof_load_firmware_memcpy);

int snd_sof_load_firmware(struct snd_sof_dev *sdev,
const struct firmware *fw)
const struct firmware *fw, bool first_boot)
{
dev_dbg(sdev->dev, "loading firmware\n");

if (sdev->ops->load_firmware)
return sdev->ops->load_firmware(sdev, fw);
return sdev->ops->load_firmware(sdev, fw, first_boot);
return 0;
}
EXPORT_SYMBOL(snd_sof_load_firmware);
Expand Down
90 changes: 83 additions & 7 deletions sound/soc/sof/pcm.c
Original file line number Diff line number Diff line change
Expand Up @@ -158,6 +158,9 @@ static int sof_pcm_hw_params(struct snd_pcm_substream *substream,
spcm->posn_offset[substream->stream] =
sdev->stream_box.offset + posn_offset;

/* save pcm hw_params */
memcpy(&spcm->params[substream->stream], params, sizeof(*params));

return ret;
}

Expand Down Expand Up @@ -190,6 +193,33 @@ static int sof_pcm_hw_free(struct snd_pcm_substream *substream)
return ret;
}

static int sof_restore_hw_params(struct snd_pcm_substream *substream,
struct snd_sof_pcm *spcm,
struct snd_sof_dev *sdev)
{
snd_pcm_uframes_t host = 0;
u64 host_posn;
int ret = 0;

/* resume stream */
host_posn = spcm->stream[substream->stream].posn.host_posn;
host = bytes_to_frames(substream->runtime, host_posn);
dev_dbg(sdev->dev,
"PCM: resume stream %d dir %d DMA position %lu\n",
spcm->pcm.pcm_id, substream->stream, host);

/* set hw_params */
ret = sof_pcm_hw_params(substream,
&spcm->params[substream->stream]);
if (ret < 0) {
dev_err(sdev->dev,
"error: set pcm hw_params after resume\n");
return ret;
}

return 0;
}

static int sof_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
Expand All @@ -212,19 +242,66 @@ static int sof_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
stream.comp_id = spcm->stream[substream->stream].comp_id;

switch (cmd) {
case SNDRV_PCM_TRIGGER_START:
stream.hdr.cmd |= SOF_IPC_STREAM_TRIG_START;
break;
case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
stream.hdr.cmd |= SOF_IPC_STREAM_TRIG_RELEASE;
break;
case SNDRV_PCM_TRIGGER_STOP:

/*
* Check if stream was marked for restore before suspend
*/
if (spcm->restore_stream[substream->stream]) {

/* unset restore_stream */
spcm->restore_stream[substream->stream] = 0;

/* do not send ipc as the stream hasn't been set up */
return 0;
}

stream.hdr.cmd |= SOF_IPC_STREAM_TRIG_STOP;
break;
case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
stream.hdr.cmd |= SOF_IPC_STREAM_TRIG_PAUSE;
break;
case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:

/* check if the stream hw_params needs to be restored */
if (spcm->restore_stream[substream->stream]) {

/* restore hw_params */
ret = sof_restore_hw_params(substream, spcm, sdev);
if (ret < 0)
return ret;

/* unset restore_stream */
spcm->restore_stream[substream->stream] = 0;

/* trigger start */
stream.hdr.cmd |= SOF_IPC_STREAM_TRIG_START;
} else {

/* trigger pause release */
stream.hdr.cmd |= SOF_IPC_STREAM_TRIG_RELEASE;
}
break;
case SNDRV_PCM_TRIGGER_START:
/* fall through */
case SNDRV_PCM_TRIGGER_RESUME:

/* check if the stream hw_params needs to be restored */
if (spcm->restore_stream[substream->stream]) {

/* restore hw_params */
ret = sof_restore_hw_params(substream, spcm, sdev);
if (ret < 0)
return ret;

/* unset restore_stream */
spcm->restore_stream[substream->stream] = 0;
}

/* trigger stream */
stream.hdr.cmd |= SOF_IPC_STREAM_TRIG_START;

break;
case SNDRV_PCM_TRIGGER_SUSPEND:
break;
default:
Expand Down Expand Up @@ -586,7 +663,6 @@ static int sof_pcm_probe(struct snd_soc_platform *platform)
pm_runtime_use_autosuspend(platform->dev);
pm_runtime_enable(platform->dev);
pm_runtime_idle(platform->dev);

err:
return ret;
}
Expand Down
Loading