^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0-only
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) // Copyright (c) 2015-2019 Intel Corporation
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) #include <linux/acpi.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) #include <sound/intel-nhlt.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) struct nhlt_acpi_table *intel_nhlt_init(struct device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) struct nhlt_acpi_table *nhlt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) acpi_status status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) status = acpi_get_table(ACPI_SIG_NHLT, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) (struct acpi_table_header **)&nhlt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) if (ACPI_FAILURE(status)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) dev_warn(dev, "NHLT table not found\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) return nhlt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) EXPORT_SYMBOL_GPL(intel_nhlt_init);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) void intel_nhlt_free(struct nhlt_acpi_table *nhlt)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) acpi_put_table((struct acpi_table_header *)nhlt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) EXPORT_SYMBOL_GPL(intel_nhlt_free);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) int intel_nhlt_get_dmic_geo(struct device *dev, struct nhlt_acpi_table *nhlt)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) struct nhlt_endpoint *epnt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) struct nhlt_dmic_array_config *cfg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) struct nhlt_vendor_dmic_array_config *cfg_vendor;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) struct nhlt_fmt *fmt_configs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) unsigned int dmic_geo = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) u16 max_ch = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) u8 i, j;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) if (!nhlt)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) if (nhlt->header.length <= sizeof(struct acpi_table_header)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) dev_warn(dev, "Invalid DMIC description table\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) for (j = 0, epnt = nhlt->desc; j < nhlt->endpoint_count; j++,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) epnt = (struct nhlt_endpoint *)((u8 *)epnt + epnt->length)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) if (epnt->linktype != NHLT_LINK_DMIC)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) cfg = (struct nhlt_dmic_array_config *)(epnt->config.caps);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) fmt_configs = (struct nhlt_fmt *)(epnt->config.caps + epnt->config.size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) /* find max number of channels based on format_configuration */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) if (fmt_configs->fmt_count) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) dev_dbg(dev, "%s: found %d format definitions\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) __func__, fmt_configs->fmt_count);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) for (i = 0; i < fmt_configs->fmt_count; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) struct wav_fmt_ext *fmt_ext;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) fmt_ext = &fmt_configs->fmt_config[i].fmt_ext;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) if (fmt_ext->fmt.channels > max_ch)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) max_ch = fmt_ext->fmt.channels;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) dev_dbg(dev, "%s: max channels found %d\n", __func__, max_ch);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) dev_dbg(dev, "%s: No format information found\n", __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) if (cfg->device_config.config_type != NHLT_CONFIG_TYPE_MIC_ARRAY) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) dmic_geo = max_ch;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) switch (cfg->array_type) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) case NHLT_MIC_ARRAY_2CH_SMALL:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) case NHLT_MIC_ARRAY_2CH_BIG:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) dmic_geo = MIC_ARRAY_2CH;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) case NHLT_MIC_ARRAY_4CH_1ST_GEOM:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) case NHLT_MIC_ARRAY_4CH_L_SHAPED:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) case NHLT_MIC_ARRAY_4CH_2ND_GEOM:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) dmic_geo = MIC_ARRAY_4CH;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) case NHLT_MIC_ARRAY_VENDOR_DEFINED:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) cfg_vendor = (struct nhlt_vendor_dmic_array_config *)cfg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) dmic_geo = cfg_vendor->nb_mics;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) dev_warn(dev, "%s: undefined DMIC array_type 0x%0x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) __func__, cfg->array_type);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) if (dmic_geo > 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) dev_dbg(dev, "%s: Array with %d dmics\n", __func__, dmic_geo);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) if (max_ch > dmic_geo) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) dev_dbg(dev, "%s: max channels %d exceed dmic number %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) __func__, max_ch, dmic_geo);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) dev_dbg(dev, "%s: dmic number %d max_ch %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) __func__, dmic_geo, max_ch);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) return dmic_geo;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) EXPORT_SYMBOL_GPL(intel_nhlt_get_dmic_geo);