summaryrefslogtreecommitdiff
path: root/include/sound/soc.h
AgeCommit message (Collapse)Author
2024-09-06ASoC: makes rtd->initialized bit fieldKuninori Morimoto
rtd->initialized is used to know whether soc_init_pcm_runtime() was correctly fined, and used to call snd_soc_link_exit(). We don't need to have it as bool, let's make it bit-field same as other flags. Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> Cc: Amadeusz Sławiński <amadeuszx.slawinski@linux.intel.com> Cc: Cezary Rojewski <cezary.rojewski@intel.com> Link: https://patch.msgid.link/87o752k7gq.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown <broonie@kernel.org>
2024-08-22ASoC: soc-pcm: Indicate warning if dpcm_playback/capture were used for ↵Kuninori Morimoto
availability limition I have been wondering why DPCM needs special flag (= dpcm_playback/capture) to use it. Below is the history why it was added to ASoC. (A) In beginning, there was no dpcm_xxx flag on ASoC. It checks channels_min for DPCM, same as current non-DPCM. Let's name it as "validation check" here. if (rtd->dai_link->dynamic || rtd->dai_link->no_pcm) { if (cpu_dai->driver->playback.channels_min) playback = 1; if (cpu_dai->driver->capture.channels_min) capture = 1; (B) commit 1e9de42f4324 ("ASoC: dpcm: Explicitly set BE DAI link supported stream directions") force to use dpcm_xxx flag on DPCM. According to this commit log, this is because "Some BE dummy DAI doesn't set channels_min for playback/capture". But we don't know which DAI is it, and not know why it can't/don't have channels_min. Let's name it as "no_chan_DAI" here. According to the code and git-log, it is used as DCPM-BE and is CPU DAI. I think the correct solution was set channels_min on "no_chan_DAI" side, not update ASoC framework side. But everything is under smoke today. if (rtd->dai_link->dynamic || rtd->dai_link->no_pcm) { playback = rtd->dai_link->dpcm_playback; capture = rtd->dai_link->dpcm_capture; (C) commit 9b5db059366a ("ASoC: soc-pcm: dpcm: Only allow playback/capture if supported") checks channels_min (= validation check) again. Because DPCM availability was handled by dpcm_xxx flag at that time, but some Sound Card set it even though it wasn't available. Clearly there's a contradiction here. I think correct solution was update Sound Card side instead of ASoC framework. Sound Card side will be updated to handle this issue later (commit 25612477d20b ("ASoC: soc-dai: set dai_link dpcm_ flags with a helper")) if (rtd->dai_link->dynamic || rtd->dai_link->no_pcm) { ... playback = rtd->dai_link->dpcm_playback && snd_soc_dai_stream_valid(cpu_dai, ...); capture = rtd->dai_link->dpcm_capture && snd_soc_dai_stream_valid(cpu_dai, ...); This (C) patch should have broken "no_chan_DAI" which doesn't have channels_min, but there was no such report during this 4 years. Possibilities case are as follows - No one is using "no_chan_DAI" - "no_chan_DAI" is no longer exist : was removed ? - "no_chan_DAI" is no longer exist : has channels_min ? Because of these history, this dpcm_xxx is unneeded flag today. But because we have been used it for 10 years since (B), it may have been used differently. For example some DAI available both playback/capture, but it set dpcm_playback flag only, in this case dpcm_xxx flag is used as availability limitation. We can use playback_only flag instead in this case, but it is very difficult to find such DAI today. Let's add grace time to remove dpcm_playback/capture flag. This patch don't use dpcm_xxx flag anymore, and indicates warning to use xxx_only flag if both playback/capture were available but using only one of dpcm_xxx flag, and not using xxx_only flag. Link: https://lore.kernel.org/r/87edaym2cg.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> Tested-by: Jerome Brunet <jbrunet@baylibre.com> Link: https://patch.msgid.link/87seuyaahn.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown <broonie@kernel.org>
2024-07-29ASoC: Use __counted_by() annotation for snd_soc_pcm_runtimeTakashi Iwai
The struct snd_soc_pcm_runtime has a flex array of snd_soc_component objects at its end, and the size is kept in num_components field. We can add __counted_by() annotation for compiler's assistance to catch array overflows. A slight additional change is the assignment of rtd->components[]; the array counter has to be incremented at first for avoiding false-positive reports from compilers. Also, the allocation size of snd_soc_pcm_runtime is cleaned up with the standard struct_size() helper, too. Signed-off-by: Takashi Iwai <tiwai@suse.de> Link: https://patch.msgid.link/20240726155237.21961-1-tiwai@suse.de Signed-off-by: Mark Brown <broonie@kernel.org>
2024-06-18ASoC: Constify passed data to core functionKrzysztof Kozlowski
Several ASoC functions receive pointers to data which is not modified, e.g. pointers to 'snd_soc_dai', 'snd_soc_pcm_runtime', 'snd_pcm_hw_params' and 'snd_soc_dai_link'. All these pointers can be made as a pointer to const. This makes code safer, serves as clear annotation of function's intentions (no ownership passed to the function, no modifications) and allows putting pointed structures in rodata (if ever applicable). Signed-off-by: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org> Link: https://msgid.link/r/20240617-n-asoc-const-auto-selectable-formats-v1-3-8004f346ee38@linaro.org Signed-off-by: Mark Brown <broonie@kernel.org>
2024-06-18ASoC: Constify of_phandle_args in snd_soc_dai_link_componentKrzysztof Kozlowski
ASoC core code does not modify contents of 'of_phandle_args' in 'struct snd_soc_dai_link_component', so the pointer can be made as a pointer to const. This makes code safer, serves as clear annotation of core's intentions and allows putting pointed structures in rodata (if ever applicable). Signed-off-by: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org> Link: https://msgid.link/r/20240617-n-asoc-const-auto-selectable-formats-v1-2-8004f346ee38@linaro.org Signed-off-by: Mark Brown <broonie@kernel.org>
2024-05-02ASoC: Use inline function for type safety in snd_soc_substream_to_rtd()Krzysztof Kozlowski
A common pattern in sound drivers is getting 'struct snd_soc_pcm_runtime' from 'struct snd_pcm_substream' opaque pointer private_data field with snd_soc_substream_to_rtd(). However 'private_data' appears in several other structures as well, including 'struct snd_compr_stream'. The field might not hold the same type for every structure, although seems the case at least for 'struct snd_compr_stream', so code can easily make a mistake by using macro for wrong structure passed as argument. Switch from macro to inline function, so such mistake will be build-time detectable. Signed-off-by: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org> Link: https://lore.kernel.org/r/20240501175127.34301-1-krzysztof.kozlowski@linaro.org Signed-off-by: Mark Brown <broonie@kernel.org>
2024-04-30ASoC: pcm: Reverse iterate DAIs when shutting them downCezary Rojewski
During startup snd_soc_dai_startup() is launched in ascending order and the exact same thing is done during shutdown procedure. Reverse the order in the latter so that it is symmetric to the former. Signed-off-by: Cezary Rojewski <cezary.rojewski@intel.com> Link: https://lore.kernel.org/r/20240426095733.3946951-2-cezary.rojewski@intel.com Signed-off-by: Mark Brown <broonie@kernel.org>
2024-04-23ASoC: soc.h: Don't use "proxy" headersAndy Shevchenko
Update header inclusions to follow IWYU (Include What You Use) principle. Signed-off-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com> Link: https://lore.kernel.org/r/20240422151513.2052167-1-andriy.shevchenko@linux.intel.com Signed-off-by: Mark Brown <broonie@kernel.org>
2024-03-26ASoC: core: add SOC_DOUBLE_RANGE_TLV() helper macroLuca Ceresoli
No macro currently allows handling a stereo control that has left and right in the same register and whose minimum register value is not zero. Add one that does that. Note that even though the snd_soc_*_volsw_range() look more appropriate given the _range suffix, they are not suitable because they don't honor the two shift values. The snd_soc_*_volsw() look more generic and are suitable for the task. Signed-off-by: Luca Ceresoli <luca.ceresoli@bootlin.com> Link: https://msgid.link/r/20240305-rk3308-audio-codec-v4-3-312acdbe628f@bootlin.com Signed-off-by: Mark Brown <broonie@kernel.org>
2024-02-19ASoC: Constify pointer to of_phandle_argsKrzysztof Kozlowski
Constify pointer to of_phandle_args in few function arguments, for code safety and self-documenting code. Signed-off-by: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org> Link: https://msgid.link/r/20240216145448.224185-1-krzysztof.kozlowski@linaro.org Signed-off-by: Mark Brown <broonie@kernel.org>
2024-01-08Merge tag 'asoc-v6.8' of ↵Takashi Iwai
https://git.kernel.org/pub/scm/linux/kernel/git/broonie/sound into for-linus ASoC: Updates for v6.8 This is a relatively quiet release, there's a lot of driver specific changes and the usual high level of activity in the SOF core but the one big core change was Mormioto-san's work to support more N:M CPU:CODEC mapping cases. Highlights include: - Enhanced support for N:M CPU:CODEC mappings in the core and in audio-graph-card2. - Support for falling back to older SOF IPC versions where firmware for new versions is not available. - Support for notification of control changes generated by SOF firmware with IPC4. - Device tree support for describing parts of the card which can be active over suspend (for very low power playback or wake word use cases). - ACPI parsing support for the ES83xx driver, reducing the number of quirks neede for x86 systems. - Support for more AMD and Intel systems, NXP i.MX8m MICFIL, Qualcomm SM8250, SM8550, SM8650 and X1E80100. - Removal of Freescale MPC8610 support, the SoC is no longer supported by Linux.
2023-12-19ASoC: soc.h: don't create dummy Component via COMP_DUMMY()Kuninori Morimoto
Many ASoC drivers define CPU/Codec/Platform dai_link by below macro. SND_SOC_DAILINK_DEFS(link, (A) DAILINK_COMP_ARRAY(COMP_CPU("cpu_dai")), (B) DAILINK_COMP_ARRAY(COMP_CODEC("codec", "dai1"), (B) COMP_CODEC("codec", "dai2")), (C) DAILINK_COMP_ARRAY(COMP_EMPTY())); In this case, this macro will be converted to like below [o] = static struct snd_soc_dai_link_component (A) [o] link_cpus[] = {{ .dai_name = "cpu_dai" }}; (B) [o] link_codecs[] = {{ .dai_name = "dai1", .name = "codec" }, { .dai_name = "dai2", .name = "codec" }} (C) [o] link_platforms[] = {{ }}; CPU and Codec info will be filled by COMP_CPU() / COMP_CODEC (= A,B), and Platform will have empty data by COMP_EMPTY() (= C) in this case. Platform empty info will be filled when driver probe() (most of case, CPU info will be copied to use soc-generic-dmaengine-pcm). For example in case of DPCM FE/BE, it will be like below. Codec will be dummy Component / DAI in this case (X). SND_SOC_DAILINK_DEFS(link, DAILINK_COMP_ARRAY(COMP_CPU(...)), (X) DAILINK_COMP_ARRAY(COMP_DUMMY()), DAILINK_COMP_ARRAY(COMP_EMPTY())); (X) part will converted like below [o] link_codecs[] = {{ .name = "snd-soc-dummy", .dai_name = "snd-soc-dummy-dai", }} Even though we already have common asoc_dummy_dlc for dummy Component / DAI, this macro will re-create new dummy dlc. Some drivers defines many dai_link info via SND_SOC_DAILINK_DEFS(), this means many dummy dlc also will be re-created. This is waste of memory. If we can use existing common asoc_dummy_dlc at (X), we can avoid to re-creating dummy dlc, then, we can save the memory. At that time, we want to keep existing code as much as possible, because too many drivers are using this macro. But because of its original style, using common asoc_dummy_dlc from it is very difficult or impossible. So let's change the mind. The macro is used like below SND_SOC_DAILINK_DEFS(link, DAILINK_COMP_ARRAY(COMP_CPU(...)), (x) DAILINK_COMP_ARRAY(COMP_DUMMY()), DAILINK_COMP_ARRAY(COMP_EMPTY())); static struct snd_soc_dai_link dai_links[] = { { .name = ..., .stream_name = ..., (y) SND_SOC_DAILINK_REG(link), }, (y) part will be like below static struct snd_soc_dai_link dai_links[] = { { .name = ..., .stream_name = ..., ^ ... | .codecs = link_codecs, (y) .num_codecs = ARRAY_SIZE(link_codecs), v ... } This patch try to use trick on COMP_DUMMY() - #define COMP_DUMMY() { .name = "snd-soc-dummy", .dai_name = "snd-soc-dummy-dai", } + #define COMP_DUMMY() By this tric, (x) part will be like below. before [o] link_codecs[] = {{ .name = "snd-soc-dummy", .dai_name = "snd-soc-dummy-dai", }} after [o] link_codecs[] = { }; This is same as below [o] link_codecs[0]; This means it has pointer (link_codecs), but the array size is 0. (y) part will be like below. static struct snd_soc_dai_link dai_links[] = { { ... .codecs = link_codecs, .num_codecs = 0, ... }, This is very special settings that normal use usually not do, but new macro do. We can find this special settings on soc-core.c and fill it as "dummy DAI" (= asoc_dummy_dlc). By this tric, we can avoid to re-create dummy dlc and save the memory. This patch add tric at COMP_DUMMY() and add snd_soc_fill_dummy_dai() to fill dummy DAI. Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> Link: https://msgid.link/r/871qbi93qu.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown <broonie@kernel.org>
2023-11-27ASoC: pcm: Honor subformat when configuring runtimeCezary Rojewski
Subformat options are ignored when setting up hardware parameters and assigning PCM stream capabilities. Account for them to allow for granular format selection. As there is only one user currently (format S32_LE), subformat is represented by a simple u32 and stores flags only for that one user alone. Such approach allows for alloc/free-less code until there are more users on the horizon. Acked-by: Mark Brown <broonie@kernel.org> Signed-off-by: Cezary Rojewski <cezary.rojewski@intel.com> Acked-by: Jaroslav Kysela <perex@perex.cz> Link: https://lore.kernel.org/r/20231117120610.1755254-4-cezary.rojewski@intel.com Signed-off-by: Takashi Iwai <tiwai@suse.de>
2023-11-27ASoC: makes CPU/Codec channel connection map more genericKuninori Morimoto
Current ASoC CPU:Codec = N:M connection is using connection mapping idea, but it is used for N < M case only. We want to use it for any case. By this patch, not only N:M connection, but all existing connection (1:1, 1:N, N:N) will use same connection mapping. Then, because it will use default mapping, no conversion patch is needed to exising drivers. More over, CPU:Codec = N:M (N > M) also supported in the same time. ch_maps array will has CPU/Codec index by this patch. Image CPU0 <---> Codec0 CPU1 <-+-> Codec1 CPU2 <-/ ch_map ch_map[0].cpu = 0 ch_map[0].codec = 0 ch_map[1].cpu = 1 ch_map[1].codec = 1 ch_map[2].cpu = 2 ch_map[2].codec = 1 Link: https://lore.kernel.org/r/87fs6wuszr.wl-kuninori.morimoto.gx@renesas.com Link: https://lore.kernel.org/r/878r7yqeo4.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> Reviewed-by: Bard Liao <yung-chuan.liao@linux.intel.com> Tested-by: Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com> Tested-by: Jerome Brunet <jbrunet@baylibre.com> Link: https://lore.kernel.org/r/87ttpq4f2c.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown <broonie@kernel.org>
2023-10-10ASoC: Merge fixes for consistent cs42l43 schemaMark Brown
We have adjacent changes for the cs42l43 DT schema, merge the fixes branch up so that there's a single thing for people to base future changes on.
2023-09-29ASoC: core: Do not call link_exit() on uninitialized rtd objectsAmadeusz Sławiński
On init we have sequence: for_each_card_prelinks(card, i, dai_link) { ret = snd_soc_add_pcm_runtime(card, dai_link); ret = init_some_other_things(...); if (ret) goto probe_end: for_each_card_rtds(card, rtd) { ret = soc_init_pcm_runtime(card, rtd); probe_end: while on exit: for_each_card_rtds(card, rtd) snd_soc_link_exit(rtd); If init_some_other_things() step fails due to error we end up with not fully setup rtds and try to call snd_soc_link_exit on them, which depending on contents on .link_exit handler, can end up dereferencing NULL pointer. Reviewed-by: Cezary Rojewski <cezary.rojewski@intel.com> Signed-off-by: Amadeusz Sławiński <amadeuszx.slawinski@linux.intel.com> Link: https://lore.kernel.org/r/20230929103243.705433-2-amadeuszx.slawinski@linux.intel.com Signed-off-by: Mark Brown <broonie@kernel.org>
2023-09-26ASoC: remove asoc_xxx() compatible macroKuninori Morimoto
No driver is using asoc_xxx() any more. This patch removes compatible macro for asoc_xxx(). Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> Link: https://lore.kernel.org/r/878r8tfo06.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown <broonie@kernel.org>
2023-09-25ASoC: soc.h: convert asoc_xxx() to snd_soc_xxx()Kuninori Morimoto
ASoC is using 2 type of prefix (asoc_xxx() vs snd_soc_xxx()), but there is no particular reason about that [1]. To reduce confusing, standarding these to snd_soc_xxx() is sensible. This patch adds asoc_xxx() macro to keep compatible for a while. It will be removed if all drivers were switched to new style. Link: https://lore.kernel.org/r/87h6td3hus.wl-kuninori.morimoto.gx@renesas.com [1] Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> Link: https://lore.kernel.org/r/87fs3ks26i.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown <broonie@kernel.org>
2023-09-12ASoC: soc-card: Add storage for PCI SSIDRichard Fitzgerald
Add members to struct snd_soc_card to store the PCI subsystem ID (SSID) of the soundcard. The PCI specification provides two registers to store a vendor-specific SSID that can be read by drivers to uniquely identify a particular "soundcard". This is defined in the PCI specification to distinguish products that use the same silicon (and therefore have the same silicon ID) so that product-specific differences can be applied. PCI only defines 0xFFFF as an invalid value. 0x0000 is not defined as invalid. So the usual pattern of zero-filling the struct and then assuming a zero value unset will not work. A flag is included to indicate when the SSID information has been filled in. Unlike DMI information, which has a free-format entirely up to the vendor, the PCI SSID has a strictly defined format and a registry of vendor IDs. It is usual in Windows drivers that the SSID is used as the sole identifier of the specific end-product and the Windows driver contains tables mapping that to information about the hardware setup, rather than using ACPI properties. This SSID is important information for ASoC components that need to apply hardware-specific configuration on PCI-based systems. As the SSID is a generic part of the PCI specification and is treated as identifying the "soundcard", it is reasonable to include this information in struct snd_soc_card, instead of components inventing their own custom ways to pass this information around. Signed-off-by: Richard Fitzgerald <rf@opensource.cirrus.com> Reviewed-by: Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com> Link: https://lore.kernel.org/r/20230912163207.3498161-2-rf@opensource.cirrus.com Signed-off-by: Mark Brown <broonie@kernel.org>
2023-09-11ASoC: soc.h: replace custom COUNT_ARGS() & CONCATENATE() implementationsAndy Shevchenko
Replace custom implementation of the macros from args.h. Signed-off-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com> Reviewed-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> Link: https://lore.kernel.org/r/20230904111524.1740930-1-andriy.shevchenko@linux.intel.com Signed-off-by: Mark Brown <broonie@kernel.org>
2023-07-17ASoC: soc-core.c: add snd_soc_copy_dai_args()Kuninori Morimoto
To use multi Component support, we need to check dai_args whether Card could get DAI from args (CPU/Codec needs set dai_args on DAI driver). If it could, we need to allocate dai_args for dlc. This patch adds snd_soc_copy_dai_args() for it. This is helper function for multi Component support. Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> Link: https://lore.kernel.org/r/87bkgko94e.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown <broonie@kernel.org>
2023-07-17ASoC: soc-core.c: add snd_soc_dlc_use_cpu_as_platform()Kuninori Morimoto
Current snd_soc_is_matching_component() checks "of_node" or "dai_args". Thus coping "of_node" only is not enough to use CPU as Platform. This patch adds snd_soc_dlc_use_cpu_as_platform() and help it. This is helper function for multi Component support. Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> Link: https://lore.kernel.org/r/87cz10o94k.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown <broonie@kernel.org>
2023-07-17ASoC: soc-core.c: add snd_soc_get_dai_via_args()Kuninori Morimoto
To enable multi Component, Card driver need to get DAI via dai_args to identify it. This patch adds snd_soc_get_dai_via_args() for it. This is helper function for multi Component support. Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> Link: https://lore.kernel.org/r/87edlgo94p.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown <broonie@kernel.org>
2023-07-17ASoC: soc-core.c: enable multi ComponentKuninori Morimoto
Current ASoC Card is using dlc (snd_soc_dai_link_component) to find target DAI / Component to be used. Current dlc has below 3 items to identify DAI / Component (a) name for Component (b) of_node for Component (c) dai_name for DAI (a) or (b) is used to identify target Component, and (c) is used to identify DAI. One of the biggest issue on it today is dlc needs "name matching" for "dai_name" (c). It was not a big deal when we were using platform_device, because we could specify nessesary "dai_name" via its platform_data. But we need to find DAI name pointer from whole registered datas and/or each related driver somehow in case of DT, because we can't specify it. Therefore, Card driver parses DT and assumes the DAI, and find its name pointer. How to assume is based on each Component and/or Card. Next biggest issue is Component node (a)/(b). Basically, Component is registered when CPU/Codec driver was probed() (X). Here, 1 Component is possible to have some DAIs. int xxx_probe(struct platform_device *pdev) { ... (X) ret = devm_snd_soc_register_component(pdev->dev, &component_driver, &dai_driver, dai_driver_num); ... } The image of each data will be like below. One note here is "driver" is included for later explanation. +-driver------+ |+-component-+| || dai0|| || dai1|| || ...|| |+-----------+| +-------------+ The point here is 1 driver has 1 Component, because basically driver calles snd_soc_register_component() (= X) once. Here is the very basic CPU/Codec connection image. HW image SW image +-- Board ------------+ +-card--------------------------+ |+-----+ +------+| |+-driver------+ +-driver------+| || CPU | <--> |CodecA|| ||+-component-+| |+-component-+|| |+-----+ +------+| ||| dai|<=>|dai ||| +---------------------+ ||+-----------+| |+-----------+|| |+-------------+ +-------------+| +-------------------------------+ It will be very complex if it has multi DAIs. Here is intuitive easy to understandable HW / SW example. HW image SW image +-- Board ---------------+ +-card--------------------------+ |+--------+ +------+| |+-driver------+ +-driver------+| || CPU ch0| <--> |CodecA|| ||+-component-+| |+-component-+|| || | +------+| ||| ch0 dai|<=>|dai ||| || | +------+| ||| || |+-----------+|| || ch1| <--> |CodecB|| ||| || +-------------+| |+--------+ +------+| ||| || +-driver------+| +------------------------+ ||| || |+-component-+|| ||| ch1 dai|<=>|dai ||| ||+-----------+| |+-----------+|| |+-------------+ +-------------+| +-------------------------------+ It will be handled as multi interface as "one Card". card0,0: CPU-ch0 - CodecA card0,1: CPU-ch1 - CodecB ^ But, here is the HW image example which will be more complex +-- Basic Board ---------+ |+--------+ +------+| || CPU ch0| <--> |CodecA|| || ch1| <-+ +------+| |+--------+ | | +-------------|----------+ +-- expansion board -----+ | | +------+| | +->|CodecB|| | +------+| +------------------------+ We intuitively think we want to handle these as "2 Sound Cards". card0,0: CPU-ch0 - CodecA card1,0: CPU-ch1 - CodecB ^ But below image which we can register today doesn't allow it, because the same Component will be connected to both Card0/1, but it will be rejected by (Z). +-driver------+ |+-component-+| +-card0-------------------------+ ||| || +-driver------+| ||| || |+-component-+|| ||| ch0 dai|<=>|dai ||| ||| || |+-----------+|| ||| || +-------------+| +-------------------------------+ || || +-card1-------------------------+ ||| || +-driver------+| ||| || |+-component-+|| ||| ch1 dai|<=>|dai ||| ||| || |+-----------+|| ||| || +-------------+| +-------------------------------+ |+-----------+| +-------------+ static int soc_probe_component() { ... if (component->card) { (Z) if (component->card != card) { dev_err(component->dev, ...); return -ENODEV; } return 0; } ... } So, how about to call snd_soc_register_component() (= X) multiple times on probe() to avoid buplicated component->card limitation, to be like below ? +-driver------+ +-card0-------------------------+ || | +-driver------+| ||+-component-+| |+-component-+|| ||| ch0 dai|<=>|dai ||| ||+-----------+| |+-----------+|| || | +-------------+| +-------------------------------+ | | +-card1-------------------------+ || | +-driver------+| ||+-component-+| |+-component-+|| ||| ch1 dai|<=>|dai ||| ||+-----------+| |+-----------+|| || | +-------------+| +-------------------------------+ +-------------+ Yes, looks good. But unfortunately it doesn't help us for now. Let's see soc_component_to_node() and snd_soc_is_matching_component() static struct device_node *soc_component_to_node(struct snd_soc_component *component) { ... (A) of_node = component->dev->of_node; ... } static int snd_soc_is_matching_component(...) { ... (B) if (dlc->of_node && component_of_node != dlc->of_node) ... } dlc checkes "of_node" to identify target component (B), but this "of_node" came from component->dev (A) which is added by snd_soc_register_component() (X) on probe(). This means we can have different "component->card", but have same "component->dev" in this case. Even though we calls snd_soc_register_component() (= X) multiple times, all Components have same driver's dev, thus it is impossible to identified the Component. And if it was impossible to identify Component, it is impossible to identify DAI on current implementation. So, how to handle above complex HW image today is 2 patterns. One is handles it as "1 big sound card". The SW image is like below. SW image +-card--------------------------+ |+-driver------+ +-driver------+| ||+-component-+| |+-component-+|| ||| ch0 dai|<=>|dai ||| ||| || |+-----------+|| ||| || +-------------+| ||| || +-driver------+| ||| || |+-component-+|| ||| ch1 dai|<->|dai ||| ||+-----------+| |+-----------+|| |+-------------+ +-------------+| +-------------------------------+ But the problem is not intuitive. We want to handle it as "2 Cards". 2nd pattern is like below. SW image +-card0-------------------------+ |+-driver------+ +-driver------+| ||+-component-+| |+-component-+|| ||| ch0 dai|<=>|dai ||| ||+-----------+| |+-----------+|| |+-------------+ +-------------+| +-------------------------------+ +-card1-------------------------+ |+-driver------+ +-driver------+| ||+-component-+| |+-component-+|| ||| ch1 dai|<=>|dai ||| ||+-----------+| |+-----------+|| |+-------------+ +-------------+| +-------------------------------+ It handles as "2 Cards", but CPU part needs to be probed as 2 drivers. It is also not intuitive. To solve this issue, we need to have multi Component support. In current implementation, we need to identify Component first to identify DAI, and it is using name matching to identify DAI. But how about to be enable to directly identify DAI by unique way instead of name matching ? In such case, we can directly identify DAI, then it can identify Component from DAI. For example Simple-Card / Audio-Graph-Card case, it is specifying DAI via its node. Simple-Card sound-dai = <&cpu-sound>; Audio-Graph-Card dais = <&cpu-sound>; If each CPU/Codec driver keeps this property when probing, we can identify DAI directly from Card. Being able to identify DAI directly means being able to identify its Component as well even though Component has same dev (= B). This patch adds new "dai_node" for it. To keeping compatibility, it checks "dai_node" first if it has, otherwise, use existing method (name matching). Link: https://lore.kernel.org/r/87fskz5yrr.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> Link: https://lore.kernel.org/r/87fs5wo94v.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown <broonie@kernel.org>
2023-06-20ASoC: soc-core.c: add index on snd_soc_of_get_dai_name()Kuninori Morimoto
Current snd_soc_of_get_dai_name() doesn't accept index for #sound-dai-cells. It is not useful for user. This patch adds it. Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> Link: https://lore.kernel.org/r/87pm5qdgng.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown <broonie@kernel.org>
2023-06-20ASoC: soc-core.c: add snd_soc_{of_}get_dlc()Kuninori Morimoto
Current soc-core.c has snd_soc_{of_}get_dai_name() to get DAI name for dlc (snd_soc_dai_link_component). It gets .dai_name, but we need .of_node too. Therefor user need to arrange. It will be more useful if it gets both .dai_name and .of_node. This patch adds snd_soc_{of_}get_dlc() for it, and existing functions uses it. Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> Link: https://lore.kernel.org/r/87r0q6dgnm.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown <broonie@kernel.org>
2023-06-13ASoC: add new trigger ordering methodMark Brown
Merge series from Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>: This patch-set adds new "trigger" starting/stopping method.
2023-06-13ASoC: remove old trigger ordering methodKuninori Morimoto
All drivers switch to use generic trigger ordering method. Let's remove old method. Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> Link: https://lore.kernel.org/r/87legufnyy.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown <broonie@kernel.org>
2023-06-13ASoC: add new trigger ordering methodKuninori Morimoto
Current ASoC is assuming that trigger starting order is Link -> Component -> DAI as default, and its reverse order for stopping. But some Driver / Card want to reorder it for some reasons. We have such flags, but is unbalance like below. struct snd_soc_component_driver :: start_dma_last struct snd_soc_dai_link :: stop_dma_first We want to have more flexible, and more generic method. This patch adds new snd_soc_trigger_order for start/stop at component / DAI-link. Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> Link: https://lore.kernel.org/r/87r0qmfnzx.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown <broonie@kernel.org>
2023-06-13ASoC: add N cpus to M codecs dai link supportBard Liao
Currently, ASoC supports dailinks with the following mappings: 1 cpu DAI to N codec DAIs N cpu DAIs to N codec DAIs But the mapping between N cpu DAIs and M codec DAIs is not supported. The reason is that we didn't have a mechanism to map cpu and codec DAIs This patch suggests a new snd_soc_dai_link_codec_ch_map struct in struct snd_soc_dai_link{} which provides codec DAI to cpu DAI mapping information used to implement N cpu DAIs to M codec DAIs support. When a dailink contains two or more cpu DAIs, we should set channel number of cpus based on its channel mask. The new struct also provides channel mask information for each codec and we can construct the cpu channel mask by combining all codec channel masks which map to the cpu. The N:M mapping is however restricted to the N <= M case due to physical restrictions on a time-multiplexed bus such as I2S/TDM, AC97, SoundWire and HDaudio. Signed-off-by: Bard Liao <yung-chuan.liao@linux.intel.com> Reviewed-by: Péter Ujfalusi <peter.ujfalusi@linux.intel.com> Reviewed-by: Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com> Reviewed-by: Ranjani Sridharan <ranjani.sridharan@linux.intel.com> Link: https://lore.kernel.org/r/20230607031242.1032060-2-yung-chuan.liao@linux.intel.com Signed-off-by: Mark Brown <broonie@kernel.org>
2023-06-06ASoC: add snd_soc_get_stream_cpu()Kuninori Morimoto
We are using get_stream_cpu() to get CPU stream which cares Codec2Codec. But it is static function for now, and we want to use it from other files. This patch makes it global function. Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> Link: https://lore.kernel.org/r/87fs7cj9mf.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown <broonie@kernel.org>
2023-06-06ASoC: soc.h: remove snd_soc_compr_ops :: triggerKuninori Morimoto
ASoC framework is not using trigger call-back for snd_soc_compr_ops. This patch remove it. Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> Link: https://lore.kernel.org/r/87edmwj9m1.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown <broonie@kernel.org>
2023-05-08ASoC: soc-utils.c: add asoc_dummy_dlcKuninori Morimoto
ASoC uses dummy Component, sharing snd_soc_dai_link_component for it is better idea. This patch adds it. Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com Link: https://lore.kernel.org/r/87a5yy0zyk.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown <broonie@kernel.org
2023-04-17ASoC: expand snd_soc_dpcm_mutex_lock/unlock()Kuninori Morimoto
soc-pcm.c has snd_soc_dpcm_mutex_lock/unlock(), but other files can't use it because it is static function. It requests snd_soc_pcm_runtime as parameter (A), but sometimes we want to use it by snd_soc_card (B). (A) static inline void snd_soc_dpcm_mutex_lock(struct snd_soc_pcm_runtime *rtd) { mutex_lock_nested(&rtd->card->pcm_mutex, rtd->card->pcm_subclass); } ^^^^^^^^^ (B) mutex_lock_nested(&card->pcm_mutex, card->pcm_subclass); ^^^^ We want to use it with both "rtd" and "card" for dapm lock/unlock. To enable it, this patch uses _Generic macro. This patch makes snd_soc_dpcm_mutex_{un}lock() global function, and use it on each files. Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> Link: https://lore.kernel.org/r/87bkk1x3ud.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown <broonie@kernel.org>
2023-04-17ASoC: expand snd_soc_dapm_mutex_lock/unlock()Kuninori Morimoto
soc.h has snd_soc_dapm_mutex_lock/unlock() definition and many drivers are using it, but soc-dapm.c is not. 1st reason is snd_soc_dapm_mutex_lock/unlock() requests snd_soc_dapm_context pointer as parameter (A), but sometimes soc-dapm.c needs to use snd_soc_card (B). (A) static inline void snd_soc_dapm_mutex_lock(struct snd_soc_dapm_context *dapm) { mutex_lock_nested(&dapm->card->dapm_mutex, SND_SOC_DAPM_CLASS_RUNTIME); } ^^^^^^^^^^ (B) mutex_lock_nested(&card->dapm_mutex, SND_SOC_DAPM_CLASS_RUNTIME); ^^^^ 2nd reason is it want to use SND_SOC_DAPM_CLASS_INIT for mutex_lock_nested(), but helper is using _RUNTIME (A). The conclusion is we want to use "dapm vs card" and "_RUNTIME vs _INIT" for dapm lock/unlock. To enable this selfish request, this patch uses _Generic macro. We can use snd_soc_dapm_mutex_lock/unlock() for both dapm and card case. snd_soc_dapm_mutex_lock(dapm); snd_soc_dapm_mutex_unlock(dapm); snd_soc_dapm_mutex_lock(card); snd_soc_dapm_mutex_unlock(card); Current soc-dapm.c is using both mutex_lock() and mutex_lock_nested(). This patch handles mutex_lock() as mutex_lock_nested(..., 0), in other words, handles below as same. mutex_lock(&card->dapm_mutex); mutex_lock_nested(&card->dapm_mutex, SND_SOC_DAPM_CLASS_INIT); Because people might misunderstand that _init() is mutex initialization, this patch renames _INIT to _ROOT and adds new snd_soc_dapm_mutex_lock_root() for it. This patch also moves snd_soc_dapm_subclass definition from soc-dapm.h to soc.h to keep related code together. Because very complex soc.h vs soc-dapm.h relationship, it is difficult/impossible to define these helper into soc-dapm.h. Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> Link: https://lore.kernel.org/r/87cz4hx3v0.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown <broonie@kernel.org>
2023-04-05ASoC: soc.h: remove unused params/num_paramsKuninori Morimoto
No drivers are using params/num_params any more. Let's remove these. Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> Link: https://lore.kernel.org/r/87iledc2ke.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown <broonie@kernel.org>
2023-04-05ASoC: soc.h: clarify Codec2Codec paramsKuninori Morimoto
snd_soc_dai_link has params/num_params, but it is unclear that params for what. This patch clarify it is params for Codec2Codec. Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> Link: https://lore.kernel.org/r/87o7o5c2lk.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown <broonie@kernel.org>
2023-03-28ASoC: soc-core.c: add snd_soc_add_pcm_runtimes()Kuninori Morimoto
Current ASoC supports snd_soc_add_pcm_runtime(), but user need to call it one-by-one if it has multi dai_links. This patch adds snd_soc_add_pcm_runtimes() which supports multi dai_links. Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> Link: https://lore.kernel.org/r/87h6u76nhq.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown <broonie@kernel.org>
2023-01-31ASoC: soc.h: add snd_soc_card_is_instantiated() helperKuninori Morimoto
ASoC framework/driver checks whether card was instantiated every where. Then, it should check card pointer too in such case. This patch adds snd_soc_card_is_instantiated() for it. Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> Reviewed-by: Charles Keepax <ckeepax@opensource.cirrus.com> Link: https://lore.kernel.org/r/875ycnfoqp.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown <broonie@kernel.org>
2022-09-20ASoC: soc.h: use array instead of playback/capture_widgetKuninori Morimoto
snd_soc_pcm_runtime has playback/capture_widget for Codec2Coddec. The naming is unclear. This patch names it as c2c_widget and uses array. struct snd_soc_pcm_runtime { ... => struct snd_soc_dapm_widget *playback_widget; => struct snd_soc_dapm_widget *capture_widget; ... } Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> Link: https://lore.kernel.org/r/87pmfqv9mk.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown <broonie@kernel.org>
2022-09-20ASoC: soc.h: use defined number instead of direct numberKuninori Morimoto
snd_soc_pcm_runtime has dpcm for Playback/Capture, but it is defined directly "2". It should use defined number. struct snd_soc_pcm_runtime { ... => struct snd_soc_dpcm_runtime dpcm[2]; ... } This patch fixup it. Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> Link: https://lore.kernel.org/r/87r106v9mv.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown <broonie@kernel.org>
2022-09-20ASoC: soc.h: remove num_cpus/codecsKuninori Morimoto
Current rtd has both dai_link pointer (A) and num_cpus/codecs (B). (A) rtd->dai_link = dai_link; (B) rtd->num_cpus = dai_link->num_cpus; (B) rtd->num_codecs = dai_link->num_codecs; But, we can get num_cpus/codecs (B) via dai_link (A). This means we don't need to keep num_cpus/codecs on rtd. This patch removes these. Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> Link: https://lore.kernel.org/r/87sfkmv9n3.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown <broonie@kernel.org>
2022-08-17ASoC: core: remove setting platform_max in kcontrol macrosSrinivas Kandagatla
platform_max should not be set by the driver, its intended for machine drivers or DT to override the max value for platform specific reasons. So remove setting this from Kcontrol macros. Setting this to max in these macros would limit the range when min value is less then zero. Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@linaro.org> Link: https://lore.kernel.org/r/20220816172129.6661-1-srinivas.kandagatla@linaro.org Signed-off-by: Mark Brown <broonie@kernel.org>
2022-06-22ASoC: core: Make snd_soc_unregister_card() return voidUwe Kleine-König
The function snd_soc_unregister_card() returned 0 unconditionally and most callers don't care to check the return value. Make it return void and adapt the callers that didn't ignore the return value before. This is a preparation for making platform remove callbacks return void. Signed-off-by: Uwe Kleine-König <u.kleine-koenig@pengutronix.de> Link: https://lore.kernel.org/r/20220621145834.198519-1-u.kleine-koenig@pengutronix.de Signed-off-by: Mark Brown <broonie@kernel.org>
2022-06-21ASoC: core: Add new SOC_DOUBLE_SX_TLV macroCharles Keepax
Currently macros only exist for SX style (implicit sign bit 2's compliment) volume controls where the volumes for left and right are in separate registers. Some future Cirrus devices will have both volumes in the same register, as such add a new macro to support this. Signed-off-by: Charles Keepax <ckeepax@opensource.cirrus.com> Link: https://lore.kernel.org/r/20220621102041.1713504-4-ckeepax@opensource.cirrus.com Signed-off-by: Mark Brown <broonie@kernel.org>
2022-06-14ASoC: Merge fixesMark Brown
Required for more changes for the ops.
2022-06-10ASoC: Remove unused hw_write_t typeAmadeusz Sławiński
Commit 81da8a0b7975 ("ASoC: remove codec hw_write/control_data") removed use of hw_write_t in struct snd_soc_codec, but it left type definition. Fully clean it up. Fixes: 81da8a0b7975 ("ASoC: remove codec hw_write/control_data") Signed-off-by: Amadeusz Sławiński <amadeuszx.slawinski@linux.intel.com> Reviewed-by: Cezary Rojewski <cezary.rojewski@intel.com> Link: https://lore.kernel.org/r/20220610124420.4160986-1-amadeuszx.slawinski@linux.intel.com Signed-off-by: Mark Brown <broonie@kernel.org>
2022-06-10ASoC: Introduce 'fixup_controls' card methodMartin Povišer
The new method is called just before the card is registered, providing an opportune time for machine-level drivers to do some final controls amending: deactivating individual controls or obtaining control references for later use. Some controls can be created by DAPM after 'late_probe' has been called, hence the need for this new method. Signed-off-by: Martin Povišer <povik+lin@cutebit.org> Link: https://lore.kernel.org/r/20220606191910.16580-5-povik+lin@cutebit.org Signed-off-by: Mark Brown <broonie@kernel.org>
2022-05-16ASoC: core: Correct spelling fliped -> flippedCharles Keepax
Signed-off-by: Charles Keepax <ckeepax@opensource.cirrus.com> Link: https://lore.kernel.org/r/20220513090532.1450944-1-ckeepax@opensource.cirrus.com Signed-off-by: Mark Brown <broonie@kernel.org>
2022-04-25ASoC: soc.h: Add SOC_SINGLE_S_EXT_TLV macroRichard Fitzgerald
Add a SOC_SINGLE_S_EXT_TLV macro as a convenience wrapper around SOC_DOUBLE_R_S_EXT_TLV for mono volume controls. Signed-off-by: Richard Fitzgerald <rf@opensource.cirrus.com> Link: https://lore.kernel.org/r/20220425125012.3044919-3-rf@opensource.cirrus.com Signed-off-by: Mark Brown <broonie@kernel.org>