blob: e2237239d922a7c778148a160560340e97a95660 [file] [log] [blame]
Pierre-Louis Bossarte149ca22020-05-01 09:58:50 -05001// SPDX-License-Identifier: GPL-2.0-only
Pierre-Louis Bossart303681f2019-07-29 10:51:48 -05002// Copyright (c) 2015-2019 Intel Corporation
3
4#include <linux/acpi.h>
5#include <sound/intel-nhlt.h>
6
Pierre-Louis Bossart303681f2019-07-29 10:51:48 -05007struct nhlt_acpi_table *intel_nhlt_init(struct device *dev)
8{
Cezary Rojewski0d283287a2020-04-23 18:03:10 +02009 struct nhlt_acpi_table *nhlt;
10 acpi_status status;
Pierre-Louis Bossart303681f2019-07-29 10:51:48 -050011
Cezary Rojewski0d283287a2020-04-23 18:03:10 +020012 status = acpi_get_table(ACPI_SIG_NHLT, 0,
13 (struct acpi_table_header **)&nhlt);
14 if (ACPI_FAILURE(status)) {
15 dev_warn(dev, "NHLT table not found\n");
Pierre-Louis Bossart303681f2019-07-29 10:51:48 -050016 return NULL;
17 }
18
Cezary Rojewski0d283287a2020-04-23 18:03:10 +020019 return nhlt;
Pierre-Louis Bossart303681f2019-07-29 10:51:48 -050020}
21EXPORT_SYMBOL_GPL(intel_nhlt_init);
22
23void intel_nhlt_free(struct nhlt_acpi_table *nhlt)
24{
Cezary Rojewski0d283287a2020-04-23 18:03:10 +020025 acpi_put_table((struct acpi_table_header *)nhlt);
Pierre-Louis Bossart303681f2019-07-29 10:51:48 -050026}
27EXPORT_SYMBOL_GPL(intel_nhlt_free);
28
29int intel_nhlt_get_dmic_geo(struct device *dev, struct nhlt_acpi_table *nhlt)
30{
31 struct nhlt_endpoint *epnt;
32 struct nhlt_dmic_array_config *cfg;
Pierre-Louis Bossart7a33ea72019-07-29 10:51:49 -050033 struct nhlt_vendor_dmic_array_config *cfg_vendor;
Pierre-Louis Bossarta864e8f2021-03-01 18:01:46 -060034 struct nhlt_fmt *fmt_configs;
Pierre-Louis Bossart303681f2019-07-29 10:51:48 -050035 unsigned int dmic_geo = 0;
Pierre-Louis Bossarta864e8f2021-03-01 18:01:46 -060036 u16 max_ch = 0;
37 u8 i, j;
Pierre-Louis Bossart303681f2019-07-29 10:51:48 -050038
39 if (!nhlt)
40 return 0;
41
Mark Pearsona14a6212021-03-02 09:10:03 -050042 if (nhlt->header.length <= sizeof(struct acpi_table_header)) {
43 dev_warn(dev, "Invalid DMIC description table\n");
44 return 0;
45 }
46
Pierre-Louis Bossarta864e8f2021-03-01 18:01:46 -060047 for (j = 0, epnt = nhlt->desc; j < nhlt->endpoint_count; j++,
48 epnt = (struct nhlt_endpoint *)((u8 *)epnt + epnt->length)) {
Pierre-Louis Bossart303681f2019-07-29 10:51:48 -050049
Pierre-Louis Bossarta864e8f2021-03-01 18:01:46 -060050 if (epnt->linktype != NHLT_LINK_DMIC)
51 continue;
52
53 cfg = (struct nhlt_dmic_array_config *)(epnt->config.caps);
54 fmt_configs = (struct nhlt_fmt *)(epnt->config.caps + epnt->config.size);
55
56 /* find max number of channels based on format_configuration */
57 if (fmt_configs->fmt_count) {
58 dev_dbg(dev, "%s: found %d format definitions\n",
59 __func__, fmt_configs->fmt_count);
60
61 for (i = 0; i < fmt_configs->fmt_count; i++) {
62 struct wav_fmt_ext *fmt_ext;
63
64 fmt_ext = &fmt_configs->fmt_config[i].fmt_ext;
65
66 if (fmt_ext->fmt.channels > max_ch)
67 max_ch = fmt_ext->fmt.channels;
68 }
69 dev_dbg(dev, "%s: max channels found %d\n", __func__, max_ch);
70 } else {
71 dev_dbg(dev, "%s: No format information found\n", __func__);
72 }
73
74 if (cfg->device_config.config_type != NHLT_CONFIG_TYPE_MIC_ARRAY) {
75 dmic_geo = max_ch;
76 } else {
Pierre-Louis Bossart303681f2019-07-29 10:51:48 -050077 switch (cfg->array_type) {
78 case NHLT_MIC_ARRAY_2CH_SMALL:
79 case NHLT_MIC_ARRAY_2CH_BIG:
80 dmic_geo = MIC_ARRAY_2CH;
81 break;
82
83 case NHLT_MIC_ARRAY_4CH_1ST_GEOM:
84 case NHLT_MIC_ARRAY_4CH_L_SHAPED:
85 case NHLT_MIC_ARRAY_4CH_2ND_GEOM:
86 dmic_geo = MIC_ARRAY_4CH;
87 break;
Pierre-Louis Bossart7a33ea72019-07-29 10:51:49 -050088 case NHLT_MIC_ARRAY_VENDOR_DEFINED:
89 cfg_vendor = (struct nhlt_vendor_dmic_array_config *)cfg;
90 dmic_geo = cfg_vendor->nb_mics;
91 break;
Pierre-Louis Bossart303681f2019-07-29 10:51:48 -050092 default:
Pierre-Louis Bossarta864e8f2021-03-01 18:01:46 -060093 dev_warn(dev, "%s: undefined DMIC array_type 0x%0x\n",
94 __func__, cfg->array_type);
95 }
96
97 if (dmic_geo > 0) {
98 dev_dbg(dev, "%s: Array with %d dmics\n", __func__, dmic_geo);
99 }
100 if (max_ch > dmic_geo) {
101 dev_dbg(dev, "%s: max channels %d exceed dmic number %d\n",
102 __func__, max_ch, dmic_geo);
Pierre-Louis Bossart303681f2019-07-29 10:51:48 -0500103 }
104 }
Pierre-Louis Bossart303681f2019-07-29 10:51:48 -0500105 }
106
Pierre-Louis Bossarta864e8f2021-03-01 18:01:46 -0600107 dev_dbg(dev, "%s: dmic number %d max_ch %d\n",
108 __func__, dmic_geo, max_ch);
109
Pierre-Louis Bossart303681f2019-07-29 10:51:48 -0500110 return dmic_geo;
111}
112EXPORT_SYMBOL_GPL(intel_nhlt_get_dmic_geo);