[PoC] ASoC: SOF: Move audio support as sof-client (support for multiple cards)#5815
Draft
ujfalusi wants to merge 83 commits into
Draft
[PoC] ASoC: SOF: Move audio support as sof-client (support for multiple cards)#5815ujfalusi wants to merge 83 commits into
ujfalusi wants to merge 83 commits into
Conversation
If either tplg_ops->dai_config or widget_kcontrol_setup fail during widget setup we would double decrement the use_count of the widget because the sof_widget_free_unlocked() would be called twice, similarly the core_put would be invoked twice as well. Since the use_count and core_put() is handled within the widget_free function we need to return without falling through the pipe_widget_free label. The fixes tag is picked to the last change around this part of the code which is adequately old enough for backporting purposes. Link: thesofproject/sof#10826 Fixes: 31ed8da ("ASoC: SOF: sof-audio: Modify logic for enabling/disabling topology cores") Signed-off-by: Peter Ujfalusi <peter.ujfalusi@linux.intel.com>
Protect IPC RX and FW state handler list unregister/dispatch paths with client_event_handler_mutex to match list registration and locking comments. Fixes: 5c19da3 ("ASoC: SOF: Use guard()/scoped_guard() for mutex locks where it makes sense") Signed-off-by: Peter Ujfalusi <peter.ujfalusi@linux.intel.com>
The IPC4 definition of pipeline prioity is: 0 - highest priority 7 - lowest priority RUNNING should use ascending order (highest priority first), otherwise descending order (lowest priority first) should be used. Fixes: 4df7d6a ("ASoC: SOF: IPC4: sort pipeline based on priority") Cc: stable@vger.kernel.org Signed-off-by: Peter Ujfalusi <peter.ujfalusi@linux.intel.com>
We need to adjust the params based on the available and picked SSP blob in the similar way we do for DMIC. Signed-off-by: Peter Ujfalusi <peter.ujfalusi@linux.intel.com>
…election The dai copier configuration for playback and capture needs to be separated because it is not correct to configure the dai copier as part of the input format selection for both direction. The input format is the dai format for capture, but it is not for playback, for playback the dai format is on the output side. Currently we configure and adjust the params based on the DAI supported formats when configuring the input side of the copier but right after the format has been adjusted we reset it for playback and loose this information. When using a nocodec passthrough topology (which is a bug) we have SSP blobs supporting 32bit only, copier supporting 16/24/32 bit then on playback the dai and copier will be incorrectly configured: host.copier.in: S16_LE host.copier.out: S16_LE dai.copier.in: S16_LE SSP.blob: S32_LE (we only have S32_LE blobs) dai.copier.out: S16_LE (the dai constraint is ignored) To handle such case the handling of capture and playback streams must be changed: The input format (no changes to previous implementation): for playback it is the pipeline_params for capture it is the adjusted fe_params The output format (no change for capture direction): for playback it is the adjusted fe_params for capture it is the fe_params with this change path format configuration will be correct: host.copier.in: S16_LE host.copier.out: S16_LE dai.copier.in: S16_LE SSP.blob: S32_LE (we only have S32_LE blobs) dai.copier.out: S32_LE Signed-off-by: Peter Ujfalusi <peter.ujfalusi@linux.intel.com>
Couple the Host and Link DMA when the stream is put. When the hda_dsp_stream_hw_free() is called the Link DMA might be still locked and we would leave the DMAs decoupled. hda_dsp_stream_hw_free() is not called for code loader use or in case of probes or trace use for example. Signed-off-by: Peter Ujfalusi <peter.ujfalusi@linux.intel.com>
Programing SoundWire registers are required for stream process. And we can only program then after the peripheral is attached and initialized. Currently, we wait initialization_complete in codec resume. To reduce the resume time, we will remove the waiting from codec resume in the follow up commits. Signed-off-by: Bard Liao <yung-chuan.liao@linux.intel.com>
…t of a module Based on the input and output formats we can evaluate what param might be changed by the module instance. If there is a difference between the input rate/channels/format and the output rate/channels/format it means that the module can change one or multiple of the params. Store this information during init for later use. Signed-off-by: Peter Ujfalusi <peter.ujfalusi@linux.intel.com>
The process module can change different parameters in the audio path and this change has to be properly evaluated and applied. In case of playback we are converting from multiple input formats to a single format (or just passing through without change), the output format lookup must be based on the input format. In case of capture, we are converting from a single input format to a format which is to be passed to the FE, we need to use the input parameters and the FE parameters to be able to find the correct format: for those parameters that are modified by the module instance we need to use the FE parameter while for the rest we use the input parameters. Signed-off-by: Peter Ujfalusi <peter.ujfalusi@linux.intel.com>
if the message times out and it was delayed, remove it as well. Signed-off-by: Peter Ujfalusi <peter.ujfalusi@linux.intel.com>
If the module in path has been already prepared on a branch type of
topology, where the branching happens downstream:
A1--> A2 ---> B1 --> B2 ... B-branch
|-> C1 --> C2 ... C-branch
In this case if B-branch is started then A1/A2 is prepared, but when
C-branch starts we still need to refine the parameters up to C1 to arrive
with a correct params to configure C1.
This branching can happen with copiers process modules.
Signed-off-by: Peter Ujfalusi <peter.ujfalusi@linux.intel.com>
…mt init Even if there is a single format supported by the module on it's input, it must be validated that it is matching with the reference parameters. The DAI copier's DAI side reference is adjusted to the formats it supports, but modules deep within the path might have incorrect configuration in topology (single format which is not matching with the previous module's output for example). This should be reported as errors and not silently accepted. Signed-off-by: Peter Ujfalusi <peter.ujfalusi@linux.intel.com>
Print the same information as we print in _sof_ipc4_prepare_copier_module() since the prepare will be not called on system resume, only the host_config will be executed and tracking the stream tag for the host is valuable information. Signed-off-by: Peter Ujfalusi <peter.ujfalusi@linux.intel.com>
…_run() It is expected that the DSP is in power down state when the firmware boot is attempted. If the DSP for any reason was left powered up then the DSP boot will fail since the ROM boot sequence might not be able to run. Make sure that the DSP is off before proceeding to boot it up. Signed-off-by: Peter Ujfalusi <peter.ujfalusi@linux.intel.com>
…_run() It is expected that the DSP is in power down state when the firmware boot is attempted. If the DSP for any reason was left powered up then the DSP boot will fail since the ROM boot sequence might not be able to run. Make sure that the DSP is off before proceeding to boot it up. Signed-off-by: Peter Ujfalusi <peter.ujfalusi@linux.intel.com>
The ipc_control_data buffer is allocated as kzalloc(max_size), where max_size covers the entire struct sof_ipc_ctrl_data including its flexible array payload. However, the bounds checks in bytes_ext_put and _bytes_ext_get compared user data lengths against max_size directly, ignoring that cdata->data sits at an offset of sizeof(struct sof_ipc_ctrl_data) bytes into the allocation. This allowed writing up to sizeof(struct sof_ipc_ctrl_data) bytes past the end of the heap buffer from unprivileged userspace via the ALSA TLV kcontrol interface, and similarly allowed over-reading adjacent heap data on the get path. Fix all bounds checks to subtract sizeof(*cdata) from max_size so they reflect the actual space available at the cdata->data offset. Also fix the error-path restore in bytes_ext_put which wrote to cdata->data instead of cdata, causing the same overflow. Additionally verify that the TLV payload length is large enough to cover what the ABI header's size field claims, preventing stale data from being sent to the DSP. Fixes: 67ec2a0 ("ASoC: SOF: Add bytes_ext control IPC ops for IPC3") Signed-off-by: Peter Ujfalusi <peter.ujfalusi@linux.intel.com>
On Intel ACE2+ platforms, each SoundWire link uses a single pair of
PDIs (PDI0 for TX, PDI1 for RX) and associated DMA resources for
Bulk Port Transfers. When two codecs on the same link initiate BRA
transfers concurrently (e.g. during firmware download), the second
sdw_bpt_send_async() call races with the first:
- intel_ace2x_bpt_open_stream() has a TOCTOU on the bpt_stream
pointer: both callers see it as NULL and proceed
- The second open overwrites the first's stream allocation, leaking
the original sdw_stream_runtime
- PCMSyCM mappings for the first transfer get overwritten, causing
chain DMA to operate with wrong PDI assignments
- IOC timeouts, use-after-free, and double-free follow on close
Add a per-bus bpt_lock mutex held across the send_async/wait span to
serialize BPT transfers. The lock is acquired in sdw_bpt_send_async()
before calling the master ops and released in sdw_bpt_wait() after the
transfer completes. On send_async failure, the lock is released
immediately.
Cross-link transfers (different sdw_bus instances) remain concurrent
since each bus has its own lock.
Signed-off-by: Peter Ujfalusi <peter.ujfalusi@linux.intel.com>
For aggregate DAIs (num_cpus > 1) the pre_trigger/post_trigger callbacks send pipeline state IPCs per-DAI without considering that multiple DAIs may share the same pipeline. This causes premature state transitions where the pipeline goes RUNNING before all link DMAs have started, or individual DAIs send redundant IPCs for shared pipelines. Fix this by checking the HDA stream running state in post_trigger: - START/PAUSE_RELEASE: defer RUNNING IPC until all DAIs sharing the same pipeline have their link DMA streams running - STOP/SUSPEND/PAUSE_PUSH: use pipeline state dedup so the PAUSED IPC is sent once regardless of how many DAIs share the pipeline The running-state check naturally handles all aggregate topologies: shared pipelines, independent pipelines, and mixed cases without requiring per-pipeline counters. Signed-off-by: Peter Ujfalusi <peter.ujfalusi@linux.intel.com>
Take a module reference in snd_compr_open() and release it in snd_compr_free(). This pins the card driver module for the lifetime of an open compress stream and prevents card removal while the stream file is still in use. Adjust the open() cleanup paths to drop the added module reference only when it was acquired, and keep release ordering safe by dropping the module reference before freeing stream data. Signed-off-by: Peter Ujfalusi <peter.ujfalusi@linux.intel.com>
Track open compressed streams per device so disconnect can stop active streams and wake waiters before snd_unregister_device(). This aligns compressed stream teardown with PCM disconnect behavior and prevents active userspace streams from running into unregister races. Signed-off-by: Peter Ujfalusi <peter.ujfalusi@linux.intel.com>
With DPCM when compr is used on FE side, the BE is still running as 'normal' PCM. It is expected that the be_substream->runtime on the BE is not NULL, for example some codec drivers expect to have the substream->runtime valid, to store configuration for example. Signed-off-by: Peter Ujfalusi <peter.ujfalusi@linux.intel.com>
… PCMs The FE-BE trigger sequence should be dynamic, similarly how soc-pcm.c dpcm_fe_dai_do_trigger() does it. Signed-off-by: Peter Ujfalusi <peter.ujfalusi@linux.intel.com>
If the last trigger that the compr device received is a DRAIN then the DPCM is left in running state (no stop trigger is sent). Before we execute the free we need to send a STOP trigger to make sure that both BE and FE is in expected state and prepared for closing. Signed-off-by: Peter Ujfalusi <peter.ujfalusi@linux.intel.com>
In preparation for adding support for compressed offload support for IPC4, rename the current compress implementation with the IPC3 prefix. Introduce a new field in struct sof_ipc_pcm_ops to save the IPC-specific compressed ops pointer. This should be set when the component driver ops are assigned during SOF device probe. Expose a couple of common functions that will be used by both IPC-specific implementations and rename the compress.c file to ipc3-compress.c Signed-off-by: Ranjani Sridharan <ranjani.sridharan@linux.intel.com> Signed-off-by: Peter Ujfalusi <peter.ujfalusi@linux.intel.com>
Serialize trigger/free with pipeline_state_mutex and validate pipeline entries before use. Also clear pipeline_list->count when freeing lists to avoid stale entries during concurrent teardown. Signed-off-by: Peter Ujfalusi <peter.ujfalusi@linux.intel.com>
During widget FREE traversal, SOF walks DAPM sink paths recursively while widgets and paths can be torn down. This can lead to stale pointer usage in sof_free_widgets_in_path() when path entries disappear during recursion. Harden the FREE path by: - validating scheduler/pipeline pointers before recursive free - using a safe DAPM path iterator for sink traversal - carrying a stable widget-list snapshot through recursion - skipping NULL sink edges during traversal The safe traversal can leave path->walking set on surviving edges after FREE, which may short-circuit later DAPM walks and break consecutive playback open/stop cycles. Reset walking flags for widgets in the current DAPM list after FREE walks (including error paths) to keep subsequent traversals clean. This keeps teardown robust for module-remove race scenarios while preserving normal consecutive playback behavior. Signed-off-by: Peter Ujfalusi <peter.ujfalusi@linux.intel.com>
These are common functions that will also be needed for the IPC4 compressed support. Signed-off-by: Ranjani Sridharan <ranjani.sridharan@linux.intel.com> Signed-off-by: Peter Ujfalusi <peter.ujfalusi@linux.intel.com>
In order to reuse the pipeline triggering logic for compressed support with IPC4, modify the signature of the trigger and hw_free PCM IPC ops so that they can be reused. Signed-off-by: Ranjani Sridharan <ranjani.sridharan@linux.intel.com> Signed-off-by: Peter Ujfalusi <peter.ujfalusi@linux.intel.com>
The route_list is topology-scoped state that belongs to the audio component instance rather than the global snd_sof_dev. Move it to snd_sof_audio_instance to properly scope route tracking per component. Callers that have a snd_soc_component available use snd_sof_component_get_audio_instance(), while global operations iterate all instances in the audio_instance_list. Signed-off-by: Peter Ujfalusi <peter.ujfalusi@linux.intel.com>
The pcm_list is topology-scoped state that belongs to the audio component instance rather than the global snd_sof_dev. Move it to snd_sof_audio_instance to properly scope PCM tracking per component. Move the audio instance function declarations before the snd_sof_find_spcm_dai() inline function in sof-audio.h since the inline now calls snd_sof_component_get_audio_instance(). Signed-off-by: Peter Ujfalusi <peter.ujfalusi@linux.intel.com>
Move kcontrol_list from the global snd_sof_dev to the per-component snd_sof_audio_instance structure. This is part of the ongoing effort to allow multiple audio components to coexist without sharing topology state. Update all call sites across topology.c, ipc3-control.c, and ipc4-control.c to access the kcontrol_list through the audio instance. Functions that have a snd_sof_widget available derive the instance from swidget->scomp via snd_sof_component_get_audio_instance(). Signed-off-by: Peter Ujfalusi <peter.ujfalusi@linux.intel.com>
Move widget_list from the global snd_sof_dev to the per-component snd_sof_audio_instance structure. This completes the migration of all topology list state to the audio instance, allowing multiple audio components to coexist without sharing topology state. Update all call sites across topology.c, ipc3-topology.c, ipc3-control.c, ipc4-topology.c, ipc4-compress.c, pcm.c, and sof-audio.c to access the widget_list through the audio instance. Functions that have a snd_soc_component or snd_sof_widget available use snd_sof_component_get_audio_instance(), while global operations iterate all instances in the audio_instance_list. Signed-off-by: Peter Ujfalusi <peter.ujfalusi@linux.intel.com>
Define a new sof_audio_ops structure for component-centric audio stream callbacks. These ops handle platform-specific stream management (host DMA, stream allocation, etc.) and receive snd_soc_component to identify the audio instance rather than snd_sof_dev. Add the audio_ops pointer to snd_sof_audio_instance, snd_sof_dev, and sof_dev_desc. The audio_ops flow is: sof_dev_desc provides it at probe time, core copies it to sdev, and audio_instance_register copies it from sdev to each instance. This is preparatory work for decoupling audio stream operations from snd_sof_dsp_ops, enabling audio to become a standalone sof-client. No functional change. Signed-off-by: Peter Ujfalusi <peter.ujfalusi@linux.intel.com>
Define sof_audio_ops instances for all Intel SOF platforms: - sof_hda_audio_ops in hda-common-ops.c, shared by all HDA platforms (SKL, APL, CNL, ICL, TGL, MTL, LNL, NVL, PTL) - sof_bdw_audio_ops in bdw.c for Broadwell - sof_byt_audio_ops and sof_cht_audio_ops in byt.c for Baytrail and Cherrytrail (different num_drv: 3 vs 6 SSPs) - sof_tng_audio_ops in pci-tng.c for Tangier Wire audio_ops into sof_dev_desc for each platform. The callbacks point to the same functions already used in snd_sof_dsp_ops. No functional change. Signed-off-by: Peter Ujfalusi <peter.ujfalusi@linux.intel.com>
Define per-variant sof_audio_ops for all AMD SOF platforms: Renoir, Rembrandt, Van Gogh, ACP63, and ACP70. Each variant has its own audio_ops with platform-specific DAI drivers and shared ACP PCM callbacks. Set sdev->audio_ops from ops_init since the audio_ops are static to each variant file and the descriptors are in separate pci-*.c files. No functional change. Signed-off-by: Peter Ujfalusi <peter.ujfalusi@linux.intel.com>
Define per-chip sof_audio_ops for i.MX SOF platforms: imx8, imx8m, imx8ulp, and imx95. Each chip has its own audio_ops with chip-specific DAI drivers and shared stream PCM callbacks. Add audio_ops pointer to imx_chip_info so ops_init can select the correct audio_ops per chip variant. No functional change. Signed-off-by: Peter Ujfalusi <peter.ujfalusi@linux.intel.com>
Define per-SoC sof_audio_ops for MediaTek SOF platforms: mt8186, mt8188, mt8195, and mt8365. Each SoC has its own audio_ops with SoC-specific DAI drivers and PCM hw_params/pointer callbacks. For mt8188, set sdev->audio_ops from ops_init since it shares the mt8186 ops file and overrides drv/num_drv at init time. No functional change. Signed-off-by: Peter Ujfalusi <peter.ujfalusi@linux.intel.com>
Switch the PCM and compress dispatch functions in ops.h from sof_ops(sdev)->callback to audio_instance->audio_ops->callback pattern. This decouples the audio path from snd_sof_dsp_ops and routes through the sof_audio_ops structure instead. Update core.c to read drv/num_drv from sdev->audio_ops for component registration. Update pcm.c to read hw_info and pcm_pointer from audio_ops. Update intel/hda.c to check audio_ops->pcm_pointer for IPC position mode. The compr_get_dai_frame_counter, pcm_get_dai_frame_counter, and pcm_get_host_byte_counter callbacks are not moved as they take sdev directly and are not part of sof_audio_ops. Signed-off-by: Peter Ujfalusi <peter.ujfalusi@linux.intel.com>
Remove the pcm, compress, DAI driver and hw_info fields from all Intel snd_sof_dsp_ops struct instances as these are now provided through the sof_audio_ops structures. Update hda_set_dai_drv_ops() and related functions to access the DAI driver array through sdev->audio_ops instead of the dsp_ops parameter. Update set_mach_params() in atom.c and bdw.c to read drv/num_drv from desc->audio_ops. Signed-off-by: Peter Ujfalusi <peter.ujfalusi@linux.intel.com>
Remove the pcm_open, pcm_close, pcm_hw_params, pcm_pointer, drv, num_drv and hw_info fields from the AMD common and per-variant snd_sof_dsp_ops struct instances as these are now provided through the sof_audio_ops structures. Signed-off-by: Peter Ujfalusi <peter.ujfalusi@linux.intel.com>
Remove the pcm_open, pcm_close, drv, num_drv and hw_info fields from the i.MX common and per-variant snd_sof_dsp_ops struct instances as these are now provided through the sof_audio_ops structures. Also remove the now-orphaned drv and num_drv fields from the imx_chip_info structure and all its instances. Signed-off-by: Peter Ujfalusi <peter.ujfalusi@linux.intel.com>
Remove the pcm_open, pcm_close, pcm_hw_params, pcm_pointer, drv, num_drv and hw_info fields from the MediaTek snd_sof_dsp_ops struct instances as these are now provided through the sof_audio_ops structures. Signed-off-by: Peter Ujfalusi <peter.ujfalusi@linux.intel.com>
Remove the pcm_open, pcm_close, pcm_hw_params, pcm_hw_free, pcm_trigger, pcm_pointer, pcm_ack, compr_open, compr_close, compr_hw_params, compr_hw_free, compr_trigger, compr_pointer, drv, num_drv and hw_info fields from struct snd_sof_dsp_ops as these are now provided through struct sof_audio_ops. Signed-off-by: Peter Ujfalusi <peter.ujfalusi@linux.intel.com>
Add sof_client_is_dspless() and sof_client_get_num_cores() accessor functions to the sof-client API. These will be needed by the audio client driver to query DSP state without direct access to snd_sof_dev. Signed-off-by: Peter Ujfalusi <peter.ujfalusi@linux.intel.com>
Refactor snd_sof_new_platform_drv() to take an explicit snd_soc_component_driver pointer instead of always filling sdev->plat_drv directly. This prepares for the audio sof-client driver which will provide its own component_driver. No functional change. Signed-off-by: Peter Ujfalusi <peter.ujfalusi@linux.intel.com>
Add sof_client_machine_register() and sof_client_machine_unregister() to the sof-client API. These allow client drivers to manage machine driver registration without direct access to snd_sof_dev. The audio sof-client driver will use these to register and unregister the machine driver as part of its lifecycle. Signed-off-by: Peter Ujfalusi <peter.ujfalusi@linux.intel.com>
Many log messages in the topology, control, PCM and audio-core paths were printing via sdev->dev even though the context is clearly bound to a specific component (scomp), widget (swidget), route (sroute) or control (scontrol). Logging through sdev->dev in those paths forces all messages to appear under the platform device, making it impossible to distinguish which audio component or pipeline instance triggered a given message. Switch all such messages to use the device that belongs to the available context. Several internal helper functions that received struct snd_sof_dev * solely to reach sdev->dev have also been simplified to derive sdev locally or drop the parameter entirely. sdev->dev is retained where there is no component context yet (e.g. early IPC notification handlers before the widget lookup, platform- level firmware loading, and places where the allocation is tied to the lifetime of sdev rather than the component). Signed-off-by: Peter Ujfalusi <peter.ujfalusi@linux.intel.com>
Move audio component and machine driver registration from core.c into a dedicated sof-client auxiliary driver (snd-sof-audio.ko). Core.c now registers a 'snd_sof.audio' auxiliary device with the pre-built snd_soc_component_driver and DAI drivers passed as platform_data. The audio client driver's probe registers the ASoC component and machine driver, and its remove handles teardown in the correct order. The component is still registered on the parent device (sdev->dev) via sof_client_get_dma_dev() to maintain machine driver compatibility. SND_SOC_SOF now selects SND_SOC_SOF_CLIENT to ensure the client framework is always available. Signed-off-by: Peter Ujfalusi <peter.ujfalusi@linux.intel.com>
Move the audio client device registration from core.c's probe path into vendor-controlled callbacks in snd_sof_dsp_ops. This allows each vendor/platform to control the audio client lifecycle. Add register_audio_client/unregister_audio_client callbacks to struct snd_sof_dsp_ops and provide default implementations (sof_register_audio_client/sof_unregister_audio_client) that all vendors use for now. The audio client registration is called from sof_register_clients() before the dspless mode early return, ensuring audio works in both normal and dspless modes. The snd_sof_new_platform_drv() call is moved into sof_register_audio_client(), making core.c no longer responsible for building the platform driver or audio client pdata. With the audio client pdata now built locally in the helper, sdev->plat_drv is no longer needed and is removed from struct snd_sof_dev. Signed-off-by: Peter Ujfalusi <peter.ujfalusi@linux.intel.com>
Register the ASoC component on the sof-client auxiliary device (&cdev->auxdev.dev) instead of the parent DSP device (sdev->dev). This gives a natural path from the component to the client device: snd_soc_component_get_drvdata() returns the cdev directly. A new helper snd_sof_component_get_cdev() is added, and the existing snd_sof_component_get_sdev() is updated to go through the client device using sof_client_dev_to_sof_dev(). The machine driver platform name (mach_params.platform) is updated in sof_client_machine_register() to match the auxiliary device name, ensuring machine driver platform matching works correctly. The nocodec path is updated to receive the platform name as a parameter instead of hardcoding dev_name(dev->parent). Add sof_client_core_module_get/put calls in PCM open/close to ensure the core DSP driver module use count is incremented while audio is active. Signed-off-by: Peter Ujfalusi <peter.ujfalusi@linux.intel.com>
When a function topology does not support a DAI link, continue to the next one instead of failing the entire topology load. This allows partial topology loading where not all DAI links have matching function topologies. Signed-off-by: Peter Ujfalusi <peter.ujfalusi@linux.intel.com>
When soc_check_tplg_fes() overrides BE DAI link CPU component names, only set cpu->name when the DAI is actually registered by the matching component. This prevents cross-component DAI binding issues when multiple components provide identically-named DAIs (e.g., SDW DAIs in soundwire_intel vs SOF audio components). Signed-off-by: Peter Ujfalusi <peter.ujfalusi@linux.intel.com>
Add card_name and dai_type_mask fields to snd_soc_acpi_mach_params to allow per-instance card naming and DAI type filtering. Use card_name in mc_probe() to set the card name when provided. Signed-off-by: Peter Ujfalusi <peter.ujfalusi@linux.intel.com>
Add dai_type_mask field filtering in asoc_sdw_count_sdw_endpoints() and asoc_sdw_parse_sdw_endpoints() to allow multi-card configurations to include only specific DAI types. When dai_type_mask is non-zero, only codec endpoints with matching dai_type bits are counted and parsed. Auxiliary devices for codecs without matching endpoints are also skipped. Signed-off-by: Peter Ujfalusi <peter.ujfalusi@linux.intel.com>
…links Before loading a user-specified feature topology, verify that the card has a matching BE DAI link. Feature topologies extend specific codec function types (amp, jack, mic) and reference widgets that only exist when the corresponding BE DAI links are present. Without this check, loading an amplifier feature topology on a card without SmartAmp DAI links would fail with -EINVAL due to missing route endpoints, killing the entire card probe. This is needed for multi-card configurations where cards are split by function type, but also provides a safety net in single-card mode when feature topologies don't match the hardware. Signed-off-by: Peter Ujfalusi <peter.ujfalusi@linux.intel.com>
Add Intel-specific multi-card audio client registration that creates separate sound cards per codec function type when the multi_card module parameter is set. The registration groups SoundWire endpoints by DAI type (jack, amp, mic) and creates a card per group using codec-specific names (e.g. cs42l43, cs35l56) with a generic function name fallback (jack, speaker, mic). DMIC and HDMI are registered as additional separate cards. Individual card registration failures are non-fatal to allow partial audio functionality when some components fail to probe. When multi_card is not set (default), falls back to the generic single-card sof_register_audio_client(). This is experimental and opt-in via: modprobe snd-sof-intel-hda-generic multi_card=1 Signed-off-by: Peter Ujfalusi <peter.ujfalusi@linux.intel.com>
Use mach_params.card_name when provided. Propagate mach_params.dmic_num to ctx->dmic_be_num. Machine data then controls DMIC BE exposure in this card. This enables per-audio-client card setup for split configurations. Signed-off-by: Peter Ujfalusi <peter.ujfalusi@linux.intel.com>
Add split_hdmi mode to register separate analog and HDMI audio clients when iDisp is present. Keep the analog card on the selected machine configuration with iDisp masked out, and register HDMI as a dedicated generic HDA card using sof-hda-generic-idisp.tplg. Update unregister handling to support split fallback to the legacy single-client path when split registration is not used. Signed-off-by: Peter Ujfalusi <peter.ujfalusi@linux.intel.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
The PR contains my PoC work in progress patches to rewrite SOF and detach the sound from the DSP core driver as 'independent' sof-client.
The DSP management, booting, IPC, PM, ID allocation still remain in the core sdev level, but audio is mostly detached from sdev into snd_sof_instance, which now owns the topology loading, widgets, pipelines, PCMs, component and sound card.
booting with this branch there must not be any functional change, everything should work as before wit the exception that we have a new
snd_sof_audiomodule.I have introduced two Intel specific module parameters to
snd_sof_intel_hda_generic:multi_card- applicable in case of function topologies and it will create sound cards per main codecs'split_hdmi` - this will separate only the HDMI card from the main card into it's own.
-- multi_card --
-- split_hdmi --
In either case, you can unbind any card runtime w/o affecting the operation of the other cards, like in
multi_card, one can remove the sof-hdmi card by:The
sof-hdmicard will always use the skl_hda machine driver with sof-hda-generic-idisp.tplg, so it's PCM list will be constant.The
split_hdmiworks with IPC3 hda and sndw machines as well.The topology name is moved from fw_profile of debugfs to audio.X/topology_name.
The branch should not case regression to @thesofproject/amd, @thesofproject/nxp or @thesofproject/mediatek, it works with nocodec and I2S machine drivers as well.
There are still layering violation around sdev accesses, some code still relies on sdev while it should not, NHLT blob is iffy a bit, but not much worst than what we have, but not ideal.
Concurrent card usage works fine as well, UIs will be broken for the
multi_cardbut likely going to work withsplit_hdmi, only that we will miss the HDMI from profile (likely) as we keep the original card's name for the card from where the HDMI is removed.