1 // SPDX-License-Identifier: GPL-2.0-only
2 // Copyright (c) 2015-2019 Intel Corporation
4 #include <linux/acpi.h>
5 #include <sound/intel-nhlt.h>
7 struct nhlt_acpi_table
*intel_nhlt_init(struct device
*dev
)
9 struct nhlt_acpi_table
*nhlt
;
12 status
= acpi_get_table(ACPI_SIG_NHLT
, 0,
13 (struct acpi_table_header
**)&nhlt
);
14 if (ACPI_FAILURE(status
)) {
15 dev_warn(dev
, "NHLT table not found\n");
21 EXPORT_SYMBOL_GPL(intel_nhlt_init
);
23 void intel_nhlt_free(struct nhlt_acpi_table
*nhlt
)
25 acpi_put_table((struct acpi_table_header
*)nhlt
);
27 EXPORT_SYMBOL_GPL(intel_nhlt_free
);
29 int intel_nhlt_get_dmic_geo(struct device
*dev
, struct nhlt_acpi_table
*nhlt
)
31 struct nhlt_endpoint
*epnt
;
32 struct nhlt_dmic_array_config
*cfg
;
33 struct nhlt_vendor_dmic_array_config
*cfg_vendor
;
34 struct nhlt_fmt
*fmt_configs
;
35 unsigned int dmic_geo
= 0;
42 if (nhlt
->header
.length
<= sizeof(struct acpi_table_header
)) {
43 dev_warn(dev
, "Invalid DMIC description table\n");
47 for (j
= 0, epnt
= nhlt
->desc
; j
< nhlt
->endpoint_count
; j
++,
48 epnt
= (struct nhlt_endpoint
*)((u8
*)epnt
+ epnt
->length
)) {
50 if (epnt
->linktype
!= NHLT_LINK_DMIC
)
53 cfg
= (struct nhlt_dmic_array_config
*)(epnt
->config
.caps
);
54 fmt_configs
= (struct nhlt_fmt
*)(epnt
->config
.caps
+ epnt
->config
.size
);
56 /* find max number of channels based on format_configuration */
57 if (fmt_configs
->fmt_count
) {
58 struct nhlt_fmt_cfg
*fmt_cfg
= fmt_configs
->fmt_config
;
60 dev_dbg(dev
, "found %d format definitions\n",
61 fmt_configs
->fmt_count
);
63 for (i
= 0; i
< fmt_configs
->fmt_count
; i
++) {
64 struct wav_fmt_ext
*fmt_ext
;
66 fmt_ext
= &fmt_cfg
->fmt_ext
;
68 if (fmt_ext
->fmt
.channels
> max_ch
)
69 max_ch
= fmt_ext
->fmt
.channels
;
71 /* Move to the next nhlt_fmt_cfg */
72 fmt_cfg
= (struct nhlt_fmt_cfg
*)(fmt_cfg
->config
.caps
+
73 fmt_cfg
->config
.size
);
75 dev_dbg(dev
, "max channels found %d\n", max_ch
);
77 dev_dbg(dev
, "No format information found\n");
80 if (cfg
->device_config
.config_type
!= NHLT_CONFIG_TYPE_MIC_ARRAY
) {
83 switch (cfg
->array_type
) {
84 case NHLT_MIC_ARRAY_2CH_SMALL
:
85 case NHLT_MIC_ARRAY_2CH_BIG
:
86 dmic_geo
= MIC_ARRAY_2CH
;
89 case NHLT_MIC_ARRAY_4CH_1ST_GEOM
:
90 case NHLT_MIC_ARRAY_4CH_L_SHAPED
:
91 case NHLT_MIC_ARRAY_4CH_2ND_GEOM
:
92 dmic_geo
= MIC_ARRAY_4CH
;
94 case NHLT_MIC_ARRAY_VENDOR_DEFINED
:
95 cfg_vendor
= (struct nhlt_vendor_dmic_array_config
*)cfg
;
96 dmic_geo
= cfg_vendor
->nb_mics
;
99 dev_warn(dev
, "%s: undefined DMIC array_type 0x%0x\n",
100 __func__
, cfg
->array_type
);
104 dev_dbg(dev
, "Array with %d dmics\n", dmic_geo
);
106 if (max_ch
> dmic_geo
) {
107 dev_dbg(dev
, "max channels %d exceed dmic number %d\n",
113 dev_dbg(dev
, "dmic number %d max_ch %d\n", dmic_geo
, max_ch
);
117 EXPORT_SYMBOL_GPL(intel_nhlt_get_dmic_geo
);
119 bool intel_nhlt_has_endpoint_type(struct nhlt_acpi_table
*nhlt
, u8 link_type
)
121 struct nhlt_endpoint
*epnt
;
127 epnt
= (struct nhlt_endpoint
*)nhlt
->desc
;
128 for (i
= 0; i
< nhlt
->endpoint_count
; i
++) {
129 if (epnt
->linktype
== link_type
)
132 epnt
= (struct nhlt_endpoint
*)((u8
*)epnt
+ epnt
->length
);
136 EXPORT_SYMBOL(intel_nhlt_has_endpoint_type
);
138 int intel_nhlt_ssp_endpoint_mask(struct nhlt_acpi_table
*nhlt
, u8 device_type
)
140 struct nhlt_endpoint
*epnt
;
144 if (!nhlt
|| (device_type
!= NHLT_DEVICE_BT
&& device_type
!= NHLT_DEVICE_I2S
))
147 epnt
= (struct nhlt_endpoint
*)nhlt
->desc
;
148 for (i
= 0; i
< nhlt
->endpoint_count
; i
++) {
149 if (epnt
->linktype
== NHLT_LINK_SSP
&& epnt
->device_type
== device_type
) {
150 /* for SSP the virtual bus id is the SSP port */
151 ssp_mask
|= BIT(epnt
->virtual_bus_id
);
153 epnt
= (struct nhlt_endpoint
*)((u8
*)epnt
+ epnt
->length
);
158 EXPORT_SYMBOL(intel_nhlt_ssp_endpoint_mask
);
160 #define SSP_BLOB_V1_0_SIZE 84
161 #define SSP_BLOB_V1_0_MDIVC_OFFSET 19 /* offset in u32 */
163 #define SSP_BLOB_V1_5_SIZE 96
164 #define SSP_BLOB_V1_5_MDIVC_OFFSET 21 /* offset in u32 */
165 #define SSP_BLOB_VER_1_5 0xEE000105
167 #define SSP_BLOB_V2_0_SIZE 88
168 #define SSP_BLOB_V2_0_MDIVC_OFFSET 20 /* offset in u32 */
169 #define SSP_BLOB_VER_2_0 0xEE000200
171 int intel_nhlt_ssp_mclk_mask(struct nhlt_acpi_table
*nhlt
, int ssp_num
)
173 struct nhlt_endpoint
*epnt
;
174 struct nhlt_fmt
*fmt
;
175 struct nhlt_fmt_cfg
*cfg
;
182 epnt
= (struct nhlt_endpoint
*)nhlt
->desc
;
183 for (i
= 0; i
< nhlt
->endpoint_count
; i
++) {
185 /* we only care about endpoints connected to an audio codec over SSP */
186 if (epnt
->linktype
== NHLT_LINK_SSP
&&
187 epnt
->device_type
== NHLT_DEVICE_I2S
&&
188 epnt
->virtual_bus_id
== ssp_num
) {
190 fmt
= (struct nhlt_fmt
*)(epnt
->config
.caps
+ epnt
->config
.size
);
191 cfg
= fmt
->fmt_config
;
194 * In theory all formats should use the same MCLK but it doesn't hurt to
195 * double-check that the configuration is consistent
197 for (j
= 0; j
< fmt
->fmt_count
; j
++) {
202 /* first check we have enough data to read the blob type */
203 if (cfg
->config
.size
< 8)
206 blob
= (u32
*)cfg
->config
.caps
;
208 if (blob
[1] == SSP_BLOB_VER_2_0
) {
209 mdivc_offset
= SSP_BLOB_V2_0_MDIVC_OFFSET
;
210 size
= SSP_BLOB_V2_0_SIZE
;
211 } else if (blob
[1] == SSP_BLOB_VER_1_5
) {
212 mdivc_offset
= SSP_BLOB_V1_5_MDIVC_OFFSET
;
213 size
= SSP_BLOB_V1_5_SIZE
;
215 mdivc_offset
= SSP_BLOB_V1_0_MDIVC_OFFSET
;
216 size
= SSP_BLOB_V1_0_SIZE
;
219 /* make sure we have enough data for the fixed part of the blob */
220 if (cfg
->config
.size
< size
)
223 mclk_mask
|= blob
[mdivc_offset
] & GENMASK(1, 0);
225 cfg
= (struct nhlt_fmt_cfg
*)(cfg
->config
.caps
+ cfg
->config
.size
);
228 epnt
= (struct nhlt_endpoint
*)((u8
*)epnt
+ epnt
->length
);
231 /* make sure only one MCLK is used */
232 if (hweight_long(mclk_mask
) != 1)
237 EXPORT_SYMBOL(intel_nhlt_ssp_mclk_mask
);
239 static struct nhlt_specific_cfg
*
240 nhlt_get_specific_cfg(struct device
*dev
, struct nhlt_fmt
*fmt
, u8 num_ch
,
241 u32 rate
, u8 vbps
, u8 bps
, bool ignore_vbps
)
243 struct nhlt_fmt_cfg
*cfg
= fmt
->fmt_config
;
244 struct wav_fmt
*wfmt
;
248 dev_dbg(dev
, "Endpoint format count=%d\n", fmt
->fmt_count
);
250 for (i
= 0; i
< fmt
->fmt_count
; i
++) {
251 wfmt
= &cfg
->fmt_ext
.fmt
;
252 _bps
= wfmt
->bits_per_sample
;
253 _vbps
= cfg
->fmt_ext
.sample
.valid_bits_per_sample
;
255 dev_dbg(dev
, "Endpoint format: ch=%d fmt=%d/%d rate=%d\n",
256 wfmt
->channels
, _vbps
, _bps
, wfmt
->samples_per_sec
);
259 * When looking for exact match of configuration ignore the vbps
260 * from NHLT table when ignore_vbps is true
262 if (wfmt
->channels
== num_ch
&& wfmt
->samples_per_sec
== rate
&&
263 (ignore_vbps
|| vbps
== _vbps
) && bps
== _bps
)
266 cfg
= (struct nhlt_fmt_cfg
*)(cfg
->config
.caps
+ cfg
->config
.size
);
272 static bool nhlt_check_ep_match(struct device
*dev
, struct nhlt_endpoint
*epnt
,
273 u32 bus_id
, u8 link_type
, u8 dir
, u8 dev_type
)
275 dev_dbg(dev
, "Endpoint: vbus_id=%d link_type=%d dir=%d dev_type = %d\n",
276 epnt
->virtual_bus_id
, epnt
->linktype
,
277 epnt
->direction
, epnt
->device_type
);
279 if ((epnt
->virtual_bus_id
!= bus_id
) ||
280 (epnt
->linktype
!= link_type
) ||
281 (epnt
->direction
!= dir
))
284 /* link of type DMIC bypasses device_type check */
285 return epnt
->linktype
== NHLT_LINK_DMIC
||
286 epnt
->device_type
== dev_type
;
289 struct nhlt_specific_cfg
*
290 intel_nhlt_get_endpoint_blob(struct device
*dev
, struct nhlt_acpi_table
*nhlt
,
291 u32 bus_id
, u8 link_type
, u8 vbps
, u8 bps
,
292 u8 num_ch
, u32 rate
, u8 dir
, u8 dev_type
)
294 struct nhlt_specific_cfg
*cfg
;
295 struct nhlt_endpoint
*epnt
;
296 bool ignore_vbps
= false;
297 struct nhlt_fmt
*fmt
;
303 dev_dbg(dev
, "Looking for configuration:\n");
304 dev_dbg(dev
, " vbus_id=%d link_type=%d dir=%d, dev_type=%d\n",
305 bus_id
, link_type
, dir
, dev_type
);
306 if (link_type
== NHLT_LINK_DMIC
&& bps
== 32 && (vbps
== 24 || vbps
== 32)) {
308 * The DMIC hardware supports only one type of 32 bits sample
309 * size, which is 24 bit sampling on the MSB side and bits[1:0]
310 * are used for indicating the channel number.
311 * It has been observed that some NHLT tables have the vbps
312 * specified as 32 while some uses 24.
313 * The format these variations describe are identical, the
314 * hardware is configured and behaves the same way.
315 * Note: when the samples assumed to be vbps=32 then the 'noise'
316 * introduced by the lower two bits (channel number) have no
317 * real life implication on audio quality.
320 " ch=%d fmt=%d rate=%d (vbps is ignored for DMIC 32bit format)\n",
324 dev_dbg(dev
, " ch=%d fmt=%d/%d rate=%d\n", num_ch
, vbps
, bps
, rate
);
326 dev_dbg(dev
, "Endpoint count=%d\n", nhlt
->endpoint_count
);
328 epnt
= (struct nhlt_endpoint
*)nhlt
->desc
;
330 for (i
= 0; i
< nhlt
->endpoint_count
; i
++) {
331 if (nhlt_check_ep_match(dev
, epnt
, bus_id
, link_type
, dir
, dev_type
)) {
332 fmt
= (struct nhlt_fmt
*)(epnt
->config
.caps
+ epnt
->config
.size
);
334 cfg
= nhlt_get_specific_cfg(dev
, fmt
, num_ch
, rate
,
335 vbps
, bps
, ignore_vbps
);
340 epnt
= (struct nhlt_endpoint
*)((u8
*)epnt
+ epnt
->length
);
345 EXPORT_SYMBOL(intel_nhlt_get_endpoint_blob
);
347 int intel_nhlt_ssp_device_type(struct device
*dev
, struct nhlt_acpi_table
*nhlt
,
350 struct nhlt_endpoint
*epnt
;
356 epnt
= (struct nhlt_endpoint
*)nhlt
->desc
;
357 for (i
= 0; i
< nhlt
->endpoint_count
; i
++) {
358 /* for SSP link the virtual bus id is the SSP port number */
359 if (epnt
->linktype
== NHLT_LINK_SSP
&&
360 epnt
->virtual_bus_id
== virtual_bus_id
) {
361 dev_dbg(dev
, "SSP%d: dev_type=%d\n", virtual_bus_id
,
363 return epnt
->device_type
;
366 epnt
= (struct nhlt_endpoint
*)((u8
*)epnt
+ epnt
->length
);
371 EXPORT_SYMBOL(intel_nhlt_ssp_device_type
);