1 /* SPDX-License-Identifier: GPL-2.0-only */ 2 /* 3 * Copyright(c) 2023-2024 Intel Corporation 4 * 5 * Authors: Cezary Rojewski <cezary.rojewski@intel.com> 6 * Amadeusz Slawinski <amadeuszx.slawinski@linux.intel.com> 7 */ 8 9 #ifndef __ACPI_NHLT_H__ 10 #define __ACPI_NHLT_H__ 11 12 #include <linux/acpi.h> 13 #include <linux/kconfig.h> 14 #include <linux/overflow.h> 15 #include <linux/types.h> 16 17 #define __acpi_nhlt_endpoint_config(ep) ((void *)((ep) + 1)) 18 #define __acpi_nhlt_config_caps(cfg) ((void *)((cfg) + 1)) 19 20 /** 21 * acpi_nhlt_endpoint_fmtscfg - Get the formats configuration space. 22 * @ep: the endpoint to retrieve the space for. 23 * 24 * Return: A pointer to the formats configuration space. 25 */ 26 static inline struct acpi_nhlt_formats_config * 27 acpi_nhlt_endpoint_fmtscfg(const struct acpi_nhlt_endpoint *ep) 28 { 29 struct acpi_nhlt_config *cfg = __acpi_nhlt_endpoint_config(ep); 30 31 return (struct acpi_nhlt_formats_config *)((u8 *)(cfg + 1) + cfg->capabilities_size); 32 } 33 34 #define __acpi_nhlt_first_endpoint(tb) \ 35 ((void *)(tb + 1)) 36 37 #define __acpi_nhlt_next_endpoint(ep) \ 38 ((void *)((u8 *)(ep) + (ep)->length)) 39 40 #define __acpi_nhlt_get_endpoint(tb, ep, i) \ 41 ((i) ? __acpi_nhlt_next_endpoint(ep) : __acpi_nhlt_first_endpoint(tb)) 42 43 #define __acpi_nhlt_first_fmtcfg(fmts) \ 44 ((void *)(fmts + 1)) 45 46 #define __acpi_nhlt_next_fmtcfg(fmt) \ 47 ((void *)((u8 *)((fmt) + 1) + (fmt)->config.capabilities_size)) 48 49 #define __acpi_nhlt_get_fmtcfg(fmts, fmt, i) \ 50 ((i) ? __acpi_nhlt_next_fmtcfg(fmt) : __acpi_nhlt_first_fmtcfg(fmts)) 51 52 /* 53 * The for_each_nhlt_*() macros rely on an iterator to deal with the 54 * variable length of each endpoint structure and the possible presence 55 * of an OED-Config used by Windows only. 56 */ 57 58 /** 59 * for_each_nhlt_endpoint - Iterate over endpoints in a NHLT table. 60 * @tb: the pointer to a NHLT table. 61 * @ep: the pointer to endpoint to use as loop cursor. 62 */ 63 #define for_each_nhlt_endpoint(tb, ep) \ 64 for (unsigned int __i = 0; \ 65 __i < (tb)->endpoints_count && \ 66 (ep = __acpi_nhlt_get_endpoint(tb, ep, __i)); \ 67 __i++) 68 69 /** 70 * for_each_nhlt_fmtcfg - Iterate over format configurations. 71 * @fmts: the pointer to formats configuration space. 72 * @fmt: the pointer to format to use as loop cursor. 73 */ 74 #define for_each_nhlt_fmtcfg(fmts, fmt) \ 75 for (unsigned int __i = 0; \ 76 __i < (fmts)->formats_count && \ 77 (fmt = __acpi_nhlt_get_fmtcfg(fmts, fmt, __i)); \ 78 __i++) 79 80 /** 81 * for_each_nhlt_endpoint_fmtcfg - Iterate over format configurations in an endpoint. 82 * @ep: the pointer to an endpoint. 83 * @fmt: the pointer to format to use as loop cursor. 84 */ 85 #define for_each_nhlt_endpoint_fmtcfg(ep, fmt) \ 86 for_each_nhlt_fmtcfg(acpi_nhlt_endpoint_fmtscfg(ep), fmt) 87 88 #if IS_ENABLED(CONFIG_ACPI_NHLT) 89 90 /* 91 * System-wide pointer to the first NHLT table. 92 * 93 * A sound driver may utilize acpi_nhlt_get/put_gbl_table() on its 94 * initialization and removal respectively to avoid excessive mapping 95 * and unmapping of the memory occupied by the table between streaming 96 * operations. 97 */ 98 99 acpi_status acpi_nhlt_get_gbl_table(void); 100 void acpi_nhlt_put_gbl_table(void); 101 102 bool acpi_nhlt_endpoint_match(const struct acpi_nhlt_endpoint *ep, 103 int link_type, int dev_type, int dir, int bus_id); 104 struct acpi_nhlt_endpoint * 105 acpi_nhlt_tb_find_endpoint(const struct acpi_table_nhlt *tb, 106 int link_type, int dev_type, int dir, int bus_id); 107 struct acpi_nhlt_endpoint * 108 acpi_nhlt_find_endpoint(int link_type, int dev_type, int dir, int bus_id); 109 struct acpi_nhlt_format_config * 110 acpi_nhlt_endpoint_find_fmtcfg(const struct acpi_nhlt_endpoint *ep, 111 u16 ch, u32 rate, u16 vbps, u16 bps); 112 struct acpi_nhlt_format_config * 113 acpi_nhlt_tb_find_fmtcfg(const struct acpi_table_nhlt *tb, 114 int link_type, int dev_type, int dir, int bus_id, 115 u16 ch, u32 rate, u16 vpbs, u16 bps); 116 struct acpi_nhlt_format_config * 117 acpi_nhlt_find_fmtcfg(int link_type, int dev_type, int dir, int bus_id, 118 u16 ch, u32 rate, u16 vpbs, u16 bps); 119 int acpi_nhlt_endpoint_mic_count(const struct acpi_nhlt_endpoint *ep); 120 121 #else /* !CONFIG_ACPI_NHLT */ 122 123 static inline acpi_status acpi_nhlt_get_gbl_table(void) 124 { 125 return AE_NOT_FOUND; 126 } 127 128 static inline void acpi_nhlt_put_gbl_table(void) 129 { 130 } 131 132 static inline bool 133 acpi_nhlt_endpoint_match(const struct acpi_nhlt_endpoint *ep, 134 int link_type, int dev_type, int dir, int bus_id) 135 { 136 return false; 137 } 138 139 static inline struct acpi_nhlt_endpoint * 140 acpi_nhlt_tb_find_endpoint(const struct acpi_table_nhlt *tb, 141 int link_type, int dev_type, int dir, int bus_id) 142 { 143 return NULL; 144 } 145 146 static inline struct acpi_nhlt_format_config * 147 acpi_nhlt_endpoint_find_fmtcfg(const struct acpi_nhlt_endpoint *ep, 148 u16 ch, u32 rate, u16 vbps, u16 bps) 149 { 150 return NULL; 151 } 152 153 static inline struct acpi_nhlt_format_config * 154 acpi_nhlt_tb_find_fmtcfg(const struct acpi_table_nhlt *tb, 155 int link_type, int dev_type, int dir, int bus_id, 156 u16 ch, u32 rate, u16 vpbs, u16 bps) 157 { 158 return NULL; 159 } 160 161 static inline int acpi_nhlt_endpoint_mic_count(const struct acpi_nhlt_endpoint *ep) 162 { 163 return 0; 164 } 165 166 static inline struct acpi_nhlt_endpoint * 167 acpi_nhlt_find_endpoint(int link_type, int dev_type, int dir, int bus_id) 168 { 169 return NULL; 170 } 171 172 static inline struct acpi_nhlt_format_config * 173 acpi_nhlt_find_fmtcfg(int link_type, int dev_type, int dir, int bus_id, 174 u16 ch, u32 rate, u16 vpbs, u16 bps) 175 { 176 return NULL; 177 } 178 179 #endif /* CONFIG_ACPI_NHLT */ 180 181 #endif /* __ACPI_NHLT_H__ */ 182