···469469470470 If you are unsure what to do, do not enable this option.471471472472+config ACPI_NHLT473473+ bool474474+472475source "drivers/acpi/nfit/Kconfig"473476source "drivers/acpi/numa/Kconfig"474477source "drivers/acpi/apei/Kconfig"
···11+// SPDX-License-Identifier: GPL-2.0-only22+/*33+ * Copyright(c) 2023-2024 Intel Corporation44+ *55+ * Authors: Cezary Rojewski <cezary.rojewski@intel.com>66+ * Amadeusz Slawinski <amadeuszx.slawinski@linux.intel.com>77+ */88+99+#define pr_fmt(fmt) "ACPI: NHLT: " fmt1010+1111+#include <linux/acpi.h>1212+#include <linux/errno.h>1313+#include <linux/export.h>1414+#include <linux/minmax.h>1515+#include <linux/printk.h>1616+#include <linux/types.h>1717+#include <acpi/nhlt.h>1818+1919+static struct acpi_table_nhlt *acpi_gbl_nhlt;2020+2121+static struct acpi_table_nhlt empty_nhlt = {2222+ .header = {2323+ .signature = ACPI_SIG_NHLT,2424+ },2525+};2626+2727+/**2828+ * acpi_nhlt_get_gbl_table - Retrieve a pointer to the first NHLT table.2929+ *3030+ * If there is no NHLT in the system, acpi_gbl_nhlt will instead point to an3131+ * empty table.3232+ *3333+ * Return: ACPI status code of the operation.3434+ */3535+acpi_status acpi_nhlt_get_gbl_table(void)3636+{3737+ acpi_status status;3838+3939+ status = acpi_get_table(ACPI_SIG_NHLT, 0, (struct acpi_table_header **)(&acpi_gbl_nhlt));4040+ if (!acpi_gbl_nhlt)4141+ acpi_gbl_nhlt = &empty_nhlt;4242+ return status;4343+}4444+EXPORT_SYMBOL_GPL(acpi_nhlt_get_gbl_table);4545+4646+/**4747+ * acpi_nhlt_put_gbl_table - Release the global NHLT table.4848+ */4949+void acpi_nhlt_put_gbl_table(void)5050+{5151+ acpi_put_table((struct acpi_table_header *)acpi_gbl_nhlt);5252+}5353+EXPORT_SYMBOL_GPL(acpi_nhlt_put_gbl_table);5454+5555+/**5656+ * acpi_nhlt_endpoint_match - Verify if an endpoint matches criteria.5757+ * @ep: the endpoint to check.5858+ * @link_type: the hardware link type, e.g.: PDM or SSP.5959+ * @dev_type: the device type.6060+ * @dir: stream direction.6161+ * @bus_id: the ID of virtual bus hosting the endpoint.6262+ *6363+ * Either of @link_type, @dev_type, @dir or @bus_id may be set to a negative6464+ * value to ignore the parameter when matching.6565+ *6666+ * Return: %true if endpoint matches specified criteria or %false otherwise.6767+ */6868+bool acpi_nhlt_endpoint_match(const struct acpi_nhlt_endpoint *ep,6969+ int link_type, int dev_type, int dir, int bus_id)7070+{7171+ return ep &&7272+ (link_type < 0 || ep->link_type == link_type) &&7373+ (dev_type < 0 || ep->device_type == dev_type) &&7474+ (bus_id < 0 || ep->virtual_bus_id == bus_id) &&7575+ (dir < 0 || ep->direction == dir);7676+}7777+EXPORT_SYMBOL_GPL(acpi_nhlt_endpoint_match);7878+7979+/**8080+ * acpi_nhlt_tb_find_endpoint - Search a NHLT table for an endpoint.8181+ * @tb: the table to search.8282+ * @link_type: the hardware link type, e.g.: PDM or SSP.8383+ * @dev_type: the device type.8484+ * @dir: stream direction.8585+ * @bus_id: the ID of virtual bus hosting the endpoint.8686+ *8787+ * Either of @link_type, @dev_type, @dir or @bus_id may be set to a negative8888+ * value to ignore the parameter during the search.8989+ *9090+ * Return: A pointer to endpoint matching the criteria, %NULL if not found or9191+ * an ERR_PTR() otherwise.9292+ */9393+struct acpi_nhlt_endpoint *9494+acpi_nhlt_tb_find_endpoint(const struct acpi_table_nhlt *tb,9595+ int link_type, int dev_type, int dir, int bus_id)9696+{9797+ struct acpi_nhlt_endpoint *ep;9898+9999+ for_each_nhlt_endpoint(tb, ep)100100+ if (acpi_nhlt_endpoint_match(ep, link_type, dev_type, dir, bus_id))101101+ return ep;102102+ return NULL;103103+}104104+EXPORT_SYMBOL_GPL(acpi_nhlt_tb_find_endpoint);105105+106106+/**107107+ * acpi_nhlt_find_endpoint - Search all NHLT tables for an endpoint.108108+ * @link_type: the hardware link type, e.g.: PDM or SSP.109109+ * @dev_type: the device type.110110+ * @dir: stream direction.111111+ * @bus_id: the ID of virtual bus hosting the endpoint.112112+ *113113+ * Either of @link_type, @dev_type, @dir or @bus_id may be set to a negative114114+ * value to ignore the parameter during the search.115115+ *116116+ * Return: A pointer to endpoint matching the criteria, %NULL if not found or117117+ * an ERR_PTR() otherwise.118118+ */119119+struct acpi_nhlt_endpoint *120120+acpi_nhlt_find_endpoint(int link_type, int dev_type, int dir, int bus_id)121121+{122122+ /* TODO: Currently limited to table of index 0. */123123+ return acpi_nhlt_tb_find_endpoint(acpi_gbl_nhlt, link_type, dev_type, dir, bus_id);124124+}125125+EXPORT_SYMBOL_GPL(acpi_nhlt_find_endpoint);126126+127127+/**128128+ * acpi_nhlt_endpoint_find_fmtcfg - Search endpoint's formats configuration space129129+ * for a specific format.130130+ * @ep: the endpoint to search.131131+ * @ch: number of channels.132132+ * @rate: samples per second.133133+ * @vbps: valid bits per sample.134134+ * @bps: bits per sample.135135+ *136136+ * Return: A pointer to format matching the criteria, %NULL if not found or137137+ * an ERR_PTR() otherwise.138138+ */139139+struct acpi_nhlt_format_config *140140+acpi_nhlt_endpoint_find_fmtcfg(const struct acpi_nhlt_endpoint *ep,141141+ u16 ch, u32 rate, u16 vbps, u16 bps)142142+{143143+ struct acpi_nhlt_wave_formatext *wav;144144+ struct acpi_nhlt_format_config *fmt;145145+146146+ for_each_nhlt_endpoint_fmtcfg(ep, fmt) {147147+ wav = &fmt->format;148148+149149+ if (wav->valid_bits_per_sample == vbps &&150150+ wav->samples_per_sec == rate &&151151+ wav->bits_per_sample == bps &&152152+ wav->channel_count == ch)153153+ return fmt;154154+ }155155+156156+ return NULL;157157+}158158+EXPORT_SYMBOL_GPL(acpi_nhlt_endpoint_find_fmtcfg);159159+160160+/**161161+ * acpi_nhlt_tb_find_fmtcfg - Search a NHLT table for a specific format.162162+ * @tb: the table to search.163163+ * @link_type: the hardware link type, e.g.: PDM or SSP.164164+ * @dev_type: the device type.165165+ * @dir: stream direction.166166+ * @bus_id: the ID of virtual bus hosting the endpoint.167167+ *168168+ * @ch: number of channels.169169+ * @rate: samples per second.170170+ * @vbps: valid bits per sample.171171+ * @bps: bits per sample.172172+ *173173+ * Either of @link_type, @dev_type, @dir or @bus_id may be set to a negative174174+ * value to ignore the parameter during the search.175175+ *176176+ * Return: A pointer to format matching the criteria, %NULL if not found or177177+ * an ERR_PTR() otherwise.178178+ */179179+struct acpi_nhlt_format_config *180180+acpi_nhlt_tb_find_fmtcfg(const struct acpi_table_nhlt *tb,181181+ int link_type, int dev_type, int dir, int bus_id,182182+ u16 ch, u32 rate, u16 vbps, u16 bps)183183+{184184+ struct acpi_nhlt_format_config *fmt;185185+ struct acpi_nhlt_endpoint *ep;186186+187187+ for_each_nhlt_endpoint(tb, ep) {188188+ if (!acpi_nhlt_endpoint_match(ep, link_type, dev_type, dir, bus_id))189189+ continue;190190+191191+ fmt = acpi_nhlt_endpoint_find_fmtcfg(ep, ch, rate, vbps, bps);192192+ if (fmt)193193+ return fmt;194194+ }195195+196196+ return NULL;197197+}198198+EXPORT_SYMBOL_GPL(acpi_nhlt_tb_find_fmtcfg);199199+200200+/**201201+ * acpi_nhlt_find_fmtcfg - Search all NHLT tables for a specific format.202202+ * @link_type: the hardware link type, e.g.: PDM or SSP.203203+ * @dev_type: the device type.204204+ * @dir: stream direction.205205+ * @bus_id: the ID of virtual bus hosting the endpoint.206206+ *207207+ * @ch: number of channels.208208+ * @rate: samples per second.209209+ * @vbps: valid bits per sample.210210+ * @bps: bits per sample.211211+ *212212+ * Either of @link_type, @dev_type, @dir or @bus_id may be set to a negative213213+ * value to ignore the parameter during the search.214214+ *215215+ * Return: A pointer to format matching the criteria, %NULL if not found or216216+ * an ERR_PTR() otherwise.217217+ */218218+struct acpi_nhlt_format_config *219219+acpi_nhlt_find_fmtcfg(int link_type, int dev_type, int dir, int bus_id,220220+ u16 ch, u32 rate, u16 vbps, u16 bps)221221+{222222+ /* TODO: Currently limited to table of index 0. */223223+ return acpi_nhlt_tb_find_fmtcfg(acpi_gbl_nhlt, link_type, dev_type, dir, bus_id,224224+ ch, rate, vbps, bps);225225+}226226+EXPORT_SYMBOL_GPL(acpi_nhlt_find_fmtcfg);227227+228228+static bool acpi_nhlt_config_is_micdevice(struct acpi_nhlt_config *cfg)229229+{230230+ return cfg->capabilities_size >= sizeof(struct acpi_nhlt_micdevice_config);231231+}232232+233233+static bool acpi_nhlt_config_is_vendor_micdevice(struct acpi_nhlt_config *cfg)234234+{235235+ struct acpi_nhlt_vendor_micdevice_config *devcfg = __acpi_nhlt_config_caps(cfg);236236+237237+ return cfg->capabilities_size >= sizeof(*devcfg) &&238238+ cfg->capabilities_size == struct_size(devcfg, mics, devcfg->mics_count);239239+}240240+241241+/**242242+ * acpi_nhlt_endpoint_mic_count - Retrieve number of digital microphones for a PDM endpoint.243243+ * @ep: the endpoint to return microphones count for.244244+ *245245+ * Return: A number of microphones or an error code if an invalid endpoint is provided.246246+ */247247+int acpi_nhlt_endpoint_mic_count(const struct acpi_nhlt_endpoint *ep)248248+{249249+ union acpi_nhlt_device_config *devcfg;250250+ struct acpi_nhlt_format_config *fmt;251251+ struct acpi_nhlt_config *cfg;252252+ u16 max_ch = 0;253253+254254+ if (!ep || ep->link_type != ACPI_NHLT_LINKTYPE_PDM)255255+ return -EINVAL;256256+257257+ /* Find max number of channels based on formats configuration. */258258+ for_each_nhlt_endpoint_fmtcfg(ep, fmt)259259+ max_ch = max(fmt->format.channel_count, max_ch);260260+261261+ cfg = __acpi_nhlt_endpoint_config(ep);262262+ devcfg = __acpi_nhlt_config_caps(cfg);263263+264264+ /* If @ep is not a mic array, fallback to channels count. */265265+ if (!acpi_nhlt_config_is_micdevice(cfg) ||266266+ devcfg->gen.config_type != ACPI_NHLT_CONFIGTYPE_MICARRAY)267267+ return max_ch;268268+269269+ switch (devcfg->mic.array_type) {270270+ case ACPI_NHLT_ARRAYTYPE_LINEAR2_SMALL:271271+ case ACPI_NHLT_ARRAYTYPE_LINEAR2_BIG:272272+ return 2;273273+274274+ case ACPI_NHLT_ARRAYTYPE_LINEAR4_GEO1:275275+ case ACPI_NHLT_ARRAYTYPE_PLANAR4_LSHAPED:276276+ case ACPI_NHLT_ARRAYTYPE_LINEAR4_GEO2:277277+ return 4;278278+279279+ case ACPI_NHLT_ARRAYTYPE_VENDOR:280280+ if (!acpi_nhlt_config_is_vendor_micdevice(cfg))281281+ return -EINVAL;282282+ return devcfg->vendor_mic.mics_count;283283+284284+ default:285285+ pr_warn("undefined mic array type: %#x\n", devcfg->mic.array_type);286286+ return max_ch;287287+ }288288+}289289+EXPORT_SYMBOL_GPL(acpi_nhlt_endpoint_mic_count);
+117-182
include/acpi/actbl2.h
···1889188918901890/*******************************************************************************18911891 *18921892- * NHLT - Non HD Audio Link Table18931893- *18941894- * Conforms to: Intel Smart Sound Technology NHLT Specification18951895- * Version 0.8.1, January 2020.18921892+ * NHLT - Non HDAudio Link Table18931893+ * Version 118961894 *18971895 ******************************************************************************/1898189618991899-/* Main table */19001900-19011897struct acpi_table_nhlt {19021898 struct acpi_table_header header; /* Common ACPI table header */19031903- u8 endpoint_count;18991899+ u8 endpoints_count;19001900+ /*19011901+ * struct acpi_nhlt_endpoint endpoints[];19021902+ * struct acpi_nhlt_config oed_config;19031903+ */19041904};1905190519061906struct acpi_nhlt_endpoint {19071907- u32 descriptor_length;19071907+ u32 length;19081908 u8 link_type;19091909 u8 instance_id;19101910 u16 vendor_id;···19141914 u8 device_type;19151915 u8 direction;19161916 u8 virtual_bus_id;19171917+ /*19181918+ * struct acpi_nhlt_config device_config;19191919+ * struct acpi_nhlt_formats_config formats_config;19201920+ * struct acpi_nhlt_devices_info devices_info;19211921+ */19171922};1918192319191919-/* Types for link_type field above */19201920-19211921-#define ACPI_NHLT_RESERVED_HD_AUDIO 019221922-#define ACPI_NHLT_RESERVED_DSP 119231923-#define ACPI_NHLT_PDM 219241924-#define ACPI_NHLT_SSP 319251925-#define ACPI_NHLT_RESERVED_SLIMBUS 419261926-#define ACPI_NHLT_RESERVED_SOUNDWIRE 519271927-#define ACPI_NHLT_TYPE_RESERVED 6 /* 6 and above are reserved */19281928-19291929-/* All other values above are reserved */19241924+/*19251925+ * Values for link_type field above19261926+ *19271927+ * Only types PDM and SSP are used19281928+ */19291929+#define ACPI_NHLT_LINKTYPE_HDA 019301930+#define ACPI_NHLT_LINKTYPE_DSP 119311931+#define ACPI_NHLT_LINKTYPE_PDM 219321932+#define ACPI_NHLT_LINKTYPE_SSP 319331933+#define ACPI_NHLT_LINKTYPE_SLIMBUS 419341934+#define ACPI_NHLT_LINKTYPE_SDW 519351935+#define ACPI_NHLT_LINKTYPE_UAOL 61930193619311937/* Values for device_id field above */1932193819331933-#define ACPI_NHLT_PDM_DMIC 0xAE2019341934-#define ACPI_NHLT_BT_SIDEBAND 0xAE3019351935-#define ACPI_NHLT_I2S_TDM_CODECS 0xAE2319391939+#define ACPI_NHLT_DEVICEID_DMIC 0xAE2019401940+#define ACPI_NHLT_DEVICEID_BT 0xAE3019411941+#define ACPI_NHLT_DEVICEID_I2S 0xAE341936194219371943/* Values for device_type field above */1938194419391939-/* SSP Link */19401940-19411941-#define ACPI_NHLT_LINK_BT_SIDEBAND 019421942-#define ACPI_NHLT_LINK_FM 119431943-#define ACPI_NHLT_LINK_MODEM 219441944-/* 3 is reserved */19451945-#define ACPI_NHLT_LINK_SSP_ANALOG_CODEC 419461946-19471947-/* PDM Link */19481948-19491949-#define ACPI_NHLT_PDM_ON_CAVS_1P8 019501950-#define ACPI_NHLT_PDM_ON_CAVS_1P5 119451945+/*19461946+ * Device types unique to endpoint of link_type=PDM19471947+ *19481948+ * Type PDM used for all SKL+ platforms19491949+ */19501950+#define ACPI_NHLT_DEVICETYPE_PDM 019511951+#define ACPI_NHLT_DEVICETYPE_PDM_SKL 119521952+/* Device types unique to endpoint of link_type=SSP */19531953+#define ACPI_NHLT_DEVICETYPE_BT 019541954+#define ACPI_NHLT_DEVICETYPE_FM 119551955+#define ACPI_NHLT_DEVICETYPE_MODEM 219561956+#define ACPI_NHLT_DEVICETYPE_CODEC 41951195719521958/* Values for Direction field above */1953195919541954-#define ACPI_NHLT_DIR_RENDER 019551955-#define ACPI_NHLT_DIR_CAPTURE 119561956-#define ACPI_NHLT_DIR_RENDER_LOOPBACK 219571957-#define ACPI_NHLT_DIR_RENDER_FEEDBACK 319581958-#define ACPI_NHLT_DIR_RESERVED 4 /* 4 and above are reserved */19601960+#define ACPI_NHLT_DIR_RENDER 019611961+#define ACPI_NHLT_DIR_CAPTURE 11959196219601960-struct acpi_nhlt_device_specific_config {19631963+struct acpi_nhlt_config {19611964 u32 capabilities_size;19651965+ u8 capabilities[];19661966+};19671967+19681968+struct acpi_nhlt_gendevice_config {19621969 u8 virtual_slot;19631970 u8 config_type;19641971};1965197219661966-struct acpi_nhlt_device_specific_config_a {19671967- u32 capabilities_size;19731973+/* Values for config_type field above */19741974+19751975+#define ACPI_NHLT_CONFIGTYPE_GENERIC 019761976+#define ACPI_NHLT_CONFIGTYPE_MICARRAY 119771977+19781978+struct acpi_nhlt_micdevice_config {19681979 u8 virtual_slot;19691980 u8 config_type;19701981 u8 array_type;19711982};1972198319731973-/* Values for Config Type above */19841984+/* Values for array_type field above */1974198519751975-#define ACPI_NHLT_CONFIG_TYPE_GENERIC 0x0019761976-#define ACPI_NHLT_CONFIG_TYPE_MIC_ARRAY 0x0119771977-#define ACPI_NHLT_CONFIG_TYPE_RENDER_FEEDBACK 0x0319781978-#define ACPI_NHLT_CONFIG_TYPE_RESERVED 0x04 /* 4 and above are reserved */19861986+#define ACPI_NHLT_ARRAYTYPE_LINEAR2_SMALL 0xA19871987+#define ACPI_NHLT_ARRAYTYPE_LINEAR2_BIG 0xB19881988+#define ACPI_NHLT_ARRAYTYPE_LINEAR4_GEO1 0xC19891989+#define ACPI_NHLT_ARRAYTYPE_PLANAR4_LSHAPED 0xD19901990+#define ACPI_NHLT_ARRAYTYPE_LINEAR4_GEO2 0xE19911991+#define ACPI_NHLT_ARRAYTYPE_VENDOR 0xF1979199219801980-struct acpi_nhlt_device_specific_config_b {19811981- u32 capabilities_size;19931993+struct acpi_nhlt_vendor_mic_config {19941994+ u8 type;19951995+ u8 panel;19961996+ u16 speaker_position_distance; /* mm */19971997+ u16 horizontal_offset; /* mm */19981998+ u16 vertical_offset; /* mm */19991999+ u8 frequency_low_band; /* 5*Hz */20002000+ u8 frequency_high_band; /* 500*Hz */20012001+ u16 direction_angle; /* -180 - +180 */20022002+ u16 elevation_angle; /* -180 - +180 */20032003+ u16 work_vertical_angle_begin; /* -180 - +180 with 2 deg step */20042004+ u16 work_vertical_angle_end; /* -180 - +180 with 2 deg step */20052005+ u16 work_horizontal_angle_begin; /* -180 - +180 with 2 deg step */20062006+ u16 work_horizontal_angle_end; /* -180 - +180 with 2 deg step */19822007};1983200819841984-struct acpi_nhlt_device_specific_config_c {19851985- u32 capabilities_size;20092009+/* Values for Type field above */20102010+20112011+#define ACPI_NHLT_MICTYPE_OMNIDIRECTIONAL 020122012+#define ACPI_NHLT_MICTYPE_SUBCARDIOID 120132013+#define ACPI_NHLT_MICTYPE_CARDIOID 220142014+#define ACPI_NHLT_MICTYPE_SUPERCARDIOID 320152015+#define ACPI_NHLT_MICTYPE_HYPERCARDIOID 420162016+#define ACPI_NHLT_MICTYPE_8SHAPED 520172017+#define ACPI_NHLT_MICTYPE_RESERVED 620182018+#define ACPI_NHLT_MICTYPE_VENDORDEFINED 720192019+20202020+/* Values for Panel field above */20212021+20222022+#define ACPI_NHLT_MICLOCATION_TOP 020232023+#define ACPI_NHLT_MICLOCATION_BOTTOM 120242024+#define ACPI_NHLT_MICLOCATION_LEFT 220252025+#define ACPI_NHLT_MICLOCATION_RIGHT 320262026+#define ACPI_NHLT_MICLOCATION_FRONT 420272027+#define ACPI_NHLT_MICLOCATION_REAR 520282028+20292029+struct acpi_nhlt_vendor_micdevice_config {19862030 u8 virtual_slot;20312031+ u8 config_type;20322032+ u8 array_type;20332033+ u8 mics_count;20342034+ struct acpi_nhlt_vendor_mic_config mics[];19872035};1988203619891989-struct acpi_nhlt_render_device_specific_config {19901990- u32 capabilities_size;20372037+union acpi_nhlt_device_config {19912038 u8 virtual_slot;20392039+ struct acpi_nhlt_gendevice_config gen;20402040+ struct acpi_nhlt_micdevice_config mic;20412041+ struct acpi_nhlt_vendor_micdevice_config vendor_mic;19922042};1993204319941994-struct acpi_nhlt_wave_extensible {20442044+/* Inherited from Microsoft's WAVEFORMATEXTENSIBLE. */20452045+struct acpi_nhlt_wave_formatext {19952046 u16 format_tag;19962047 u16 channel_count;19972048 u32 samples_per_sec;···20522001 u16 extra_format_size;20532002 u16 valid_bits_per_sample;20542003 u32 channel_mask;20552055- u8 sub_format_guid[16];20042004+ u8 subformat[16];20562005};2057200620582058-/* Values for channel_mask above */20592059-20602060-#define ACPI_NHLT_SPKR_FRONT_LEFT 0x120612061-#define ACPI_NHLT_SPKR_FRONT_RIGHT 0x220622062-#define ACPI_NHLT_SPKR_FRONT_CENTER 0x420632063-#define ACPI_NHLT_SPKR_LOW_FREQ 0x820642064-#define ACPI_NHLT_SPKR_BACK_LEFT 0x1020652065-#define ACPI_NHLT_SPKR_BACK_RIGHT 0x2020662066-#define ACPI_NHLT_SPKR_FRONT_LEFT_OF_CENTER 0x4020672067-#define ACPI_NHLT_SPKR_FRONT_RIGHT_OF_CENTER 0x8020682068-#define ACPI_NHLT_SPKR_BACK_CENTER 0x10020692069-#define ACPI_NHLT_SPKR_SIDE_LEFT 0x20020702070-#define ACPI_NHLT_SPKR_SIDE_RIGHT 0x40020712071-#define ACPI_NHLT_SPKR_TOP_CENTER 0x80020722072-#define ACPI_NHLT_SPKR_TOP_FRONT_LEFT 0x100020732073-#define ACPI_NHLT_SPKR_TOP_FRONT_CENTER 0x200020742074-#define ACPI_NHLT_SPKR_TOP_FRONT_RIGHT 0x400020752075-#define ACPI_NHLT_SPKR_TOP_BACK_LEFT 0x800020762076-#define ACPI_NHLT_SPKR_TOP_BACK_CENTER 0x1000020772077-#define ACPI_NHLT_SPKR_TOP_BACK_RIGHT 0x2000020782078-20792007struct acpi_nhlt_format_config {20802080- struct acpi_nhlt_wave_extensible format;20812081- u32 capability_size;20822082- u8 capabilities[];20082008+ struct acpi_nhlt_wave_formatext format;20092009+ struct acpi_nhlt_config config;20832010};2084201120852012struct acpi_nhlt_formats_config {20862013 u8 formats_count;20872087-};20882088-20892089-struct acpi_nhlt_device_specific_hdr {20902090- u8 virtual_slot;20912091- u8 config_type;20922092-};20932093-20942094-/* Types for config_type above */20952095-20962096-#define ACPI_NHLT_GENERIC 020972097-#define ACPI_NHLT_MIC 120982098-#define ACPI_NHLT_RENDER 320992099-21002100-struct acpi_nhlt_mic_device_specific_config {21012101- struct acpi_nhlt_device_specific_hdr device_config;21022102- u8 array_type_ext;21032103-};21042104-21052105-/* Values for array_type_ext above */21062106-21072107-#define ACPI_NHLT_ARRAY_TYPE_RESERVED 0x09 /* 9 and below are reserved */21082108-#define ACPI_NHLT_SMALL_LINEAR_2ELEMENT 0x0A21092109-#define ACPI_NHLT_BIG_LINEAR_2ELEMENT 0x0B21102110-#define ACPI_NHLT_FIRST_GEOMETRY_LINEAR_4ELEMENT 0x0C21112111-#define ACPI_NHLT_PLANAR_LSHAPED_4ELEMENT 0x0D21122112-#define ACPI_NHLT_SECOND_GEOMETRY_LINEAR_4ELEMENT 0x0E21132113-#define ACPI_NHLT_VENDOR_DEFINED 0x0F21142114-#define ACPI_NHLT_ARRAY_TYPE_MASK 0x0F21152115-#define ACPI_NHLT_ARRAY_TYPE_EXT_MASK 0x1021162116-21172117-#define ACPI_NHLT_NO_EXTENSION 0x021182118-#define ACPI_NHLT_MIC_SNR_SENSITIVITY_EXT (1<<4)21192119-21202120-struct acpi_nhlt_vendor_mic_count {21212121- u8 microphone_count;21222122-};21232123-21242124-struct acpi_nhlt_vendor_mic_config {21252125- u8 type;21262126- u8 panel;21272127- u16 speaker_position_distance; /* mm */21282128- u16 horizontal_offset; /* mm */21292129- u16 vertical_offset; /* mm */21302130- u8 frequency_low_band; /* 5*Hz */21312131- u8 frequency_high_band; /* 500*Hz */21322132- u16 direction_angle; /* -180 - + 180 */21332133- u16 elevation_angle; /* -180 - + 180 */21342134- u16 work_vertical_angle_begin; /* -180 - + 180 with 2 deg step */21352135- u16 work_vertical_angle_end; /* -180 - + 180 with 2 deg step */21362136- u16 work_horizontal_angle_begin; /* -180 - + 180 with 2 deg step */21372137- u16 work_horizontal_angle_end; /* -180 - + 180 with 2 deg step */21382138-};21392139-21402140-/* Values for Type field above */21412141-21422142-#define ACPI_NHLT_MIC_OMNIDIRECTIONAL 021432143-#define ACPI_NHLT_MIC_SUBCARDIOID 121442144-#define ACPI_NHLT_MIC_CARDIOID 221452145-#define ACPI_NHLT_MIC_SUPER_CARDIOID 321462146-#define ACPI_NHLT_MIC_HYPER_CARDIOID 421472147-#define ACPI_NHLT_MIC_8_SHAPED 521482148-#define ACPI_NHLT_MIC_RESERVED6 6 /* 6 is reserved */21492149-#define ACPI_NHLT_MIC_VENDOR_DEFINED 721502150-#define ACPI_NHLT_MIC_RESERVED 8 /* 8 and above are reserved */21512151-21522152-/* Values for Panel field above */21532153-21542154-#define ACPI_NHLT_MIC_POSITION_TOP 021552155-#define ACPI_NHLT_MIC_POSITION_BOTTOM 121562156-#define ACPI_NHLT_MIC_POSITION_LEFT 221572157-#define ACPI_NHLT_MIC_POSITION_RIGHT 321582158-#define ACPI_NHLT_MIC_POSITION_FRONT 421592159-#define ACPI_NHLT_MIC_POSITION_BACK 521602160-#define ACPI_NHLT_MIC_POSITION_RESERVED 6 /* 6 and above are reserved */21612161-21622162-struct acpi_nhlt_vendor_mic_device_specific_config {21632163- struct acpi_nhlt_mic_device_specific_config mic_array_device_config;21642164- u8 number_of_microphones;21652165- struct acpi_nhlt_vendor_mic_config mic_config[]; /* Indexed by number_of_microphones */21662166-};21672167-21682168-/* Microphone SNR and Sensitivity extension */21692169-21702170-struct acpi_nhlt_mic_snr_sensitivity_extension {21712171- u32 SNR;21722172- u32 sensitivity;21732173-};21742174-21752175-/* Render device with feedback */21762176-21772177-struct acpi_nhlt_render_feedback_device_specific_config {21782178- u8 feedback_virtual_slot; /* Render slot in case of capture */21792179- u16 feedback_channels; /* Informative only */21802180- u16 feedback_valid_bits_per_sample;21812181-};21822182-21832183-/* Non documented structures */21842184-21852185-struct acpi_nhlt_device_info_count {21862186- u8 structure_count;20142014+ struct acpi_nhlt_format_config formats[];21872015};2188201621892017struct acpi_nhlt_device_info {21902190- u8 device_id[16];21912191- u8 device_instance_id;21922192- u8 device_port_id;20182018+ u8 id[16];20192019+ u8 instance_id;20202020+ u8 port_id;20212021+};20222022+20232023+struct acpi_nhlt_devices_info {20242024+ u8 devices_count;20252025+ struct acpi_nhlt_device_info devices[];21932026};2194202721952028/*******************************************************************************
+181
include/acpi/nhlt.h
···11+/* SPDX-License-Identifier: GPL-2.0-only */22+/*33+ * Copyright(c) 2023-2024 Intel Corporation44+ *55+ * Authors: Cezary Rojewski <cezary.rojewski@intel.com>66+ * Amadeusz Slawinski <amadeuszx.slawinski@linux.intel.com>77+ */88+99+#ifndef __ACPI_NHLT_H__1010+#define __ACPI_NHLT_H__1111+1212+#include <linux/acpi.h>1313+#include <linux/kconfig.h>1414+#include <linux/overflow.h>1515+#include <linux/types.h>1616+1717+#define __acpi_nhlt_endpoint_config(ep) ((void *)((ep) + 1))1818+#define __acpi_nhlt_config_caps(cfg) ((void *)((cfg) + 1))1919+2020+/**2121+ * acpi_nhlt_endpoint_fmtscfg - Get the formats configuration space.2222+ * @ep: the endpoint to retrieve the space for.2323+ *2424+ * Return: A pointer to the formats configuration space.2525+ */2626+static inline struct acpi_nhlt_formats_config *2727+acpi_nhlt_endpoint_fmtscfg(const struct acpi_nhlt_endpoint *ep)2828+{2929+ struct acpi_nhlt_config *cfg = __acpi_nhlt_endpoint_config(ep);3030+3131+ return (struct acpi_nhlt_formats_config *)((u8 *)(cfg + 1) + cfg->capabilities_size);3232+}3333+3434+#define __acpi_nhlt_first_endpoint(tb) \3535+ ((void *)(tb + 1))3636+3737+#define __acpi_nhlt_next_endpoint(ep) \3838+ ((void *)((u8 *)(ep) + (ep)->length))3939+4040+#define __acpi_nhlt_get_endpoint(tb, ep, i) \4141+ ((i) ? __acpi_nhlt_next_endpoint(ep) : __acpi_nhlt_first_endpoint(tb))4242+4343+#define __acpi_nhlt_first_fmtcfg(fmts) \4444+ ((void *)(fmts + 1))4545+4646+#define __acpi_nhlt_next_fmtcfg(fmt) \4747+ ((void *)((u8 *)((fmt) + 1) + (fmt)->config.capabilities_size))4848+4949+#define __acpi_nhlt_get_fmtcfg(fmts, fmt, i) \5050+ ((i) ? __acpi_nhlt_next_fmtcfg(fmt) : __acpi_nhlt_first_fmtcfg(fmts))5151+5252+/*5353+ * The for_each_nhlt_*() macros rely on an iterator to deal with the5454+ * variable length of each endpoint structure and the possible presence5555+ * of an OED-Config used by Windows only.5656+ */5757+5858+/**5959+ * for_each_nhlt_endpoint - Iterate over endpoints in a NHLT table.6060+ * @tb: the pointer to a NHLT table.6161+ * @ep: the pointer to endpoint to use as loop cursor.6262+ */6363+#define for_each_nhlt_endpoint(tb, ep) \6464+ for (unsigned int __i = 0; \6565+ __i < (tb)->endpoints_count && \6666+ (ep = __acpi_nhlt_get_endpoint(tb, ep, __i)); \6767+ __i++)6868+6969+/**7070+ * for_each_nhlt_fmtcfg - Iterate over format configurations.7171+ * @fmts: the pointer to formats configuration space.7272+ * @fmt: the pointer to format to use as loop cursor.7373+ */7474+#define for_each_nhlt_fmtcfg(fmts, fmt) \7575+ for (unsigned int __i = 0; \7676+ __i < (fmts)->formats_count && \7777+ (fmt = __acpi_nhlt_get_fmtcfg(fmts, fmt, __i)); \7878+ __i++)7979+8080+/**8181+ * for_each_nhlt_endpoint_fmtcfg - Iterate over format configurations in an endpoint.8282+ * @ep: the pointer to an endpoint.8383+ * @fmt: the pointer to format to use as loop cursor.8484+ */8585+#define for_each_nhlt_endpoint_fmtcfg(ep, fmt) \8686+ for_each_nhlt_fmtcfg(acpi_nhlt_endpoint_fmtscfg(ep), fmt)8787+8888+#if IS_ENABLED(CONFIG_ACPI_NHLT)8989+9090+/*9191+ * System-wide pointer to the first NHLT table.9292+ *9393+ * A sound driver may utilize acpi_nhlt_get/put_gbl_table() on its9494+ * initialization and removal respectively to avoid excessive mapping9595+ * and unmapping of the memory occupied by the table between streaming9696+ * operations.9797+ */9898+9999+acpi_status acpi_nhlt_get_gbl_table(void);100100+void acpi_nhlt_put_gbl_table(void);101101+102102+bool acpi_nhlt_endpoint_match(const struct acpi_nhlt_endpoint *ep,103103+ int link_type, int dev_type, int dir, int bus_id);104104+struct acpi_nhlt_endpoint *105105+acpi_nhlt_tb_find_endpoint(const struct acpi_table_nhlt *tb,106106+ int link_type, int dev_type, int dir, int bus_id);107107+struct acpi_nhlt_endpoint *108108+acpi_nhlt_find_endpoint(int link_type, int dev_type, int dir, int bus_id);109109+struct acpi_nhlt_format_config *110110+acpi_nhlt_endpoint_find_fmtcfg(const struct acpi_nhlt_endpoint *ep,111111+ u16 ch, u32 rate, u16 vbps, u16 bps);112112+struct acpi_nhlt_format_config *113113+acpi_nhlt_tb_find_fmtcfg(const struct acpi_table_nhlt *tb,114114+ int link_type, int dev_type, int dir, int bus_id,115115+ u16 ch, u32 rate, u16 vpbs, u16 bps);116116+struct acpi_nhlt_format_config *117117+acpi_nhlt_find_fmtcfg(int link_type, int dev_type, int dir, int bus_id,118118+ u16 ch, u32 rate, u16 vpbs, u16 bps);119119+int acpi_nhlt_endpoint_mic_count(const struct acpi_nhlt_endpoint *ep);120120+121121+#else /* !CONFIG_ACPI_NHLT */122122+123123+static inline acpi_status acpi_nhlt_get_gbl_table(void)124124+{125125+ return AE_NOT_FOUND;126126+}127127+128128+static inline void acpi_nhlt_put_gbl_table(void)129129+{130130+}131131+132132+static inline bool133133+acpi_nhlt_endpoint_match(const struct acpi_nhlt_endpoint *ep,134134+ int link_type, int dev_type, int dir, int bus_id)135135+{136136+ return false;137137+}138138+139139+static inline struct acpi_nhlt_endpoint *140140+acpi_nhlt_tb_find_endpoint(const struct acpi_table_nhlt *tb,141141+ int link_type, int dev_type, int dir, int bus_id)142142+{143143+ return NULL;144144+}145145+146146+static inline struct acpi_nhlt_format_config *147147+acpi_nhlt_endpoint_find_fmtcfg(const struct acpi_nhlt_endpoint *ep,148148+ u16 ch, u32 rate, u16 vbps, u16 bps)149149+{150150+ return NULL;151151+}152152+153153+static inline struct acpi_nhlt_format_config *154154+acpi_nhlt_tb_find_fmtcfg(const struct acpi_table_nhlt *tb,155155+ int link_type, int dev_type, int dir, int bus_id,156156+ u16 ch, u32 rate, u16 vpbs, u16 bps)157157+{158158+ return NULL;159159+}160160+161161+static inline int acpi_nhlt_endpoint_mic_count(const struct acpi_nhlt_endpoint *ep)162162+{163163+ return 0;164164+}165165+166166+static inline struct acpi_nhlt_endpoint *167167+acpi_nhlt_find_endpoint(int link_type, int dev_type, int dir, int bus_id)168168+{169169+ return NULL;170170+}171171+172172+static inline struct acpi_nhlt_format_config *173173+acpi_nhlt_find_fmtcfg(int link_type, int dev_type, int dir, int bus_id,174174+ u16 ch, u32 rate, u16 vpbs, u16 bps)175175+{176176+ return NULL;177177+}178178+179179+#endif /* CONFIG_ACPI_NHLT */180180+181181+#endif /* __ACPI_NHLT_H__ */
+1
sound/hda/Kconfig
···42424343config SND_INTEL_DSP_CONFIG4444 tristate4545+ select ACPI_NHLT if ACPI4546 select SND_INTEL_NHLT if ACPI4647 select SND_INTEL_SOUNDWIRE_ACPI if ACPI4748 # this config should be selected only for Intel DSP platforms.
+9-7
sound/hda/intel-dsp-config.c
···1313#include <sound/intel-nhlt.h>1414#include <sound/soc-acpi.h>15151616+#include <acpi/nhlt.h>1717+1618static int dsp_driver;17191820module_param(dsp_driver, int, 0444);···595593596594static int snd_intel_dsp_check_dmic(struct pci_dev *pci)597595{598598- struct nhlt_acpi_table *nhlt;599596 int ret = 0;600597601601- nhlt = intel_nhlt_init(&pci->dev);602602- if (nhlt) {603603- if (intel_nhlt_has_endpoint_type(nhlt, NHLT_LINK_DMIC))604604- ret = 1;605605- intel_nhlt_free(nhlt);606606- }598598+ acpi_nhlt_get_gbl_table();599599+600600+ if (acpi_nhlt_find_endpoint(ACPI_NHLT_LINKTYPE_PDM, -1, -1, -1))601601+ ret = 1;602602+603603+ acpi_nhlt_put_gbl_table();604604+607605 return ret;608606}609607