xref: /linux/include/acpi/nhlt.h (revision f4cdf7ca9a1fdcca413157df19753f388a5a224e)
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