summaryrefslogtreecommitdiff
path: root/sound/soc/codecs/cs35l56.c
AgeCommit message (Collapse)AuthorFilesLines
2023-10-10ASoC: Merge fixes for consistent cs42l43 schemaMark Brown1-1/+7
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-10-09ASoC: cs35l56: ASP1 DOUT must default to Hi-Z when not transmittingRichard Fitzgerald1-0/+6
The ASP1 DOUT line must be defaulted to be high-impedance when it is not actually transmitting data for an active channel. In non-SoundWire modes ASP1 will usually be shared by multiple amps so each amp must only drive the line during the slot for an enabled TX channel. In SoundWire mode a custom firmware can use ASP1 as a secondary chip-to-chip audio link or as GPIO. It should be defaulted to high-impedance since by default the purpose of this pin is not known. Backport note: On kernel versions before 6.6 the cs35l56->base.regmap argument to regmap_set_bits() must be changed to cs35l56->regmap. Signed-off-by: Richard Fitzgerald <rf@opensource.cirrus.com> Fixes: e49611252900 ("ASoC: cs35l56: Add driver for Cirrus Logic CS35L56") Link: https://lore.kernel.org/r/20231009153412.30380-1-rf@opensource.cirrus.com Signed-off-by: Mark Brown <broonie@kernel.org>
2023-10-09ASoC: cs35l56: Fix illegal use of init_completion()Richard Fitzgerald1-1/+1
Fix cs35l56_patch() to call reinit_completion() to reinitialize the completion object. It was incorrectly using init_completion(). Signed-off-by: Richard Fitzgerald <rf@opensource.cirrus.com> Fixes: e49611252900 ("ASoC: cs35l56: Add driver for Cirrus Logic CS35L56") Link: https://lore.kernel.org/r/20231006164405.253796-1-rf@opensource.cirrus.com Signed-off-by: Mark Brown <broonie@kernel.org>
2023-09-14ASoC: cs35l56: Omit cs35l56_pm_ops_i2c_spi if I2C/SPI not enabledRichard Fitzgerald1-0/+2
The cs35l56_pm_ops_i2c_spi struct is only needed if either the I2C or SPI modules are selected for building. Otherwise it would be unused bytes, so in that case omit it. Signed-off-by: Richard Fitzgerald <rf@opensource.cirrus.com> Link: https://lore.kernel.org/r/20230914150918.14505-4-rf@opensource.cirrus.com Signed-off-by: Mark Brown <broonie@kernel.org>
2023-09-14ASoC: cs35l56: Use new export macro for dev_pm_opsRichard Fitzgerald1-2/+1
pm.h now has macros to create and export the dev_pm_ops struct only if CONFIG_PM is enabled. Signed-off-by: Richard Fitzgerald <rf@opensource.cirrus.com> Link: https://lore.kernel.org/r/20230914150918.14505-3-rf@opensource.cirrus.com Signed-off-by: Mark Brown <broonie@kernel.org>
2023-09-13ASoC: cs35l56: Use PCI SSID to select specificMark Brown1-0/+11
Merge series from Richard Fitzgerald <rf@opensource.cirrus.com>: The PCI device registers contain a subsystem ID (SSID), that is separate from the silicon ID. The PCI specification defines it thus: "They provide a mechanism for board vendors to distiguish their boards from one another even thought the boards may have the same PCI controller on them." This allows the driver for the silicon part to apply board-speficic settings based on this SSID. The CS35L56 driver uses this to select the correct firmware file for the board. The actual ID is part of the PCI register set of the host audio interface so this set of patches includes extracting the SSID from the Intel audio controller and passing it to the machine driver and then to ASoC components. Other PCI audio controllers will have the same SSID registers, so can use the same mechanism to pass the SSID.
2023-09-12ASoC: cs35l56: Use PCI SSID as the firmware UIDRichard Fitzgerald1-0/+11
If the driver properties do not define a cirrus,firmware-uid try to get the PCI SSID as the UID. On PCI-based systems the PCI SSID is used to uniquely identify the specific sound hardware. This is the standard mechanism for x86 systems and is the way to get a unique system identifier for systems that use the CS35L56 on SoundWire. For non-SoundWire systems there is no Windows equivalent of the ASoC driver in I2C/SPI mode. These would be: 1. HDA systems, which are handled by the HDA subsystem. 2. Linux-specific systems. 3. Composite devices where the cs35l56 is not present in ACPI and is configured using software nodes. Case 2 can use the firmware-uid property, though the PCI SSID is supported as an alternative, as it is the standard PCI mechanism. Case 3 is a SoundWire system where some other codec is the SoundWire bridge device and CS35L56 is not listed in ACPI. As these are SoundWire systems they will normally use the PCI SSID. 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-5-rf@opensource.cirrus.com Signed-off-by: Mark Brown <broonie@kernel.org>
2023-09-11ASoC: cs35l56: Call pm_runtime_dont_use_autosuspend()Richard Fitzgerald1-0/+1
Driver remove() must call pm_runtime_dont_use_autosuspend(). Drivers that call pm_runtime_use_autosuspend() must disable it in driver remove(). Unfortunately until recently this was only mentioned in 1 line in a 900+ line document so most people hadn't noticed this. It has only recently been added to the kerneldoc of pm_runtime_use_autosuspend(). THIS WON'T APPLY CLEANLY TO V6.5 AND EARLIER: We will send a separate backported patch to stable. Signed-off-by: Richard Fitzgerald <rf@opensource.cirrus.com> Link: https://lore.kernel.org/r/20230908101716.2658582-1-rf@opensource.cirrus.com Signed-off-by: Mark Brown <broonie@kernel.org>
2023-08-18ASoC: Merge up fixesMark Brown1-19/+12
For the benefit of CI.
2023-08-17ASoC: cs35l56: Read firmware uuid from a device property instead of _SUBMaciej Strozek1-19/+12
Use a device property "cirrus,firmware-uid" to get the unique firmware identifier instead of using ACPI _SUB. There aren't any products that use _SUB. There will not usually be a _SUB in Soundwire nodes. The ACPI can use a _DSD section for custom properties. There is also a need to support instantiating this driver using software nodes. This is for systems where the CS35L56 is a back-end device and the ACPI refers only to the front-end audio device - there will not be any ACPI references to CS35L56. Fixes: e49611252900 ("ASoC: cs35l56: Add driver for Cirrus Logic CS35L56") Signed-off-by: Maciej Strozek <mstrozek@opensource.cirrus.com> Signed-off-by: Richard Fitzgerald <rf@opensource.cirrus.com> Link: https://lore.kernel.org/r/20230817112712.16637-2-rf@opensource.cirrus.com Signed-off-by: Mark Brown <broonie@kernel.org>
2023-08-15ASoC: cs35l56: Don't overwrite a patched firmwareRichard Fitzgerald1-2/+15
Only attempt to download wmfw/bin files to a non-secured part if it reports FIRMWARE_MISSING. If FIRMWARE_MISSING is false the firmware has already been patched and overwriting the patch could corrupt the running firmware. For a secured part the wmfw/bin can be downloaded even if FIRMWARE_MISSING is false, because they will only patch tunings. Signed-off-by: Richard Fitzgerald <rf@opensource.cirrus.com> Link: https://lore.kernel.org/r/20230815124826.5447-3-rf@opensource.cirrus.com Signed-off-by: Mark Brown <broonie@kernel.org>
2023-08-15ASoC: wm_adsp: Support powering-up DSP without trying to load firmwareRichard Fitzgerald1-2/+2
Add a flag to wm_adsp_power_up() that indicates whether it should attempt to find and load firmware files. This is to support DSPs that have built-in firmware that may already have been patched (for example, by the BIOS). In that case the patch must not be overwritten because that could corrupt the running firmware. Signed-off-by: Richard Fitzgerald <rf@opensource.cirrus.com> Link: https://lore.kernel.org/r/20230815124826.5447-2-rf@opensource.cirrus.com Signed-off-by: Mark Brown <broonie@kernel.org>
2023-08-09ASoC: cs35l56: Call wm_adsp_power_down() before reloading firmwareSimon Trimmer1-0/+1
When cs35l56_system_resume() needs to reload firmware it should call wm_adsp_power_down() to put cs_dsp into a powered-down state before cs35l56_secure_patch() or cs35l56_patch() calls wm_adsp_power_up(). Signed-off-by: Simon Trimmer <simont@opensource.cirrus.com> Signed-off-by: Richard Fitzgerald <rf@opensource.cirrus.com> Link: https://lore.kernel.org/r/20230808164702.21272-6-rf@opensource.cirrus.com Signed-off-by: Mark Brown <broonie@kernel.org>
2023-08-09ASoC: cs35l56: Wait for control port ready during system-resumeRichard Fitzgerald1-0/+6
The CS35L56 could be hard-reset during a system suspend-resume cycle, either by the codec driver, in cs35l56_system_resume_early(), or by ACPI. After a hard reset the driver must wait for the control port to be ready (datasheet tIRS time) before attempting to access the CS35L56. Signed-off-by: Richard Fitzgerald <rf@opensource.cirrus.com> Link: https://lore.kernel.org/r/20230808164702.21272-4-rf@opensource.cirrus.com Signed-off-by: Mark Brown <broonie@kernel.org>
2023-08-09ASoC: cs35l56: Don't rely on GPIOD_OUT_LOW to set RESET initially lowRichard Fitzgerald1-0/+2
The ACPI setting for a GPIO default state has higher priority than the flag passed to devm_gpiod_get_optional() so ACPI can override the GPIOD_OUT_LOW. Explicitly set the GPIO low when hard resetting. Although GPIOD_OUT_LOW can't be relied on this doesn't seem like a reason to stop passing it to devm_gpiod_get_optional(). So we still pass it to state our intent, but can deal with it having no effect. Signed-off-by: Richard Fitzgerald <rf@opensource.cirrus.com> Link: https://lore.kernel.org/r/20230808164702.21272-3-rf@opensource.cirrus.com Signed-off-by: Mark Brown <broonie@kernel.org>
2023-08-09ASoC: cs35l56: Avoid uninitialized variable in cs35l56_set_asp_slot_positions()Richard Fitzgerald1-16/+8
Re-implement setting of ASP TDM slots so that only the common loop to build the register word is factored out. The original cs35l56_set_asp_slot_positions() had an apparent uninitialized variable if the passed register address was neither of the ASP slot registers. In fact this would never happen because the calling code passed valid registers. While it's trivial to initialize the variable or add a default case, actually the only common code was the loop at the end of the function, which simply manipulates some mask values and is identical for either register. Factoring out the regmap_write() didn't really gain anything. So instead re-implement the code to replace the original function with cs35l56_make_tdm_config_word() that only does the loop, and change the calling code to call regmap_write() directly. Signed-off-by: Richard Fitzgerald <rf@opensource.cirrus.com> Link: https://lore.kernel.org/r/20230808164702.21272-2-rf@opensource.cirrus.com Signed-off-by: Mark Brown <broonie@kernel.org>
2023-07-24ASoC: cs35l56: Make a common function to shutdown the DSPSimon Trimmer1-16/+1
Move issuing of a CS35L56_MBOX_CMD_SHUTDOWN command and then waiting for the DSP to reach CS35L56_HALO_STATE_SHUTDOWN in the register appropriate for the hardware revision into a common function. Signed-off-by: Simon Trimmer <simont@opensource.cirrus.com> Signed-off-by: Richard Fitzgerald <rf@opensource.cirrus.com> Acked-by: Mark Brown <broonie@kernel.org> Link: https://lore.kernel.org/r/20230721132120.5523-10-rf@opensource.cirrus.com Signed-off-by: Mark Brown <broonie@kernel.org>
2023-07-24ASoC: cs35l56: Move part of cs35l56_init() to shared libraryRichard Fitzgerald1-69/+2
Part of the initialization code in cs35l56_init() can be re-used by the HDA driver so move it into a new function in the shared library. Signed-off-by: Richard Fitzgerald <rf@opensource.cirrus.com> Acked-by: Mark Brown <broonie@kernel.org> Link: https://lore.kernel.org/r/20230721132120.5523-8-rf@opensource.cirrus.com Signed-off-by: Mark Brown <broonie@kernel.org>
2023-07-24ASoC: cs35l56: Move cs_dsp init into shared libraryRichard Fitzgerald1-10/+1
Move the code that initialized the struct cs_dsp members into the shared library so that the HDA driver can use it. Signed-off-by: Richard Fitzgerald <rf@opensource.cirrus.com> Acked-by: Mark Brown <broonie@kernel.org> Link: https://lore.kernel.org/r/20230721132120.5523-7-rf@opensource.cirrus.com Signed-off-by: Mark Brown <broonie@kernel.org>
2023-07-24ASoC: cs35l56: Move runtime suspend/resume to shared libraryRichard Fitzgerald1-116/+4
The majority of runtime_suspend and runtime_resume handling doesn't have anything specific to the ASoC driver, so can be shared by the HDA driver. Move this code into the shared library. Signed-off-by: Richard Fitzgerald <rf@opensource.cirrus.com> Acked-by: Mark Brown <broonie@kernel.org> Link: https://lore.kernel.org/r/20230721132120.5523-6-rf@opensource.cirrus.com Signed-off-by: Mark Brown <broonie@kernel.org>
2023-07-24ASoC: cs35l56: Move utility functions to shared fileSimon Trimmer1-203/+0
Move the cs35l56 utility functions into the shared file so they are available for use in HDA. Signed-off-by: Simon Trimmer <simont@opensource.cirrus.com> Signed-off-by: Richard Fitzgerald <rf@opensource.cirrus.com> Acked-by: Mark Brown <broonie@kernel.org> Link: https://lore.kernel.org/r/20230721132120.5523-5-rf@opensource.cirrus.com Signed-off-by: Mark Brown <broonie@kernel.org>
2023-07-24ASoC: cs35l56: Convert utility functions to use common data structureSimon Trimmer1-16/+16
Use the new cs35l56_base struct for utility functions. Signed-off-by: Simon Trimmer <simont@opensource.cirrus.com> Signed-off-by: Richard Fitzgerald <rf@opensource.cirrus.com> Acked-by: Mark Brown <broonie@kernel.org> Link: https://lore.kernel.org/r/20230721132120.5523-4-rf@opensource.cirrus.com Signed-off-by: Mark Brown <broonie@kernel.org>
2023-07-24ASoC: cs35l56: Make cs35l56_system_reset() code more genericSimon Trimmer1-6/+6
The function can be more easily reused in HDA if the tracking of whether a soft reset is being performed and whether the device is connected to a SoundWire bus is moved out of the function. Signed-off-by: Simon Trimmer <simont@opensource.cirrus.com> Signed-off-by: Richard Fitzgerald <rf@opensource.cirrus.com> Acked-by: Mark Brown <broonie@kernel.org> Link: https://lore.kernel.org/r/20230721132120.5523-3-rf@opensource.cirrus.com Signed-off-by: Mark Brown <broonie@kernel.org>
2023-07-24ASoC: cs35l56: Move shared data into a common data structureSimon Trimmer1-200/+204
The ASoC and HDA drivers have structures that contain some of the same information - instead of maintaining two locations for this data the drivers should share a common data structure as this will enable common utility functions to be created. The first step is to move the location of these members in the ASoC driver. Signed-off-by: Simon Trimmer <simont@opensource.cirrus.com> Signed-off-by: Richard Fitzgerald <rf@opensource.cirrus.com> Acked-by: Mark Brown <broonie@kernel.org> Link: https://lore.kernel.org/r/20230721132120.5523-2-rf@opensource.cirrus.com Signed-off-by: Mark Brown <broonie@kernel.org>
2023-07-18ASoC: cs35l56: Patch soft registers to defaultsRichard Fitzgerald1-2/+3
The soft (firmware) registers for volume/mute/posture are not reset by a chip soft-reset, so use a regmap patch to set them to defaults. cs35l56_reread_firmware_registers() has been removed. Its intent was to use whatever the firmware set as a default. But the driver now patches the defaults to the registers. Signed-off-by: Richard Fitzgerald <rf@opensource.cirrus.com> Link: https://lore.kernel.org/r/20230718144625.39634-1-rf@opensource.cirrus.com Signed-off-by: Mark Brown <broonie@kernel.org>
2023-06-16ASoC: Merge fixes due to dependenciesMark Brown1-3/+0
So we can apply the tlv320aic3xxx DT conversion.
2023-06-01ASoC: cs35l56: Remove NULL check from cs35l56_sdw_dai_set_stream()Richard Fitzgerald1-3/+0
The dma pointer must be set to the passed stream pointer, even if that pointer is NULL. Fixes: e49611252900 ("ASoC: cs35l56: Add driver for Cirrus Logic CS35L56") Signed-off-by: Richard Fitzgerald <rf@opensource.cirrus.com> Link: https://lore.kernel.org/r/20230601124907.3128170-1-rf@opensource.cirrus.com Signed-off-by: Mark Brown <broonie@kernel.org>
2023-05-30ES8316 audio codec fixes on Rock5BMark Brown1-1/+2
Merge series from Cristian Ciocaltea <cristian.ciocaltea@collabora.com>: This patch series handles a few issues related to the ES8316 audio codec, discovered while doing some testing on the Rock 5B board.
2023-05-19ASoC: cs35l56: In secure mode skip SHUTDOWN and RESET around fw downloadSimon Trimmer1-10/+37
If the device is in secure mode it's unnecessary to send a SHUTDOWN and SYSTEM_RESET around the firmware download. It could only be patching insecure tunings. A tuning patch doesn't need a SHUTDOWN and only needs a REINIT afterwards. This will reduce the overhead of exiting system suspend in secure mode. Signed-off-by: Simon Trimmer <simont@opensource.cirrus.com> Signed-off-by: Richard Fitzgerald <rf@opensource.cirrus.com> Link: https://lore.kernel.org/r/Message-Id: <20230518150250.1121006-4-rf@opensource.cirrus.com> Signed-off-by: Mark Brown <broonie@kernel.org>
2023-05-19ASoC: cs35l56: sdw_write_no_pm() should be performed under a pm_runtime requestSimon Trimmer1-3/+3
SoundWire bus accesses must be performed under the guard of a pm_runtime request, in this case the write was being performed just after the request had been put() and so the bus could not be guaranteed to be available. Signed-off-by: Simon Trimmer <simont@opensource.cirrus.com> Signed-off-by: Richard Fitzgerald <rf@opensource.cirrus.com> Link: https://lore.kernel.org/r/Message-Id: <20230518150250.1121006-3-rf@opensource.cirrus.com> Signed-off-by: Mark Brown <broonie@kernel.org>
2023-05-19ASoC: cs35l56: Move DSP part string generation so that it is done only onceSimon Trimmer1-6/+6
Each time we go through dsp_work() it does a devm_kasprintf() to allocate memory to hold the part name string. It's not strictly a memory leak because devm will free it all if the driver is removed. But we keep allocating more and more memory to hold the same string. Move the allocation so that it is performed after the version and secured state information is gathered and handle allocation errors. Signed-off-by: Simon Trimmer <simont@opensource.cirrus.com> Signed-off-by: Richard Fitzgerald <rf@opensource.cirrus.com> Link: https://lore.kernel.org/r/Message-Id: <20230518150250.1121006-2-rf@opensource.cirrus.com> Signed-off-by: Mark Brown <broonie@kernel.org>
2023-05-15ASoC: cs35l56: Prevent unbalanced pm_runtime in dsp_work() on SoundWireSimon Trimmer1-1/+2
Flush the SoundWire interrupt handler work instead of cancelling it. When a SoundWire interrupt is triggered the pm_runtime is held until the work has completed. It's therefore unsafe to cancel the work, it must be flushed. Signed-off-by: Simon Trimmer <simont@opensource.cirrus.com Signed-off-by: Richard Fitzgerald <rf@opensource.cirrus.com Link: https://lore.kernel.org/r/20230512144237.739000-1-rf@opensource.cirrus.com Signed-off-by: Mark Brown <broonie@kernel.org
2023-04-20ASoC: cs35l56: Remove duplicate mbox log messagesSimon Trimmer1-6/+2
cs35l56_mbox_send() logs a warning when sending a mbox command fails so the callers can be simplified. Signed-off-by: Simon Trimmer <simont@opensource.cirrus.com> Signed-off-by: Richard Fitzgerald <rf@opensource.cirrus.com> Link: https://lore.kernel.org/r/20230420102043.1151830-1-rf@opensource.cirrus.com Signed-off-by: Mark Brown <broonie@kernel.org>
2023-04-18ASoC: cs35l56: Remove SDW1 TX5 and TX6Richard Fitzgerald1-27/+1
Reduce SDW1 to 4 channels and remove the controls for SDW1 TX5 and TX6. The TX5 and TX6 channels have been removed from B0 silicon. There is no need to support them on A1 silicon. Signed-off-by: Richard Fitzgerald <rf@opensource.cirrus.com> Link: https://lore.kernel.org/r/20230418144309.1100721-3-rf@opensource.cirrus.com Signed-off-by: Mark Brown <broonie@kernel.org>
2023-04-18ASoC: cs35l56: Update comment on masking of EINT20 interruptsRichard Fitzgerald1-1/+1
EINT20 contains wake-source interrupts and also interface-blocked interrupts, which all default to unmasked after reset or wake. The comment in cs35l56_init() only mentioned the wake interrupts. Update the comment so it's clear that it's intentional to also mask the *_BLOCKED interrupts. Signed-off-by: Richard Fitzgerald <rf@opensource.cirrus.com> Link: https://lore.kernel.org/r/20230418144309.1100721-2-rf@opensource.cirrus.com Signed-off-by: Mark Brown <broonie@kernel.org>
2023-04-17ASoC: cs35l56: Don't return a value from cs35l56_remove()Simon Trimmer1-3/+1
cs35l56_remove() always returns 0. Two of the functions that call it are void and the other one should only return 0. So there's no point returning anything from cs35l56_remove(). Signed-off-by: Simon Trimmer <simont@opensource.cirrus.com> Signed-off-by: Richard Fitzgerald <rf@opensource.cirrus.com> Link: https://lore.kernel.org/r/20230414133753.653139-6-rf@opensource.cirrus.com Signed-off-by: Mark Brown <broonie@kernel.org>
2023-04-17ASoC: cs35l56: Remove redundant dsp_ready_completionSimon Trimmer1-32/+9
dsp_ready_completion is redundant and can be replaced by a call flush_work() to wait for cs35l56_dsp_work() to complete. As the dsp_work is queued by component_probe() it must run before other ASoC component callbacks and therefore there is no risk of calling flush_work() before the dsp_work() has been queued. Signed-off-by: Simon Trimmer <simont@opensource.cirrus.com> Signed-off-by: Richard Fitzgerald <rf@opensource.cirrus.com> Link: https://lore.kernel.org/r/20230414133753.653139-5-rf@opensource.cirrus.com Signed-off-by: Mark Brown <broonie@kernel.org>
2023-04-17ASoC: cs35l56: Wait for init_complete in cs35l56_component_probe()Simon Trimmer1-7/+6
Moving the wait from the beginning of the cs35l56_dsp_work() into cs35l56_component_probe() will prevent the limbo situation that is an artifact of the two stage SoundWire driver probe and initialisation where the card is all registered and shows in ALSA but doesn't actually work because the hardware didn't enumerate. The other bus drivers perform the probe and init sequentially and are not susceptible to this issue. Signed-off-by: Simon Trimmer <simont@opensource.cirrus.com> Signed-off-by: Richard Fitzgerald <rf@opensource.cirrus.com> Link: https://lore.kernel.org/r/20230414133753.653139-4-rf@opensource.cirrus.com Signed-off-by: Mark Brown <broonie@kernel.org>
2023-04-17ASoC: cs35l56: Allow a wider range for reset pulse widthSimon Trimmer1-5/+9
There is no reason to have such a tight usleep range of 400us and it is acceptable to allow MIN_US * 2. Also wrap the usleep in an inline function. Signed-off-by: Simon Trimmer <simont@opensource.cirrus.com> Signed-off-by: Richard Fitzgerald <rf@opensource.cirrus.com> Link: https://lore.kernel.org/r/168147949455.26.3401634900657387799@mailman-core.alsa-project.org Signed-off-by: Mark Brown <broonie@kernel.org>
2023-04-17ASoC: cs35l56: Rework IRQ allocationSimon Trimmer1-5/+6
The irq member was being set before calling the init function and then cs35l56_irq_request() was called only when the init was successful. However cs35l56_release() calls devm_free_irq() when the irq member is set and therefore if init() fails then this will cause an attempted free of an unallocated IRQ. Instead pass the desired IRQ number to the cs35l56_irq_request() function and set cs35l56->irq only when it has been successfully allocated. Signed-off-by: Simon Trimmer <simont@opensource.cirrus.com> Signed-off-by: Richard Fitzgerald <rf@opensource.cirrus.com> Link: https://lore.kernel.org/r/168147949598.26.711670799488943454@mailman-core.alsa-project.org Signed-off-by: Mark Brown <broonie@kernel.org>
2023-04-12ASoC: cs35l56: Re-patch firmware after system suspendRichard Fitzgerald1-1/+66
Check during cs35l56_system_resume() whether the firmware patch must be applied again. The FIRMWARE_MISSING flag in the PROTECTION_STATUS register indicates whether the firmware has been patched. In non-secure mode the FIRMWARE_MISSING flag is cleared at the end of dsp_work(). If it is set after system-resume we know that dsp_work() must be run again. In secure mode the pre-OS loader will have done the secure patching and cleared the FIRMWARE_MISSING flag. So this flag does not tell us whether firmware memory was lost. But the driver could only be downloading non-secure tunings, which is always safe to do. If the driver has control of RESET we will have asserted it during suspend so the firmware patch will have been lost. The driver would only have control of RESET in non-secure mode. Signed-off-by: Richard Fitzgerald <rf@opensource.cirrus.com> Link: https://lore.kernel.org/r/168122674550.26.8545058503709956172@mailman-core.alsa-project.org Signed-off-by: Mark Brown <broonie@kernel.org>
2023-04-12ASoC: cs35l56: Remove quick-cancelling of dsp_work()Richard Fitzgerald1-7/+1
Delete the 'removing' flag and don't kick init_completion to make a quick cancel of dsp_work(). Just let it timeout on the wait for the completion. Simplify the code to standard cancelling or flushing of the work. This avoids introducing corner cases from a layer of custom signalling. It also avoids potential race conditions when system-suspend handling is added. Unless the hardware is broken, the dsp_work() will already have started and passed the completion before the driver would want to cancel it. Signed-off-by: Richard Fitzgerald <rf@opensource.cirrus.com> Link: https://lore.kernel.org/r/168122674746.26.16881587647873355224@mailman-core.alsa-project.org Signed-off-by: Mark Brown <broonie@kernel.org>
2023-04-12ASoC: cs35l56: Add basic system suspend handlingRichard Fitzgerald1-0/+126
This adds the main handling for system suspend but does not handle re-patching the firmware after system resume. This is a multi-stage suspend and resume because if there is a RESET line it is almost certain that it will be shared by all the amps. So every amp must have done its suspend before we can assert RESET. Likewise we must de-assert RESET before the amps can resume. It's preferable to assert RESET before we turning off regulators, and while they power up. The actual suspend and resume is done by using the pair pm_runtime_force_suspend() and pm_runtime_force_resume() to re-use our runtime suspend/resume sequences. pm_runtime_force_suspend() will disable our pm_runtime. If we were runtime-resumed it calls our runtime_suspend(). pm_runtime_force_resume() re-enables pm_runtime and if we were originally runtime-resumed before the pm_runtime_force_suspend() it calls our runtime_resume(). Otherwise it leaves us runtime-suspended. The general process is therefore: suspend() -> finish dsp_work and then run our runtime_suspend suspend_late() -> assert RESET and turn off supplies resume_early() -> enable supplies and de-assert RESET resume() -> pm_runtime_force_resume() In addition, to prevent the IRQ handler running in the period between pm_runtime_force_suspend() and pm_runtime_force_resume() the parent IRQ is temporarily disabled: - from suspend until suspend_noirq - from resume_noirq until resume Signed-off-by: Richard Fitzgerald <rf@opensource.cirrus.com> Link: https://lore.kernel.org/r/20230411152528.329803-6-rf@opensource.cirrus.com Signed-off-by: Mark Brown <broonie@kernel.org>
2023-04-12ASoC: cs35l56: Always wait for firmware boot in runtime-resumeRichard Fitzgerald1-4/+2
When we are resuming from a system suspend the CS35L56 has probably been hard reset (usually a power-on reset). So we must wait for the firmware to boot. On SoundWire we also need it to re-initialize before we can read the registers to check the CS35L56 state. The simplest way to handle this is for runtime-resume to always wait for firmware boot. If the firmware is already booted the overhead is only one register read. The system-resume will have to runtime-resume the driver anyway before attempting any register access. So this will automatically include the wait for initialization on SoundWire. Signed-off-by: Richard Fitzgerald <rf@opensource.cirrus.com> Link: https://lore.kernel.org/r/20230411152528.329803-5-rf@opensource.cirrus.com Signed-off-by: Mark Brown <broonie@kernel.org>
2023-04-12ASoC: cs35l56: Skip first init_completion wait in dsp_work if init_doneRichard Fitzgerald1-1/+2
At the start of dsp_work() only wait for init_completion if !init_done. This allows system suspend to re-queue dsp_work() without having to do a dummy complete() of init_completion. A dummy completion in system suspend would have to be conditional on init_done. But that would create a possible race condition between our system resume and cs35l56_init() in the corner case that we suspend right after the SoundWire core has enumerated and reported ATTACHED. It is safer and simpler to have cs35l56_init() as the only place that init_completion is completed, and dsp_work() as the only place that it is consumed. Signed-off-by: Richard Fitzgerald <rf@opensource.cirrus.com> Link: https://lore.kernel.org/r/20230411152528.329803-4-rf@opensource.cirrus.com Signed-off-by: Mark Brown <broonie@kernel.org>
2023-04-12ASoC: cs35l56: Use DAPM widget for firmware PLAY/PAUSERichard Fitzgerald1-50/+55
If we use a DAPM widget instead of mute_stream() to send the PLAY command we can issue the plays to multiple amps in parallel. With mute_stream each codec driver instance is called one at a time so we get N * PS0 delay time. DAPM does each stage on every widget in a card before moving to the next stage. So all amps will do the PRE_PMU then all will do the POST_PMU. The PLAY is sent in the PRE_PMU so that they all power-up in parallel. After the PS0 wait in the first POST_PMU all the other amps will also be ready so there won't be any extra delay, or it will be negligible. There's also no point waiting for the MBOX ack in the PRE_PMU. We won't see a PS0 state in POST_PMU if it didn't ack the PLAY command. So we can save a little extra time. Signed-off-by: Richard Fitzgerald <rf@opensource.cirrus.com> Link: https://lore.kernel.org/r/20230411152528.329803-3-rf@opensource.cirrus.com Signed-off-by: Mark Brown <broonie@kernel.org>
2023-03-24ASoC: cs35l56: Fix an unsigned comparison which can never be negativeJiapeng Chong1-1/+3
The variable 'rv' is defined as unsigned type, so the following if statement is invalid, we can modify the type of rv to int. if (rv < 0) { dev_err(cs35l56->dev, "irq: failed to get pm_runtime: %d\n", rv); goto err_unlock; } ./sound/soc/codecs/cs35l56.c:333:5-7: WARNING: Unsigned expression compared with zero: rv < 0. Reported-by: Abaci Robot <abaci@linux.alibaba.com> Link: https://bugzilla.openanolis.cn/show_bug.cgi?id=4599 Signed-off-by: Jiapeng Chong <jiapeng.chong@linux.alibaba.com> Reviewed-by: Richard Fitzgerald <rf@opensource.cirrus.com> Link: https://lore.kernel.org/r/20230324022303.121485-1-jiapeng.chong@linux.alibaba.com Signed-off-by: Mark Brown <broonie@kernel.org>
2023-03-21ASoC: cs35l56: Add driver for Cirrus Logic CS35L56Richard Fitzgerald1-0/+1461
The CS35L56 combines a high-performance mono audio amplifier, Class-H tracking inductive boost converter, Halo Core(TM) DSP and a DC-DC boost converter supporting Class-H tracking. Supported control interfaces are I2C, SPI or SoundWire. Supported audio interfaces are I2S/TDM or SoundWire. Most chip functionality is controlled by on-board ROM firmware that is always running. The driver must apply patch/tune to the firmware before using the CS35L56. Signed-off-by: Simon Trimmer <simont@opensource.cirrus.com> Signed-off-by: Richard Fitzgerald <rf@opensource.cirrus.com> Link: https://lore.kernel.org/r/20230320112245.115720-9-rf@opensource.cirrus.com Signed-off-by: Mark Brown <broonie@kernel.org>