summaryrefslogtreecommitdiff
path: root/include/sound/hda-mlink.h
diff options
context:
space:
mode:
authorPierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>2023-04-04 13:41:17 +0300
committerMark Brown <broonie@kernel.org>2023-04-06 16:45:40 +0100
commitfc7dab8ec0b4a451dd5737aa4f06a0e8bd6efa32 (patch)
tree44fa547fa0863e4772c48da746b40161c96cd403 /include/sound/hda-mlink.h
parent4c2d4e446d5673db2c653a6e53ca9be908582c4e (diff)
ASoC: SOF: Intel: hda-mlink: introduce helpers for 'extended links' PM
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>
Diffstat (limited to 'include/sound/hda-mlink.h')
-rw-r--r--include/sound/hda-mlink.h32
1 files changed, 32 insertions, 0 deletions
diff --git a/include/sound/hda-mlink.h b/include/sound/hda-mlink.h
index 8048bf01c133..6ecb4c29e472 100644
--- a/include/sound/hda-mlink.h
+++ b/include/sound/hda-mlink.h
@@ -12,6 +12,13 @@ struct hdac_bus;
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);
@@ -23,6 +30,31 @@ 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; }