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