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 *
acpi_nhlt_endpoint_fmtscfg(const struct acpi_nhlt_endpoint * ep)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 
acpi_nhlt_get_gbl_table(void)123 static inline acpi_status acpi_nhlt_get_gbl_table(void)
124 {
125 	return AE_NOT_FOUND;
126 }
127 
acpi_nhlt_put_gbl_table(void)128 static inline void acpi_nhlt_put_gbl_table(void)
129 {
130 }
131 
132 static inline bool
acpi_nhlt_endpoint_match(const struct acpi_nhlt_endpoint * ep,int link_type,int dev_type,int dir,int bus_id)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 *
acpi_nhlt_tb_find_endpoint(const struct acpi_table_nhlt * tb,int link_type,int dev_type,int dir,int bus_id)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 *
acpi_nhlt_endpoint_find_fmtcfg(const struct acpi_nhlt_endpoint * ep,u16 ch,u32 rate,u16 vbps,u16 bps)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 *
acpi_nhlt_tb_find_fmtcfg(const struct acpi_table_nhlt * tb,int link_type,int dev_type,int dir,int bus_id,u16 ch,u32 rate,u16 vpbs,u16 bps)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 
acpi_nhlt_endpoint_mic_count(const struct acpi_nhlt_endpoint * ep)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 *
acpi_nhlt_find_endpoint(int link_type,int dev_type,int dir,int bus_id)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 *
acpi_nhlt_find_fmtcfg(int link_type,int dev_type,int dir,int bus_id,u16 ch,u32 rate,u16 vpbs,u16 bps)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