nhlt.c
1 /* SPDX-License-Identifier: GPL-2.0-only */ 2 3 #include <acpi/acpi.h> 4 #include <cbfs.h> 5 #include <commonlib/endian.h> 6 #include <console/console.h> 7 #include <nhlt.h> 8 #include <stdlib.h> 9 #include <string.h> 10 11 #define NHLT_RID 1 12 #define NHLT_SSID 1 13 #define WAVEFORMAT_TAG 0xfffe 14 #define DEFAULT_VIRTUAL_BUS_ID 0 15 16 static const struct sub_format pcm_subformat = { 17 .data1 = 0x00000001, 18 .data2 = 0x0000, 19 .data3 = 0x0010, 20 .data4 = { 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71 }, 21 }; 22 23 struct nhlt *nhlt_init(void) 24 { 25 struct nhlt *nhlt; 26 27 nhlt = malloc(sizeof(*nhlt)); 28 29 if (nhlt == NULL) 30 return NULL; 31 32 memset(nhlt, 0, sizeof(*nhlt)); 33 nhlt->subsystem_id = NHLT_SSID; 34 35 return nhlt; 36 } 37 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) 41 { 42 struct nhlt_endpoint *endp; 43 44 if (link_type < NHLT_LINK_HDA || link_type >= NHLT_MAX_LINK_TYPES) 45 return NULL; 46 47 if (nhlt->num_endpoints >= MAX_ENDPOINTS) 48 return NULL; 49 50 endp = &nhlt->endpoints[nhlt->num_endpoints]; 51 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; 61 62 nhlt->num_endpoints++; 63 64 return endp; 65 } 66 67 static int append_specific_config(struct nhlt_specific_config *spec_cfg, 68 const void *config, size_t config_sz) 69 { 70 size_t new_sz; 71 void *new_cfg; 72 73 if (config == NULL || config_sz == 0) 74 return 0; 75 76 new_sz = spec_cfg->size + config_sz; 77 78 new_cfg = malloc(new_sz); 79 80 if (new_cfg == NULL) 81 return -1; 82 83 /* Append new config. */ 84 memcpy(new_cfg, spec_cfg->capabilities, spec_cfg->size); 85 memcpy(new_cfg + spec_cfg->size, config, config_sz); 86 87 free(spec_cfg->capabilities); 88 89 /* Update with new config data. */ 90 spec_cfg->size = new_sz; 91 spec_cfg->capabilities = new_cfg; 92 93 return 0; 94 } 95 96 int nhlt_endpoint_append_config(struct nhlt_endpoint *endp, const void *config, 97 size_t config_sz) 98 { 99 return append_specific_config(&endp->config, config, config_sz); 100 } 101 102 struct nhlt_format *nhlt_add_format(struct nhlt_endpoint *endp, 103 int num_channels, 104 int sample_freq_khz, 105 int container_bits_per_sample, 106 int valid_bits_per_sample, 107 uint32_t speaker_mask) 108 { 109 struct nhlt_format *fmt; 110 struct nhlt_waveform *wave; 111 112 if (endp->num_formats >= MAX_FORMATS) 113 return NULL; 114 115 fmt = &endp->formats[endp->num_formats]; 116 wave = &fmt->waveform; 117 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)); 128 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; 132 133 endp->num_formats++; 134 135 return fmt; 136 } 137 138 int nhlt_format_append_config(struct nhlt_format *fmt, const void *config, 139 size_t config_sz) 140 { 141 return append_specific_config(&fmt->config, config, config_sz); 142 } 143 144 int nhlt_endpoint_add_formats(struct nhlt_endpoint *endp, 145 const struct nhlt_format_config *formats, 146 size_t num_formats) 147 { 148 size_t i; 149 150 for (i = 0; i < num_formats; i++) { 151 struct nhlt_format *fmt; 152 void *settings_data; 153 size_t size; 154 const struct nhlt_format_config *cfg = &formats[i]; 155 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, 160 cfg->speaker_mask); 161 162 if (fmt == NULL) 163 return -1; 164 165 if (cfg->settings_file == NULL) 166 continue; 167 168 /* Find the settings file in CBFS and place it in format. */ 169 settings_data = cbfs_map(cfg->settings_file, &size); 170 if (!settings_data) 171 return -1; 172 173 if (nhlt_format_append_config(fmt, settings_data, size)) { 174 cbfs_unmap(settings_data); 175 return -1; 176 } 177 178 cbfs_unmap(settings_data); 179 } 180 181 return 0; 182 } 183 184 static size_t calc_specific_config_size(struct nhlt_specific_config *cfg) 185 { 186 return sizeof(cfg->size) + cfg->size; 187 } 188 189 static size_t calc_format_size(struct nhlt_format *fmt) 190 { 191 size_t sz = 0; 192 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); 204 205 sz += calc_specific_config_size(&fmt->config); 206 207 return sz; 208 } 209 210 static size_t calc_endpoint_size(struct nhlt_endpoint *endp) 211 { 212 int i; 213 size_t sz = 0; 214 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); 222 223 for (i = 0; i < endp->num_formats; i++) 224 sz += calc_format_size(&endp->formats[i]); 225 226 /* Adjust endpoint length to reflect current configuration. */ 227 endp->length = sz; 228 229 return sz; 230 } 231 232 static size_t calc_endpoints_size(struct nhlt *nhlt) 233 { 234 int i; 235 size_t sz = 0; 236 237 for (i = 0; i < nhlt->num_endpoints; i++) 238 sz += calc_endpoint_size(&nhlt->endpoints[i]); 239 240 return sz; 241 } 242 243 static size_t calc_size(struct nhlt *nhlt) 244 { 245 return sizeof(nhlt->num_endpoints) + calc_endpoints_size(nhlt); 246 } 247 248 size_t nhlt_current_size(struct nhlt *nhlt) 249 { 250 return calc_size(nhlt) + sizeof(acpi_header_t) + sizeof(uint32_t); 251 } 252 253 static void nhlt_free_resources(struct nhlt *nhlt) 254 { 255 int i; 256 int j; 257 258 /* Free all specific configs. */ 259 for (i = 0; i < nhlt->num_endpoints; i++) { 260 struct nhlt_endpoint *endp = &nhlt->endpoints[i]; 261 262 free(endp->config.capabilities); 263 for (j = 0; j < endp->num_formats; j++) { 264 struct nhlt_format *fmt = &endp->formats[j]; 265 266 free(fmt->config.capabilities); 267 } 268 } 269 270 /* Free nhlt object proper. */ 271 free(nhlt); 272 } 273 274 struct cursor { 275 uint8_t *buf; 276 }; 277 278 static void ser8(struct cursor *cur, uint8_t val) 279 { 280 write_le8(cur->buf, val); 281 cur->buf += sizeof(val); 282 } 283 284 static void ser16(struct cursor *cur, uint16_t val) 285 { 286 write_le16(cur->buf, val); 287 cur->buf += sizeof(val); 288 } 289 290 static void ser32(struct cursor *cur, uint32_t val) 291 { 292 write_le32(cur->buf, val); 293 cur->buf += sizeof(val); 294 } 295 296 static void serblob(struct cursor *cur, void *from, size_t sz) 297 { 298 memcpy(cur->buf, from, sz); 299 cur->buf += sz; 300 } 301 302 static void serialize_specific_config(struct nhlt_specific_config *cfg, 303 struct cursor *cur) 304 { 305 ser32(cur, cfg->size); 306 serblob(cur, cfg->capabilities, cfg->size); 307 } 308 309 static void serialize_waveform(struct nhlt_waveform *wave, struct cursor *cur) 310 { 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)); 324 } 325 326 static void serialize_format(struct nhlt_format *fmt, struct cursor *cur) 327 { 328 serialize_waveform(&fmt->waveform, cur); 329 serialize_specific_config(&fmt->config, cur); 330 } 331 332 static void serialize_endpoint(struct nhlt_endpoint *endp, struct cursor *cur) 333 { 334 int i; 335 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); 348 349 for (i = 0; i < endp->num_formats; i++) 350 serialize_format(&endp->formats[i], cur); 351 } 352 353 static void nhlt_serialize_endpoints(struct nhlt *nhlt, struct cursor *cur) 354 { 355 int i, capabilities_size = 0; 356 357 ser8(cur, nhlt->num_endpoints); 358 359 for (i = 0; i < nhlt->num_endpoints; i++) 360 serialize_endpoint(&nhlt->endpoints[i], cur); 361 ser32(cur, capabilities_size); 362 } 363 364 uintptr_t nhlt_serialize(struct nhlt *nhlt, uintptr_t acpi_addr) 365 { 366 return nhlt_serialize_oem_overrides(nhlt, acpi_addr, NULL, NULL, 0); 367 } 368 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) 372 { 373 struct cursor cur; 374 acpi_header_t *header; 375 size_t sz; 376 size_t oem_id_len; 377 size_t oem_table_id_len; 378 379 printk(BIOS_DEBUG, "ACPI: * NHLT\n"); 380 381 sz = nhlt_current_size(nhlt); 382 383 /* Create header */ 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)); 389 390 if (oem_id == NULL) 391 oem_id = OEM_ID; 392 393 if (oem_table_id == NULL) 394 oem_table_id = ACPI_TABLE_CREATOR; 395 396 oem_id_len = MIN(strlen(oem_id), 6); 397 oem_table_id_len = MIN(strlen(oem_table_id), 8); 398 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); 403 404 cur.buf = (void *)(acpi_addr + sizeof(acpi_header_t)); 405 nhlt_serialize_endpoints(nhlt, &cur); 406 407 write_le8(&header->checksum, acpi_checksum((void *)header, sz)); 408 409 nhlt_free_resources(nhlt); 410 411 acpi_addr += sz; 412 acpi_addr = ALIGN_UP(acpi_addr, 16); 413 414 return acpi_addr; 415 } 416 417 static int _nhlt_add_single_endpoint(struct nhlt *nhlt, int virtual_bus_id, 418 const struct nhlt_endp_descriptor *epd) 419 { 420 struct nhlt_endpoint *endp; 421 422 endp = nhlt_add_endpoint(nhlt, epd->link, epd->device, epd->direction, 423 epd->vid, epd->did); 424 425 if (endp == NULL) 426 return -1; 427 428 endp->virtual_bus_id = virtual_bus_id; 429 430 if (nhlt_endpoint_append_config(endp, epd->cfg, epd->cfg_size)) 431 return -1; 432 433 if (nhlt_endpoint_add_formats(endp, epd->formats, epd->num_formats)) 434 return -1; 435 436 return 0; 437 } 438 439 static int _nhlt_add_endpoints(struct nhlt *nhlt, int virtual_bus_id, 440 const struct nhlt_endp_descriptor *epds, 441 size_t num_epds) 442 { 443 size_t i; 444 445 for (i = 0; i < num_epds; i++) 446 if (_nhlt_add_single_endpoint(nhlt, virtual_bus_id, &epds[i])) 447 return -1; 448 449 return 0; 450 } 451 452 int nhlt_add_endpoints(struct nhlt *nhlt, 453 const struct nhlt_endp_descriptor *epds, 454 size_t num_epds) 455 { 456 int ret; 457 ret = _nhlt_add_endpoints(nhlt, DEFAULT_VIRTUAL_BUS_ID, epds, num_epds); 458 return ret; 459 } 460 461 int nhlt_add_ssp_endpoints(struct nhlt *nhlt, int virtual_bus_id, 462 const struct nhlt_endp_descriptor *epds, size_t num_epds) 463 { 464 return _nhlt_add_endpoints(nhlt, virtual_bus_id, epds, num_epds); 465 }