mirror of
https://github.com/torvalds/linux
synced 2024-10-15 15:59:15 +00:00
fc7dab8ec0
Add helpers to program SPA/CPA bits, using a mutex to access the shared LCTL register if required. All links are managed with the same LCTLx.SPA bits. However there are quite a few implementation details to be aware of: Legacy HDaudio multi-links are powered-up when exiting reset, which requires the ref_count to be manually set to one when initializing the link. Alternate links for SoundWire/DMIC/SSP need to be explicitly powered-up before accessing the SHIM/IP/Vendor-Specific SHIM space for each sublink. DMIC/SSP/SoundWire are all different cases with a different device/dai/hlink relationship. SoundWire will handle power management with the auxiliary device resume/suspend routine. The ref_count is not necessary in this case. The DMIC/SSP will by contrast handle the power management from DAI .startup and .shutdown callbacks. The SSP has a 1:1 mapping between sublink and DAI, but it's bidirectional so the ref_count will help avoid turning off the sublink when one of the two directions is still in use. The DMIC has a single link but two DAIs for data generated at different sampling frequencies, again the ref_count will make sure the two DAIs can be used concurrently. And last the SoundWire Intel require power-up/down and bank switch to be handled with a lock already taken, so the 'eml_lock' is made optional with the _unlocked versions of the helpers. Note that the _check_power_active() implementation is similar to previous helpers in sound/hda/ext, with sleep duration and timeout aligned with hardware recommendations. If desired, this helper could be modified in a second step with .e.g. readl_poll_timeout() Signed-off-by: Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com> Reviewed-by: Rander Wang <rander.wang@intel.com> Reviewed-by: Péter Ujfalusi <peter.ujfalusi@linux.intel.com> Reviewed-by: Ranjani Sridharan <ranjani.sridharan@linux.intel.com> Signed-off-by: Peter Ujfalusi <peter.ujfalusi@linux.intel.com> Reviewed-by: Takashi Iwai <tiwai@suse.de> Link: https://lore.kernel.org/r/20230404104127.5629-9-peter.ujfalusi@linux.intel.com Signed-off-by: Mark Brown <broonie@kernel.org>
64 lines
1.8 KiB
C
64 lines
1.8 KiB
C
/* SPDX-License-Identifier: (GPL-2.0-only OR BSD-3-Clause) */
|
|
/*
|
|
* This file is provided under a dual BSD/GPLv2 license. When using or
|
|
* redistributing this file, you may do so under either license.
|
|
*
|
|
* Copyright(c) 2022-2023 Intel Corporation. All rights reserved.
|
|
*/
|
|
|
|
struct hdac_bus;
|
|
|
|
#if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA_MLINK)
|
|
|
|
int hda_bus_ml_init(struct hdac_bus *bus);
|
|
void hda_bus_ml_free(struct hdac_bus *bus);
|
|
|
|
int hdac_bus_eml_power_up(struct hdac_bus *bus, bool alt, int elid, int sublink);
|
|
int hdac_bus_eml_power_up_unlocked(struct hdac_bus *bus, bool alt, int elid, int sublink);
|
|
|
|
int hdac_bus_eml_power_down(struct hdac_bus *bus, bool alt, int elid, int sublink);
|
|
int hdac_bus_eml_power_down_unlocked(struct hdac_bus *bus, bool alt, int elid, int sublink);
|
|
|
|
void hda_bus_ml_put_all(struct hdac_bus *bus);
|
|
void hda_bus_ml_reset_losidv(struct hdac_bus *bus);
|
|
int hda_bus_ml_resume(struct hdac_bus *bus);
|
|
int hda_bus_ml_suspend(struct hdac_bus *bus);
|
|
|
|
#else
|
|
|
|
static inline int
|
|
hda_bus_ml_init(struct hdac_bus *bus) { return 0; }
|
|
|
|
static inline void hda_bus_ml_free(struct hdac_bus *bus) { }
|
|
|
|
static inline int
|
|
hdac_bus_eml_power_up(struct hdac_bus *bus, bool alt, int elid, int sublink)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
static inline int
|
|
hdac_bus_eml_power_up_unlocked(struct hdac_bus *bus, bool alt, int elid, int sublink)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
static inline int
|
|
hdac_bus_eml_power_down(struct hdac_bus *bus, bool alt, int elid, int sublink)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
static inline int
|
|
hdac_bus_eml_power_down_unlocked(struct hdac_bus *bus, bool alt, int elid, int sublink)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
static inline void hda_bus_ml_put_all(struct hdac_bus *bus) { }
|
|
static inline void hda_bus_ml_reset_losidv(struct hdac_bus *bus) { }
|
|
static inline int hda_bus_ml_resume(struct hdac_bus *bus) { return 0; }
|
|
static inline int hda_bus_ml_suspend(struct hdac_bus *bus) { return 0; }
|
|
|
|
#endif /* CONFIG_SND_SOC_SOF_HDA */
|