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
8 changes: 3 additions & 5 deletions sound/soc/sof/intel/hda-dai.c
Original file line number Diff line number Diff line change
Expand Up @@ -226,8 +226,6 @@ static int hda_link_hw_params(struct snd_pcm_substream *substream,

snd_soc_dai_set_dma_data(dai, substream, (void *)link_dev);

hda_stream->hw_params_upon_resume = 0;

link = snd_hdac_ext_bus_get_link(bus, codec_dai->component->name);
if (!link)
return -EINVAL;
Expand Down Expand Up @@ -267,8 +265,7 @@ static int hda_link_pcm_prepare(struct snd_pcm_substream *substream,

hda_stream = hstream_to_sof_hda_stream(link_dev);

/* setup hw_params again only if resuming from system suspend */
if (!hda_stream->hw_params_upon_resume)
if (link_dev->link_prepared)
return 0;

dev_dbg(sdev->dev, "hda: prepare stream dir %d\n", substream->stream);
Expand Down Expand Up @@ -317,6 +314,7 @@ static int hda_link_pcm_trigger(struct snd_pcm_substream *substream,
snd_hdac_ext_link_stream_start(link_dev);
break;
case SNDRV_PCM_TRIGGER_SUSPEND:
case SNDRV_PCM_TRIGGER_STOP:
/*
* clear and release link DMA channel. It will be assigned when
* hw_params is set up again after resume.
Expand All @@ -329,10 +327,10 @@ static int hda_link_pcm_trigger(struct snd_pcm_substream *substream,
snd_hdac_ext_link_clear_stream_id(link, stream_tag);
snd_hdac_ext_stream_release(link_dev,
HDAC_EXT_STREAM_TYPE_LINK);
link_dev->link_prepared = 0;

/* fallthrough */
case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
case SNDRV_PCM_TRIGGER_STOP:
snd_hdac_ext_link_stream_clear(link_dev);
break;
default:
Expand Down
17 changes: 6 additions & 11 deletions sound/soc/sof/intel/hda-dsp.c
Original file line number Diff line number Diff line change
Expand Up @@ -423,25 +423,19 @@ int hda_dsp_suspend(struct snd_sof_dev *sdev)

int hda_dsp_set_hw_params_upon_resume(struct snd_sof_dev *sdev)
{
struct hdac_bus *bus = sof_to_bus(sdev);
struct sof_intel_hda_stream *hda_stream;
struct hdac_ext_stream *stream;
struct hdac_stream *s;

#if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA)

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

maybe better not call this function at all when CONFIG_SND_SOC_SOF_HDA isn't selected? The SOF CONFIG_* graph is too confusing...

@kv2019i kv2019i Jul 5, 2019 •

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@lyakh I completely agree, but I don't want to start refactoring the SOF_HDA approach in this patch too much. Now the #ifdefs are in hda-dsp.c code in sof/intel/ and not in the caller, and I'd prefer to keep it like this in the patch.
UPDATE: I have added cleaning the ifdef-chaos to this improvement item -> #990 @lyakh ok for you (for this patch)?

struct hdac_bus *bus = sof_to_bus(sdev);
struct snd_soc_pcm_runtime *rtd;
struct hdac_ext_stream *stream;
struct hdac_ext_link *link;
struct hdac_stream *s;
const char *name;
int stream_tag;
#endif

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

please also refine the layout of variable declaration.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@rander Ack, will do in next patch revision.


/* set internal flag for BE */
list_for_each_entry(s, &bus->stream_list, list) {
stream = stream_to_hdac_ext_stream(s);
hda_stream = container_of(stream, struct sof_intel_hda_stream,
hda_stream);
hda_stream->hw_params_upon_resume = 1;
#if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA)

/*
* clear and release stream. This should already be taken care
* for running streams when the SUSPEND trigger is called.
Expand All @@ -458,8 +452,9 @@ int hda_dsp_set_hw_params_upon_resume(struct snd_sof_dev *sdev)
snd_hdac_ext_link_clear_stream_id(link, stream_tag);
snd_hdac_ext_stream_release(stream,
HDAC_EXT_STREAM_TYPE_LINK);
stream->link_prepared = 0;
}
#endif
}
#endif
return 0;
}
1 change: 0 additions & 1 deletion sound/soc/sof/intel/hda.h
Original file line number Diff line number Diff line change
Expand Up @@ -421,7 +421,6 @@ struct sof_intel_hda_stream {
struct snd_sof_dev *sdev;
struct hdac_ext_stream hda_stream;
struct sof_intel_stream stream;
int hw_params_upon_resume; /* set up hw_params upon resume */
int host_reserved; /* reserve host DMA channel */
};

Expand Down
63 changes: 33 additions & 30 deletions sound/soc/sof/pcm.c
Original file line number Diff line number Diff line change
Expand Up @@ -208,11 +208,31 @@ static int sof_pcm_hw_params(struct snd_pcm_substream *substream,
if (ret < 0)
return ret;

spcm->prepared[substream->stream] = true;

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

/* clear hw_params_upon_resume flag */
spcm->hw_params_upon_resume[substream->stream] = 0;
return ret;
}

static int sof_pcm_dsp_pcm_free(struct snd_pcm_substream *substream,
struct snd_sof_dev *sdev,
struct snd_sof_pcm *spcm)
{
struct sof_ipc_stream stream;
struct sof_ipc_reply reply;
int ret;

stream.hdr.size = sizeof(stream);
stream.hdr.cmd = SOF_IPC_GLB_STREAM_MSG | SOF_IPC_STREAM_PCM_FREE;
stream.comp_id = spcm->stream[substream->stream].comp_id;

/* send IPC to the DSP */
ret = sof_ipc_tx_message(sdev->ipc, stream.hdr.cmd, &stream,
sizeof(stream), &reply, sizeof(reply));
if (!ret)
spcm->prepared[substream->stream] = false;

return ret;
}
Expand All @@ -224,8 +244,6 @@ static int sof_pcm_hw_free(struct snd_pcm_substream *substream)
snd_soc_rtdcom_lookup(rtd, DRV_NAME);
struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(component);
struct snd_sof_pcm *spcm;
struct sof_ipc_stream stream;
struct sof_ipc_reply reply;
int ret;

/* nothing to do for BE */
Expand All @@ -236,16 +254,13 @@ static int sof_pcm_hw_free(struct snd_pcm_substream *substream)
if (!spcm)
return -EINVAL;

if (!spcm->prepared[substream->stream])
return 0;

dev_dbg(sdev->dev, "pcm: free stream %d dir %d\n", spcm->pcm.pcm_id,
substream->stream);

stream.hdr.size = sizeof(stream);
stream.hdr.cmd = SOF_IPC_GLB_STREAM_MSG | SOF_IPC_STREAM_PCM_FREE;
stream.comp_id = spcm->stream[substream->stream].comp_id;

/* send IPC to the DSP */
ret = sof_ipc_tx_message(sdev->ipc, stream.hdr.cmd, &stream,
sizeof(stream), &reply, sizeof(reply));
ret = sof_pcm_dsp_pcm_free(substream, sdev, spcm);

snd_pcm_lib_free_pages(substream);

Expand Down Expand Up @@ -278,11 +293,7 @@ static int sof_pcm_prepare(struct snd_pcm_substream *substream)
if (!spcm)
return -EINVAL;

/*
* check if hw_params needs to be set-up again.
* This is only needed when resuming from system sleep.
*/
if (!spcm->hw_params_upon_resume[substream->stream])
if (spcm->prepared[substream->stream])
return 0;

dev_dbg(sdev->dev, "pcm: prepare stream %d dir %d\n", spcm->pcm.pcm_id,
Expand Down Expand Up @@ -311,6 +322,7 @@ static int sof_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
struct snd_sof_pcm *spcm;
struct sof_ipc_stream stream;
struct sof_ipc_reply reply;
bool reset_hw_params = false;
int ret;

/* nothing to do for BE */
Expand Down Expand Up @@ -351,6 +363,7 @@ static int sof_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
case SNDRV_PCM_TRIGGER_SUSPEND:
case SNDRV_PCM_TRIGGER_STOP:
stream.hdr.cmd |= SOF_IPC_STREAM_TRIG_STOP;
reset_hw_params = true;

@RanderWang RanderWang Jul 5, 2019 •

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

please add spcm->prepared[substream->stream] = false;
I am debugging issue: #1057. For this case, the S3 is interrupted by RTC event, and ASoC only trigger SUSPEND to SOF in both FE & BE. There is no chance to invoke sof_suspend. Then SOF prepare functions are invoked by ASoC. we need to set spcm->prepared[substream->stream] = false to make prepare function work. And you also set link_dev->link_prepared = 0 in BE trigger function, so just add it here

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@RanderWang The prepared variable will be set to 'false' in this case. We set 'reset_hw_params' here to true, and at tne end of function, we will call sof_pcm_dsp_pcm_free() and this will set prepared[substream]=false. So should be fine, right?

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yes, I got it. I was confused by if(!ret)

break;
default:
dev_err(sdev->dev, "error: unhandled trigger cmd %d\n", cmd);
Expand All @@ -363,21 +376,10 @@ static int sof_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
ret = sof_ipc_tx_message(sdev->ipc, stream.hdr.cmd, &stream,
sizeof(stream), &reply, sizeof(reply));

if (ret < 0 || cmd != SNDRV_PCM_TRIGGER_SUSPEND)
return ret;
if (!ret && reset_hw_params)
ret = sof_pcm_dsp_pcm_free(substream, sdev, spcm);

/*
* The hw_free op is usually called when the pcm stream is closed.
* Since the stream is not closed during suspend, the DSP needs to be
* notified explicitly to free pcm to prevent errors upon resume.
*/
stream.hdr.size = sizeof(stream);
stream.hdr.cmd = SOF_IPC_GLB_STREAM_MSG | SOF_IPC_STREAM_PCM_FREE;
stream.comp_id = spcm->stream[substream->stream].comp_id;

/* send IPC to the DSP */
return sof_ipc_tx_message(sdev->ipc, stream.hdr.cmd, &stream,
sizeof(stream), &reply, sizeof(reply));
return ret;
}

static snd_pcm_uframes_t sof_pcm_pointer(struct snd_pcm_substream *substream)
Expand Down Expand Up @@ -481,6 +483,7 @@ static int sof_pcm_open(struct snd_pcm_substream *substream)
spcm->stream[substream->stream].posn.host_posn = 0;
spcm->stream[substream->stream].posn.dai_posn = 0;
spcm->stream[substream->stream].substream = substream;
spcm->prepared[substream->stream] = false;

ret = snd_sof_pcm_platform_open(sdev, substream);
if (ret < 0)
Expand Down
2 changes: 1 addition & 1 deletion sound/soc/sof/pm.c
Original file line number Diff line number Diff line change
Expand Up @@ -233,7 +233,7 @@ static int sof_set_hw_params_upon_resume(struct snd_sof_dev *sdev)

state = substream->runtime->status->state;
if (state == SNDRV_PCM_STATE_SUSPENDED)
spcm->hw_params_upon_resume[dir] = 1;
spcm->prepared[dir] = false;
}
}

Expand Down
2 changes: 1 addition & 1 deletion sound/soc/sof/sof-priv.h
Original file line number Diff line number Diff line change
Expand Up @@ -295,7 +295,7 @@ struct snd_sof_pcm {
struct snd_sof_pcm_stream stream[2];
struct list_head list; /* list in sdev pcm list */
struct snd_pcm_hw_params params[2];
int hw_params_upon_resume[2]; /* set up hw_params upon resume */
bool prepared[2]; /* PCM_PARAMS set successfully */
};

/* ALSA SOF Kcontrol device */
Expand Down