Branch data Line data Source code
1 : : // SPDX-License-Identifier: GPL-2.0 2 : : // Copyright (c) 2015-2019 Intel Corporation 3 : : 4 : : #include <linux/acpi.h> 5 : : #include <sound/intel-nhlt.h> 6 : : 7 : : #define NHLT_ACPI_HEADER_SIG "NHLT" 8 : : 9 : : /* Unique identification for getting NHLT blobs */ 10 : : static const guid_t osc_guid = 11 : : GUID_INIT(0xA69F886E, 0x6CEB, 0x4594, 12 : : 0xA4, 0x1F, 0x7B, 0x5D, 0xCE, 0x24, 0xC5, 0x53); 13 : : 14 : 0 : struct nhlt_acpi_table *intel_nhlt_init(struct device *dev) 15 : : { 16 : 0 : acpi_handle handle; 17 : 0 : union acpi_object *obj; 18 : 0 : struct nhlt_resource_desc *nhlt_ptr; 19 : 0 : struct nhlt_acpi_table *nhlt_table = NULL; 20 : : 21 [ # # # # ]: 0 : handle = ACPI_HANDLE(dev); 22 [ # # ]: 0 : if (!handle) { 23 : 0 : dev_err(dev, "Didn't find ACPI_HANDLE\n"); 24 : 0 : return NULL; 25 : : } 26 : : 27 : 0 : obj = acpi_evaluate_dsm(handle, &osc_guid, 1, 1, NULL); 28 : : 29 [ # # ]: 0 : if (!obj) 30 : : return NULL; 31 : : 32 [ # # ]: 0 : if (obj->type != ACPI_TYPE_BUFFER) { 33 : 0 : dev_dbg(dev, "No NHLT table found\n"); 34 : 0 : ACPI_FREE(obj); 35 : 0 : return NULL; 36 : : } 37 : : 38 : 0 : nhlt_ptr = (struct nhlt_resource_desc *)obj->buffer.pointer; 39 [ # # ]: 0 : if (nhlt_ptr->length) 40 : 0 : nhlt_table = (struct nhlt_acpi_table *) 41 : 0 : memremap(nhlt_ptr->min_addr, nhlt_ptr->length, 42 : : MEMREMAP_WB); 43 : 0 : ACPI_FREE(obj); 44 [ # # ]: 0 : if (nhlt_table && 45 [ # # ]: 0 : (strncmp(nhlt_table->header.signature, 46 : : NHLT_ACPI_HEADER_SIG, 47 : : strlen(NHLT_ACPI_HEADER_SIG)) != 0)) { 48 : 0 : memunmap(nhlt_table); 49 : 0 : dev_err(dev, "NHLT ACPI header signature incorrect\n"); 50 : 0 : return NULL; 51 : : } 52 : : return nhlt_table; 53 : : } 54 : : EXPORT_SYMBOL_GPL(intel_nhlt_init); 55 : : 56 : 0 : void intel_nhlt_free(struct nhlt_acpi_table *nhlt) 57 : : { 58 : 0 : memunmap((void *)nhlt); 59 : 0 : } 60 : : EXPORT_SYMBOL_GPL(intel_nhlt_free); 61 : : 62 : 0 : int intel_nhlt_get_dmic_geo(struct device *dev, struct nhlt_acpi_table *nhlt) 63 : : { 64 : 0 : struct nhlt_endpoint *epnt; 65 : 0 : struct nhlt_dmic_array_config *cfg; 66 : 0 : struct nhlt_vendor_dmic_array_config *cfg_vendor; 67 : 0 : unsigned int dmic_geo = 0; 68 : 0 : u8 j; 69 : : 70 [ # # ]: 0 : if (!nhlt) 71 : : return 0; 72 : : 73 : 0 : epnt = (struct nhlt_endpoint *)nhlt->desc; 74 : : 75 [ # # ]: 0 : for (j = 0; j < nhlt->endpoint_count; j++) { 76 [ # # ]: 0 : if (epnt->linktype == NHLT_LINK_DMIC) { 77 : 0 : cfg = (struct nhlt_dmic_array_config *) 78 : : (epnt->config.caps); 79 [ # # # # ]: 0 : switch (cfg->array_type) { 80 : : case NHLT_MIC_ARRAY_2CH_SMALL: 81 : : case NHLT_MIC_ARRAY_2CH_BIG: 82 : : dmic_geo = MIC_ARRAY_2CH; 83 : : break; 84 : : 85 : 0 : case NHLT_MIC_ARRAY_4CH_1ST_GEOM: 86 : : case NHLT_MIC_ARRAY_4CH_L_SHAPED: 87 : : case NHLT_MIC_ARRAY_4CH_2ND_GEOM: 88 : 0 : dmic_geo = MIC_ARRAY_4CH; 89 : 0 : break; 90 : 0 : case NHLT_MIC_ARRAY_VENDOR_DEFINED: 91 : 0 : cfg_vendor = (struct nhlt_vendor_dmic_array_config *)cfg; 92 : 0 : dmic_geo = cfg_vendor->nb_mics; 93 : 0 : break; 94 : 0 : default: 95 : 0 : dev_warn(dev, "undefined DMIC array_type 0x%0x\n", 96 : : cfg->array_type); 97 : : } 98 : 0 : } 99 : 0 : epnt = (struct nhlt_endpoint *)((u8 *)epnt + epnt->length); 100 : : } 101 : : 102 : 0 : return dmic_geo; 103 : : } 104 : : EXPORT_SYMBOL_GPL(intel_nhlt_get_dmic_geo);