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 */ 26static inline struct acpi_nhlt_formats_config * 27acpi_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 99acpi_status acpi_nhlt_get_gbl_table(void); 100void acpi_nhlt_put_gbl_table(void); 101 102bool acpi_nhlt_endpoint_match(const struct acpi_nhlt_endpoint *ep, 103 int link_type, int dev_type, int dir, int bus_id); 104struct acpi_nhlt_endpoint * 105acpi_nhlt_tb_find_endpoint(const struct acpi_table_nhlt *tb, 106 int link_type, int dev_type, int dir, int bus_id); 107struct acpi_nhlt_endpoint * 108acpi_nhlt_find_endpoint(int link_type, int dev_type, int dir, int bus_id); 109struct acpi_nhlt_format_config * 110acpi_nhlt_endpoint_find_fmtcfg(const struct acpi_nhlt_endpoint *ep, 111 u16 ch, u32 rate, u16 vbps, u16 bps); 112struct acpi_nhlt_format_config * 113acpi_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); 116struct acpi_nhlt_format_config * 117acpi_nhlt_find_fmtcfg(int link_type, int dev_type, int dir, int bus_id, 118 u16 ch, u32 rate, u16 vpbs, u16 bps); 119int acpi_nhlt_endpoint_mic_count(const struct acpi_nhlt_endpoint *ep); 120 121#else /* !CONFIG_ACPI_NHLT */ 122 123static inline acpi_status acpi_nhlt_get_gbl_table(void) 124{ 125 return AE_NOT_FOUND; 126} 127 128static inline void acpi_nhlt_put_gbl_table(void) 129{ 130} 131 132static inline bool 133acpi_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 139static inline struct acpi_nhlt_endpoint * 140acpi_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 146static inline struct acpi_nhlt_format_config * 147acpi_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 153static inline struct acpi_nhlt_format_config * 154acpi_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 161static inline int acpi_nhlt_endpoint_mic_count(const struct acpi_nhlt_endpoint *ep) 162{ 163 return 0; 164} 165 166static inline struct acpi_nhlt_endpoint * 167acpi_nhlt_find_endpoint(int link_type, int dev_type, int dir, int bus_id) 168{ 169 return NULL; 170} 171 172static inline struct acpi_nhlt_format_config * 173acpi_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