Uh oh!
There was an error while loading. Please reload this page.
Abstract the DMA and Codec DAI ops for the BE DAI widgets - #3972
Conversation
787fa0e to
e945284CompareUh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
| strstr(ops->drv[i].name, "Analog") || | ||
| strstr(ops->drv[i].name, "Digital")) | ||
| ops->drv[i].ops = &ipc4_hda_dai_ops; | ||
| ops->drv[i].ops = &hda_dai_ops; |
There was a problem hiding this comment.
this is a bit confusion, if the ops are the same between IPC and IPC4 why do wee need the switch()?
There was a problem hiding this comment.
for SSP and the NHLT for IPC4
| if (ops && ops->dma_ops && ops->dma_ops->post_trigger) { | ||
| ret = ops->dma_ops->post_trigger(sdev, cpu_dai, | ||
| hext_stream->link_substream, | ||
| SNDRV_PCM_TRIGGER_SUSPEND); |
There was a problem hiding this comment.
I didn't really follow how the hw_free and post-trigger were related. The naming points to different phases in the ALSA world.
There was a problem hiding this comment.
For IPC3, post_trigger does what hda_dai_hw_free_ipc(). For IPC4 also, we were doing the same and it made no sense. SO this patch actually fixes it
e945284 to
d56c49bCompared56c49b to
ba07eb1Compare| struct hdac_ext_link *hlink; | ||
| struct snd_sof_dev *sdev; | ||
| struct hdac_bus *bus; | ||
| unsigned int format_val, link_bps; |
There was a problem hiding this comment.
they are not initialized, so this is fine.
There was a problem hiding this comment.
it's still better to have one variable per line for consistency.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
plbossart
left a comment
There was a problem hiding this comment.
LGTM, we should probably do more testing overnight to see if we have any regressions, this is a rather intrusive patch.
Nice work @ranj063, I think this will help a lot clarify the sequences which were diluted with different ops and branches left and right.
plbossart
commented
Nov 17, 2022
@ujfalusi@RanderWang@bardliao@kv2019i@jsarha please prioritize this PR if you have a bit of time on Thursday 16, we are trying to complete this work before the Thanksgiving break. Friday will be too late for any interaction. |
| if (tplg_ops && tplg_ops->dai_config) { | ||
| ret = tplg_ops->dai_config(sdev, swidget, flags, data); | ||
| if (ret < 0) { | ||
| dev_err(sdev->dev, "DAI config with flags %x failed for widget %s\n", |
There was a problem hiding this comment.
%#x to print hex number ? It does not block me.
| int stream = substream->stream; | ||
| struct snd_sof_dai_config_data data = { 0 }; | ||
| unsigned int flags = SOF_DAI_CONFIG_FLAGS_HW_PARAMS; | ||
| int ret; |
There was a problem hiding this comment.
I like the layout
unsigned int flags = SOF_DAI_CONFIG_FLAGS_HW_PARAMS;
struct snd_sof_dai_config_data data = { 0 };
struct hdac_ext_stream *hext_stream;
| } | ||
| default: | ||
| break; | ||
| ipc4_data->nhlt = intel_nhlt_init(sdev->dev); |
There was a problem hiding this comment.
why we need to init nhlt in hda_set_dai_drv_ops ? It is not a issue in this PR. we remove the switch for ipc version but leave one if for ipc version
ujfalusi
left a comment
There was a problem hiding this comment.
@ranj063, this looks really nice!
The only thing holding me to Approve is that I can not follow optionality in struct hda_dai_widget_dma_ops.assign_hext_stream is as mandatory as the get_hext_stream, which also brings the release_hext_stream as mandatory.
By the look, the other ops are really optional.
Uh oh!
There was an error while loading. Please reload this page.
| snd_hdac_ext_stream_decouple_locked(bus, res, true); | ||
| /* check if mandatory ops are set */ | ||
| if (!ops || !ops->get_hext_stream) | ||
| return NULL; |
There was a problem hiding this comment.
nitpick: I would print error when the get_ext_stream is missing to make it more obvious.
| if (!hext_stream) { | ||
| if (ops->assign_hext_stream) | ||
| hext_stream = ops->assign_hext_stream(sdev, cpu_dai, substream); | ||
| } |
There was a problem hiding this comment.
You got me here...
Only get_hext_stream is mandatory, which is to to retrieve the dma_data set by the optional assign_hext_stream.
If the assign_hext_stream is not set (optional!) and this is the first call here then the get_hext_stream is going to return with NULL and you are not going to get anything but NULL...
What I was saying is that most, if not all callbacks in struct hda_dai_widget_dma_ops are in fact mandatory, don't they?
There was a problem hiding this comment.
also to note: you also must have the release_hext_stream defined if you have the assign_hext_stream, but you must need to have the assign_hext_stream in order to have working stack.
There was a problem hiding this comment.
or you should not return with error in line 118?
There was a problem hiding this comment.
The conclusion for this thread is that assign/release need to be optional because couple mode will not need them
| struct sof_ipc4_pipeline *pipeline; | ||
| const struct hda_dai_widget_dma_ops *ops = hda_dai_get_ops(substream, dai); | ||
| struct snd_sof_widget *swidget = w->dobj.private; | ||
| struct hdac_ext_stream *hext_stream; |
There was a problem hiding this comment.
nitpick: would look better two lines down..
Introduce a new ops structure for HDA DAI widget DMA ops and add a new field to struct snd_sof_dai that will be used to set the ops pointer for DAI widgets. Signed-off-by: Ranjani Sridharan <ranjani.sridharan@linux.intel.com>
Define and set the get_hext_stream, assign_hext_stream and release_hext_stream DMA ops for HDA DAIs. Signed-off-by: Ranjani Sridharan <ranjani.sridharan@linux.intel.com>
…A ops Define and use the setup_hext_stream/reset_hext_stream DMA ops during link hw_params and cleanup. Signed-off-by: Ranjani Sridharan <ranjani.sridharan@linux.intel.com>
Use the topology IPC dai_config to update the dai_config for HDA DAI widgets. Signed-off-by: Ranjani Sridharan <ranjani.sridharan@linux.intel.com>
Define and use the SOF widget's DMA pre_trigger/trigger/post_trigger ops in ipc4_hda_dai_trigger(). Signed-off-by: Ranjani Sridharan <ranjani.sridharan@linux.intel.com>
Define the post_trigger DMA op for IPC3 and unify the DAI driver ops for IPC3 and IPC4 for HDA DAI's. Also, use the post_trigger op to stop the paused streams properly in the hda_dai_suspend() function. This fixes the suspend while paused case for IPC4 because previously we weren't resetting the pipeline when suspending the system with some paused streams. Signed-off-by: Ranjani Sridharan <ranjani.sridharan@linux.intel.com>
Remove these functions and reuse hda_dai_config(). Signed-off-by: Ranjani Sridharan <ranjani.sridharan@linux.intel.com>
ee710ae5c11a0f to
ee710aeCompare
Introduce SOF DAI ops to abstract the BE DAI widget DMA, codec_dai and dai_config ops. This change will allow adding the chained DMA mode or the DSP-less mode for the BE DAI widgets with a simple change like this: