1 /* 2 * skl-nhlt.c - Intel SKL Platform NHLT parsing 3 * 4 * Copyright (C) 2015 Intel Corp 5 * Author: Sanjiv Kumar <sanjiv.kumar@intel.com> 6 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 7 * 8 * This program is free software; you can redistribute it and/or modify 9 * it under the terms of the GNU General Public License as published by 10 * the Free Software Foundation; version 2 of the License. 11 * 12 * This program is distributed in the hope that it will be useful, but 13 * WITHOUT ANY WARRANTY; without even the implied warranty of 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 * General Public License for more details. 16 * 17 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 18 * 19 */ 20 #include <linux/pci.h> 21 #include "skl.h" 22 23 #define NHLT_ACPI_HEADER_SIG "NHLT" 24 25 /* Unique identification for getting NHLT blobs */ 26 static guid_t osc_guid = 27 GUID_INIT(0xA69F886E, 0x6CEB, 0x4594, 28 0xA4, 0x1F, 0x7B, 0x5D, 0xCE, 0x24, 0xC5, 0x53); 29 30 struct nhlt_acpi_table *skl_nhlt_init(struct device *dev) 31 { 32 acpi_handle handle; 33 union acpi_object *obj; 34 struct nhlt_resource_desc *nhlt_ptr = NULL; 35 struct nhlt_acpi_table *nhlt_table = NULL; 36 37 handle = ACPI_HANDLE(dev); 38 if (!handle) { 39 dev_err(dev, "Didn't find ACPI_HANDLE\n"); 40 return NULL; 41 } 42 43 obj = acpi_evaluate_dsm(handle, &osc_guid, 1, 1, NULL); 44 if (obj && obj->type == ACPI_TYPE_BUFFER) { 45 nhlt_ptr = (struct nhlt_resource_desc *)obj->buffer.pointer; 46 nhlt_table = (struct nhlt_acpi_table *) 47 memremap(nhlt_ptr->min_addr, nhlt_ptr->length, 48 MEMREMAP_WB); 49 ACPI_FREE(obj); 50 if (nhlt_table && (strncmp(nhlt_table->header.signature, 51 NHLT_ACPI_HEADER_SIG, 52 strlen(NHLT_ACPI_HEADER_SIG)) != 0)) { 53 memunmap(nhlt_table); 54 dev_err(dev, "NHLT ACPI header signature incorrect\n"); 55 return NULL; 56 } 57 return nhlt_table; 58 } 59 60 dev_err(dev, "device specific method to extract NHLT blob failed\n"); 61 return NULL; 62 } 63 64 void skl_nhlt_free(struct nhlt_acpi_table *nhlt) 65 { 66 memunmap((void *) nhlt); 67 } 68 69 static struct nhlt_specific_cfg *skl_get_specific_cfg( 70 struct device *dev, struct nhlt_fmt *fmt, 71 u8 no_ch, u32 rate, u16 bps, u8 linktype) 72 { 73 struct nhlt_specific_cfg *sp_config; 74 struct wav_fmt *wfmt; 75 struct nhlt_fmt_cfg *fmt_config = fmt->fmt_config; 76 int i; 77 78 dev_dbg(dev, "Format count =%d\n", fmt->fmt_count); 79 80 for (i = 0; i < fmt->fmt_count; i++) { 81 wfmt = &fmt_config->fmt_ext.fmt; 82 dev_dbg(dev, "ch=%d fmt=%d s_rate=%d\n", wfmt->channels, 83 wfmt->bits_per_sample, wfmt->samples_per_sec); 84 if (wfmt->channels == no_ch && wfmt->bits_per_sample == bps) { 85 /* 86 * if link type is dmic ignore rate check as the blob is 87 * generic for all rates 88 */ 89 sp_config = &fmt_config->config; 90 if (linktype == NHLT_LINK_DMIC) 91 return sp_config; 92 93 if (wfmt->samples_per_sec == rate) 94 return sp_config; 95 } 96 97 fmt_config = (struct nhlt_fmt_cfg *)(fmt_config->config.caps + 98 fmt_config->config.size); 99 } 100 101 return NULL; 102 } 103 104 static void dump_config(struct device *dev, u32 instance_id, u8 linktype, 105 u8 s_fmt, u8 num_channels, u32 s_rate, u8 dirn, u16 bps) 106 { 107 dev_dbg(dev, "Input configuration\n"); 108 dev_dbg(dev, "ch=%d fmt=%d s_rate=%d\n", num_channels, s_fmt, s_rate); 109 dev_dbg(dev, "vbus_id=%d link_type=%d\n", instance_id, linktype); 110 dev_dbg(dev, "bits_per_sample=%d\n", bps); 111 } 112 113 static bool skl_check_ep_match(struct device *dev, struct nhlt_endpoint *epnt, 114 u32 instance_id, u8 link_type, u8 dirn, u8 dev_type) 115 { 116 dev_dbg(dev, "vbus_id=%d link_type=%d dir=%d dev_type = %d\n", 117 epnt->virtual_bus_id, epnt->linktype, 118 epnt->direction, epnt->device_type); 119 120 if ((epnt->virtual_bus_id == instance_id) && 121 (epnt->linktype == link_type) && 122 (epnt->direction == dirn)) { 123 /* do not check dev_type for DMIC link type */ 124 if (epnt->linktype == NHLT_LINK_DMIC) 125 return true; 126 127 if (epnt->device_type == dev_type) 128 return true; 129 } 130 131 return false; 132 } 133 134 struct nhlt_specific_cfg 135 *skl_get_ep_blob(struct skl *skl, u32 instance, u8 link_type, 136 u8 s_fmt, u8 num_ch, u32 s_rate, 137 u8 dirn, u8 dev_type) 138 { 139 struct nhlt_fmt *fmt; 140 struct nhlt_endpoint *epnt; 141 struct hdac_bus *bus = ebus_to_hbus(&skl->ebus); 142 struct device *dev = bus->dev; 143 struct nhlt_specific_cfg *sp_config; 144 struct nhlt_acpi_table *nhlt = skl->nhlt; 145 u16 bps = (s_fmt == 16) ? 16 : 32; 146 u8 j; 147 148 dump_config(dev, instance, link_type, s_fmt, num_ch, s_rate, dirn, bps); 149 150 epnt = (struct nhlt_endpoint *)nhlt->desc; 151 152 dev_dbg(dev, "endpoint count =%d\n", nhlt->endpoint_count); 153 154 for (j = 0; j < nhlt->endpoint_count; j++) { 155 if (skl_check_ep_match(dev, epnt, instance, link_type, 156 dirn, dev_type)) { 157 fmt = (struct nhlt_fmt *)(epnt->config.caps + 158 epnt->config.size); 159 sp_config = skl_get_specific_cfg(dev, fmt, num_ch, 160 s_rate, bps, link_type); 161 if (sp_config) 162 return sp_config; 163 } 164 165 epnt = (struct nhlt_endpoint *)((u8 *)epnt + epnt->length); 166 } 167 168 return NULL; 169 } 170 171 int skl_get_dmic_geo(struct skl *skl) 172 { 173 struct nhlt_acpi_table *nhlt = (struct nhlt_acpi_table *)skl->nhlt; 174 struct nhlt_endpoint *epnt; 175 struct nhlt_dmic_array_config *cfg; 176 struct device *dev = &skl->pci->dev; 177 unsigned int dmic_geo = 0; 178 u8 j; 179 180 epnt = (struct nhlt_endpoint *)nhlt->desc; 181 182 for (j = 0; j < nhlt->endpoint_count; j++) { 183 if (epnt->linktype == NHLT_LINK_DMIC) { 184 cfg = (struct nhlt_dmic_array_config *) 185 (epnt->config.caps); 186 switch (cfg->array_type) { 187 case NHLT_MIC_ARRAY_2CH_SMALL: 188 case NHLT_MIC_ARRAY_2CH_BIG: 189 dmic_geo |= MIC_ARRAY_2CH; 190 break; 191 192 case NHLT_MIC_ARRAY_4CH_1ST_GEOM: 193 case NHLT_MIC_ARRAY_4CH_L_SHAPED: 194 case NHLT_MIC_ARRAY_4CH_2ND_GEOM: 195 dmic_geo |= MIC_ARRAY_4CH; 196 break; 197 198 default: 199 dev_warn(dev, "undefined DMIC array_type 0x%0x\n", 200 cfg->array_type); 201 202 } 203 } 204 epnt = (struct nhlt_endpoint *)((u8 *)epnt + epnt->length); 205 } 206 207 return dmic_geo; 208 } 209 210 static void skl_nhlt_trim_space(char *trim) 211 { 212 char *s = trim; 213 int cnt; 214 int i; 215 216 cnt = 0; 217 for (i = 0; s[i]; i++) { 218 if (!isspace(s[i])) 219 s[cnt++] = s[i]; 220 } 221 222 s[cnt] = '\0'; 223 } 224 225 int skl_nhlt_update_topology_bin(struct skl *skl) 226 { 227 struct nhlt_acpi_table *nhlt = (struct nhlt_acpi_table *)skl->nhlt; 228 struct hdac_bus *bus = ebus_to_hbus(&skl->ebus); 229 struct device *dev = bus->dev; 230 231 dev_dbg(dev, "oem_id %.6s, oem_table_id %8s oem_revision %d\n", 232 nhlt->header.oem_id, nhlt->header.oem_table_id, 233 nhlt->header.oem_revision); 234 235 snprintf(skl->tplg_name, sizeof(skl->tplg_name), "%x-%.6s-%.8s-%d%s", 236 skl->pci_id, nhlt->header.oem_id, nhlt->header.oem_table_id, 237 nhlt->header.oem_revision, "-tplg.bin"); 238 239 skl_nhlt_trim_space(skl->tplg_name); 240 241 return 0; 242 } 243 244 static ssize_t skl_nhlt_platform_id_show(struct device *dev, 245 struct device_attribute *attr, char *buf) 246 { 247 struct pci_dev *pci = to_pci_dev(dev); 248 struct hdac_ext_bus *ebus = pci_get_drvdata(pci); 249 struct skl *skl = ebus_to_skl(ebus); 250 struct nhlt_acpi_table *nhlt = (struct nhlt_acpi_table *)skl->nhlt; 251 char platform_id[32]; 252 253 sprintf(platform_id, "%x-%.6s-%.8s-%d", skl->pci_id, 254 nhlt->header.oem_id, nhlt->header.oem_table_id, 255 nhlt->header.oem_revision); 256 257 skl_nhlt_trim_space(platform_id); 258 return sprintf(buf, "%s\n", platform_id); 259 } 260 261 static DEVICE_ATTR(platform_id, 0444, skl_nhlt_platform_id_show, NULL); 262 263 int skl_nhlt_create_sysfs(struct skl *skl) 264 { 265 struct device *dev = &skl->pci->dev; 266 267 if (sysfs_create_file(&dev->kobj, &dev_attr_platform_id.attr)) 268 dev_warn(dev, "Error creating sysfs entry\n"); 269 270 return 0; 271 } 272 273 void skl_nhlt_remove_sysfs(struct skl *skl) 274 { 275 struct device *dev = &skl->pci->dev; 276 277 sysfs_remove_file(&dev->kobj, &dev_attr_platform_id.attr); 278 } 279