1 /* SPDX-License-Identifier: GPL-2.0-only */
5 #include <commonlib/endian.h>
6 #include <console/console.h>
13 #define WAVEFORMAT_TAG 0xfffe
14 #define DEFAULT_VIRTUAL_BUS_ID 0
16 static const struct sub_format pcm_subformat
= {
20 .data4
= { 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71 },
23 struct nhlt
*nhlt_init(void)
27 nhlt
= malloc(sizeof(*nhlt
));
32 memset(nhlt
, 0, sizeof(*nhlt
));
33 nhlt
->subsystem_id
= NHLT_SSID
;
38 struct nhlt_endpoint
*nhlt_add_endpoint(struct nhlt
*nhlt
, int link_type
,
39 int device_type
, int dir
,
40 uint16_t vid
, uint16_t did
)
42 struct nhlt_endpoint
*endp
;
44 if (link_type
< NHLT_LINK_HDA
|| link_type
>= NHLT_MAX_LINK_TYPES
)
47 if (nhlt
->num_endpoints
>= MAX_ENDPOINTS
)
50 endp
= &nhlt
->endpoints
[nhlt
->num_endpoints
];
52 endp
->link_type
= link_type
;
53 endp
->instance_id
= nhlt
->current_instance_id
[link_type
];
54 endp
->vendor_id
= vid
;
55 endp
->device_id
= did
;
56 endp
->revision_id
= NHLT_RID
;
57 endp
->subsystem_id
= nhlt
->subsystem_id
;
58 endp
->device_type
= device_type
;
59 endp
->direction
= dir
;
60 endp
->virtual_bus_id
= DEFAULT_VIRTUAL_BUS_ID
;
62 nhlt
->num_endpoints
++;
67 static int append_specific_config(struct nhlt_specific_config
*spec_cfg
,
68 const void *config
, size_t config_sz
)
73 if (config
== NULL
|| config_sz
== 0)
76 new_sz
= spec_cfg
->size
+ config_sz
;
78 new_cfg
= malloc(new_sz
);
83 /* Append new config. */
84 memcpy(new_cfg
, spec_cfg
->capabilities
, spec_cfg
->size
);
85 memcpy(new_cfg
+ spec_cfg
->size
, config
, config_sz
);
87 free(spec_cfg
->capabilities
);
89 /* Update with new config data. */
90 spec_cfg
->size
= new_sz
;
91 spec_cfg
->capabilities
= new_cfg
;
96 int nhlt_endpoint_append_config(struct nhlt_endpoint
*endp
, const void *config
,
99 return append_specific_config(&endp
->config
, config
, config_sz
);
102 struct nhlt_format
*nhlt_add_format(struct nhlt_endpoint
*endp
,
105 int container_bits_per_sample
,
106 int valid_bits_per_sample
,
107 uint32_t speaker_mask
)
109 struct nhlt_format
*fmt
;
110 struct nhlt_waveform
*wave
;
112 if (endp
->num_formats
>= MAX_FORMATS
)
115 fmt
= &endp
->formats
[endp
->num_formats
];
116 wave
= &fmt
->waveform
;
118 wave
->tag
= WAVEFORMAT_TAG
;
119 wave
->num_channels
= num_channels
;
120 wave
->samples_per_second
= sample_freq_khz
* KHz
;
121 wave
->bits_per_sample
= container_bits_per_sample
;
122 wave
->extra_size
= sizeof(wave
->valid_bits_per_sample
);
123 wave
->extra_size
+= sizeof(wave
->channel_mask
);
124 wave
->extra_size
+= sizeof(wave
->sub_format
);
125 wave
->valid_bits_per_sample
= valid_bits_per_sample
;
126 wave
->channel_mask
= speaker_mask
;
127 memcpy(&wave
->sub_format
, &pcm_subformat
, sizeof(wave
->sub_format
));
129 /* Calculate the derived fields. */
130 wave
->block_align
= wave
->num_channels
* wave
->bits_per_sample
/ 8;
131 wave
->bytes_per_second
= wave
->block_align
* wave
->samples_per_second
;
138 int nhlt_format_append_config(struct nhlt_format
*fmt
, const void *config
,
141 return append_specific_config(&fmt
->config
, config
, config_sz
);
144 int nhlt_endpoint_add_formats(struct nhlt_endpoint
*endp
,
145 const struct nhlt_format_config
*formats
,
150 for (i
= 0; i
< num_formats
; i
++) {
151 struct nhlt_format
*fmt
;
154 const struct nhlt_format_config
*cfg
= &formats
[i
];
156 fmt
= nhlt_add_format(endp
, cfg
->num_channels
,
157 cfg
->sample_freq_khz
,
158 cfg
->container_bits_per_sample
,
159 cfg
->valid_bits_per_sample
,
165 if (cfg
->settings_file
== NULL
)
168 /* Find the settings file in CBFS and place it in format. */
169 settings_data
= cbfs_map(cfg
->settings_file
, &size
);
173 if (nhlt_format_append_config(fmt
, settings_data
, size
)) {
174 cbfs_unmap(settings_data
);
178 cbfs_unmap(settings_data
);
184 static size_t calc_specific_config_size(struct nhlt_specific_config
*cfg
)
186 return sizeof(cfg
->size
) + cfg
->size
;
189 static size_t calc_format_size(struct nhlt_format
*fmt
)
193 /* Wave format first. */
194 sz
+= sizeof(fmt
->waveform
.tag
);
195 sz
+= sizeof(fmt
->waveform
.num_channels
);
196 sz
+= sizeof(fmt
->waveform
.samples_per_second
);
197 sz
+= sizeof(fmt
->waveform
.bytes_per_second
);
198 sz
+= sizeof(fmt
->waveform
.block_align
);
199 sz
+= sizeof(fmt
->waveform
.bits_per_sample
);
200 sz
+= sizeof(fmt
->waveform
.extra_size
);
201 sz
+= sizeof(fmt
->waveform
.valid_bits_per_sample
);
202 sz
+= sizeof(fmt
->waveform
.channel_mask
);
203 sz
+= sizeof(fmt
->waveform
.sub_format
);
205 sz
+= calc_specific_config_size(&fmt
->config
);
210 static size_t calc_endpoint_size(struct nhlt_endpoint
*endp
)
215 sz
+= sizeof(endp
->length
) + sizeof(endp
->link_type
);
216 sz
+= sizeof(endp
->instance_id
) + sizeof(endp
->vendor_id
);
217 sz
+= sizeof(endp
->device_id
) + sizeof(endp
->revision_id
);
218 sz
+= sizeof(endp
->subsystem_id
) + sizeof(endp
->device_type
);
219 sz
+= sizeof(endp
->direction
) + sizeof(endp
->virtual_bus_id
);
220 sz
+= calc_specific_config_size(&endp
->config
);
221 sz
+= sizeof(endp
->num_formats
);
223 for (i
= 0; i
< endp
->num_formats
; i
++)
224 sz
+= calc_format_size(&endp
->formats
[i
]);
226 /* Adjust endpoint length to reflect current configuration. */
232 static size_t calc_endpoints_size(struct nhlt
*nhlt
)
237 for (i
= 0; i
< nhlt
->num_endpoints
; i
++)
238 sz
+= calc_endpoint_size(&nhlt
->endpoints
[i
]);
243 static size_t calc_size(struct nhlt
*nhlt
)
245 return sizeof(nhlt
->num_endpoints
) + calc_endpoints_size(nhlt
);
248 size_t nhlt_current_size(struct nhlt
*nhlt
)
250 return calc_size(nhlt
) + sizeof(acpi_header_t
) + sizeof(uint32_t);
253 static void nhlt_free_resources(struct nhlt
*nhlt
)
258 /* Free all specific configs. */
259 for (i
= 0; i
< nhlt
->num_endpoints
; i
++) {
260 struct nhlt_endpoint
*endp
= &nhlt
->endpoints
[i
];
262 free(endp
->config
.capabilities
);
263 for (j
= 0; j
< endp
->num_formats
; j
++) {
264 struct nhlt_format
*fmt
= &endp
->formats
[j
];
266 free(fmt
->config
.capabilities
);
270 /* Free nhlt object proper. */
278 static void ser8(struct cursor
*cur
, uint8_t val
)
280 write_le8(cur
->buf
, val
);
281 cur
->buf
+= sizeof(val
);
284 static void ser16(struct cursor
*cur
, uint16_t val
)
286 write_le16(cur
->buf
, val
);
287 cur
->buf
+= sizeof(val
);
290 static void ser32(struct cursor
*cur
, uint32_t val
)
292 write_le32(cur
->buf
, val
);
293 cur
->buf
+= sizeof(val
);
296 static void serblob(struct cursor
*cur
, void *from
, size_t sz
)
298 memcpy(cur
->buf
, from
, sz
);
302 static void serialize_specific_config(struct nhlt_specific_config
*cfg
,
305 ser32(cur
, cfg
->size
);
306 serblob(cur
, cfg
->capabilities
, cfg
->size
);
309 static void serialize_waveform(struct nhlt_waveform
*wave
, struct cursor
*cur
)
311 ser16(cur
, wave
->tag
);
312 ser16(cur
, wave
->num_channels
);
313 ser32(cur
, wave
->samples_per_second
);
314 ser32(cur
, wave
->bytes_per_second
);
315 ser16(cur
, wave
->block_align
);
316 ser16(cur
, wave
->bits_per_sample
);
317 ser16(cur
, wave
->extra_size
);
318 ser16(cur
, wave
->valid_bits_per_sample
);
319 ser32(cur
, wave
->channel_mask
);
320 ser32(cur
, wave
->sub_format
.data1
);
321 ser16(cur
, wave
->sub_format
.data2
);
322 ser16(cur
, wave
->sub_format
.data3
);
323 serblob(cur
, wave
->sub_format
.data4
, sizeof(wave
->sub_format
.data4
));
326 static void serialize_format(struct nhlt_format
*fmt
, struct cursor
*cur
)
328 serialize_waveform(&fmt
->waveform
, cur
);
329 serialize_specific_config(&fmt
->config
, cur
);
332 static void serialize_endpoint(struct nhlt_endpoint
*endp
, struct cursor
*cur
)
336 ser32(cur
, endp
->length
);
337 ser8(cur
, endp
->link_type
);
338 ser8(cur
, endp
->instance_id
);
339 ser16(cur
, endp
->vendor_id
);
340 ser16(cur
, endp
->device_id
);
341 ser16(cur
, endp
->revision_id
);
342 ser32(cur
, endp
->subsystem_id
);
343 ser8(cur
, endp
->device_type
);
344 ser8(cur
, endp
->direction
);
345 ser8(cur
, endp
->virtual_bus_id
);
346 serialize_specific_config(&endp
->config
, cur
);
347 ser8(cur
, endp
->num_formats
);
349 for (i
= 0; i
< endp
->num_formats
; i
++)
350 serialize_format(&endp
->formats
[i
], cur
);
353 static void nhlt_serialize_endpoints(struct nhlt
*nhlt
, struct cursor
*cur
)
355 int i
, capabilities_size
= 0;
357 ser8(cur
, nhlt
->num_endpoints
);
359 for (i
= 0; i
< nhlt
->num_endpoints
; i
++)
360 serialize_endpoint(&nhlt
->endpoints
[i
], cur
);
361 ser32(cur
, capabilities_size
);
364 uintptr_t nhlt_serialize(struct nhlt
*nhlt
, uintptr_t acpi_addr
)
366 return nhlt_serialize_oem_overrides(nhlt
, acpi_addr
, NULL
, NULL
, 0);
369 uintptr_t nhlt_serialize_oem_overrides(struct nhlt
*nhlt
,
370 uintptr_t acpi_addr
, const char *oem_id
, const char *oem_table_id
,
371 uint32_t oem_revision
)
374 acpi_header_t
*header
;
377 size_t oem_table_id_len
;
379 printk(BIOS_DEBUG
, "ACPI: * NHLT\n");
381 sz
= nhlt_current_size(nhlt
);
384 header
= (void *)acpi_addr
;
385 memset(header
, 0, sizeof(acpi_header_t
));
386 memcpy(header
->signature
, "NHLT", 4);
387 write_le32(&header
->length
, sz
);
388 write_le8(&header
->revision
, get_acpi_table_revision(NHLT
));
393 if (oem_table_id
== NULL
)
394 oem_table_id
= ACPI_TABLE_CREATOR
;
396 oem_id_len
= MIN(strlen(oem_id
), 6);
397 oem_table_id_len
= MIN(strlen(oem_table_id
), 8);
399 memcpy(header
->oem_id
, oem_id
, oem_id_len
);
400 memcpy(header
->oem_table_id
, oem_table_id
, oem_table_id_len
);
401 write_le32(&header
->oem_revision
, oem_revision
);
402 memcpy(header
->asl_compiler_id
, ASLC
, 4);
404 cur
.buf
= (void *)(acpi_addr
+ sizeof(acpi_header_t
));
405 nhlt_serialize_endpoints(nhlt
, &cur
);
407 write_le8(&header
->checksum
, acpi_checksum((void *)header
, sz
));
409 nhlt_free_resources(nhlt
);
412 acpi_addr
= ALIGN_UP(acpi_addr
, 16);
417 static int _nhlt_add_single_endpoint(struct nhlt
*nhlt
, int virtual_bus_id
,
418 const struct nhlt_endp_descriptor
*epd
)
420 struct nhlt_endpoint
*endp
;
422 endp
= nhlt_add_endpoint(nhlt
, epd
->link
, epd
->device
, epd
->direction
,
428 endp
->virtual_bus_id
= virtual_bus_id
;
430 if (nhlt_endpoint_append_config(endp
, epd
->cfg
, epd
->cfg_size
))
433 if (nhlt_endpoint_add_formats(endp
, epd
->formats
, epd
->num_formats
))
439 static int _nhlt_add_endpoints(struct nhlt
*nhlt
, int virtual_bus_id
,
440 const struct nhlt_endp_descriptor
*epds
,
445 for (i
= 0; i
< num_epds
; i
++)
446 if (_nhlt_add_single_endpoint(nhlt
, virtual_bus_id
, &epds
[i
]))
452 int nhlt_add_endpoints(struct nhlt
*nhlt
,
453 const struct nhlt_endp_descriptor
*epds
,
457 ret
= _nhlt_add_endpoints(nhlt
, DEFAULT_VIRTUAL_BUS_ID
, epds
, num_epds
);
461 int nhlt_add_ssp_endpoints(struct nhlt
*nhlt
, int virtual_bus_id
,
462 const struct nhlt_endp_descriptor
*epds
, size_t num_epds
)
464 return _nhlt_add_endpoints(nhlt
, virtual_bus_id
, epds
, num_epds
);