ALSA: hda: Allow to fetch hlink by ID
authorCezary Rojewski <cezary.rojewski@intel.com>
Mon, 7 Apr 2025 11:23:43 +0000 (13:23 +0200)
committerMark Brown <broonie@kernel.org>
Mon, 7 Apr 2025 13:39:55 +0000 (14:39 +0100)
Starting with LNL platform, Intel HDAudio Links carry IDs specifying
non-HDAudio transfer type they help facilitate e.g.: 0xC0 for I2S as
defined by AZX_REG_ML_LEPTR_ID_INTEL_SSP.

The mechanism accounts for LEPTR register as it is Reserved if
LCAP.ALT for given Link equals 0.

Reviewed-by: Amadeusz Sławiński <amadeuszx.slawinski@linux.intel.com>
Signed-off-by: Cezary Rojewski <cezary.rojewski@intel.com>
Acked-by: Liam Girdwood <liam.r.girdwood@linux.intel.com>
Link: https://patch.msgid.link/20250407112352.3720779-2-cezary.rojewski@intel.com
Signed-off-by: Mark Brown <broonie@kernel.org>
include/sound/hdaudio_ext.h
sound/hda/ext/hdac_ext_controller.c

index 4c7a40e149a594dbe0f31205b7714dc7012982bb..60ec12e3b72f8d3b1db6df3b68880a12bae101a9 100644 (file)
@@ -22,6 +22,7 @@ void snd_hdac_ext_bus_ppcap_enable(struct hdac_bus *chip, bool enable);
 void snd_hdac_ext_bus_ppcap_int_enable(struct hdac_bus *chip, bool enable);
 
 int snd_hdac_ext_bus_get_ml_capabilities(struct hdac_bus *bus);
+struct hdac_ext_link *snd_hdac_ext_bus_get_hlink_by_id(struct hdac_bus *bus, u32 id);
 struct hdac_ext_link *snd_hdac_ext_bus_get_hlink_by_addr(struct hdac_bus *bus, int addr);
 struct hdac_ext_link *snd_hdac_ext_bus_get_hlink_by_name(struct hdac_bus *bus,
                                                         const char *codec_name);
@@ -97,12 +98,16 @@ struct hdac_ext_link {
        void __iomem *ml_addr; /* link output stream reg pointer */
        u32 lcaps;   /* link capablities */
        u16 lsdiid;  /* link sdi identifier */
+       u32 id;
 
        int ref_count;
 
        struct list_head list;
 };
 
+#define hdac_ext_link_alt(link)                ((link)->lcaps & AZX_ML_HDA_LCAP_ALT)
+#define hdac_ext_link_ofls(link)       ((link)->lcaps & AZX_ML_HDA_LCAP_OFLS)
+
 int snd_hdac_ext_bus_link_power_up(struct hdac_ext_link *hlink);
 int snd_hdac_ext_bus_link_power_down(struct hdac_ext_link *hlink);
 int snd_hdac_ext_bus_link_power_up_all(struct hdac_bus *bus);
index 6199bb60ccf00f95e78f765bafbb62ab902b683e..2ec1531d1c1b511e892020b8314decc5d88d3f5e 100644 (file)
@@ -9,6 +9,7 @@
  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  */
 
+#include <linux/bitfield.h>
 #include <linux/delay.h>
 #include <linux/slab.h>
 #include <sound/hda_register.h>
@@ -81,6 +82,7 @@ int snd_hdac_ext_bus_get_ml_capabilities(struct hdac_bus *bus)
        int idx;
        u32 link_count;
        struct hdac_ext_link *hlink;
+       u32 leptr;
 
        link_count = readl(bus->mlcap + AZX_REG_ML_MLCD) + 1;
 
@@ -97,6 +99,11 @@ int snd_hdac_ext_bus_get_ml_capabilities(struct hdac_bus *bus)
                hlink->lcaps  = readl(hlink->ml_addr + AZX_REG_ML_LCAP);
                hlink->lsdiid = readw(hlink->ml_addr + AZX_REG_ML_LSDIID);
 
+               if (hdac_ext_link_alt(hlink)) {
+                       leptr = readl(hlink->ml_addr + AZX_REG_ML_LEPTR);
+                       hlink->id = FIELD_GET(AZX_REG_ML_LEPTR_ID, leptr);
+               }
+
                /* since link in On, update the ref */
                hlink->ref_count = 1;
 
@@ -125,6 +132,17 @@ void snd_hdac_ext_link_free_all(struct hdac_bus *bus)
 }
 EXPORT_SYMBOL_GPL(snd_hdac_ext_link_free_all);
 
+struct hdac_ext_link *snd_hdac_ext_bus_get_hlink_by_id(struct hdac_bus *bus, u32 id)
+{
+       struct hdac_ext_link *hlink;
+
+       list_for_each_entry(hlink, &bus->hlink_list, list)
+               if (hdac_ext_link_alt(hlink) && hlink->id == id)
+                       return hlink;
+       return NULL;
+}
+EXPORT_SYMBOL_GPL(snd_hdac_ext_bus_get_hlink_by_id);
+
 /**
  * snd_hdac_ext_bus_get_hlink_by_addr - get hlink at specified address
  * @bus: hlink's parent bus device