Skip to content

Commit a864e8f

Browse files
plbossarttiwai
authored andcommitted
ALSA: hda: intel-nhlt: verify config type
Multiple bug reports report issues with the SOF and SST drivers when dealing with single microphone cases. We currently read the DMIC array information unconditionally but we don't check that the configuration type is actually a mic array. When the DMIC link does not rely on a mic array configuration, the recommendation is to check the format information to infer the maximum number of channels, and map this to the number of microphones. This leaves a potential for a mismatch between actual microphones available in hardware and what the ACPI table contains, but we have no other source of information. Note that single microphone configurations can alternatively be handled with a 'mic array' configuration along with a 'vendor-defined' geometry. Bugzilla: https://bugzilla.kernel.org/show_bug.cgi?id=201251 BugLink: thesofproject/linux#2725 Fixes: 7a33ea7 ('ALSA: hda: intel-nhlt: handle NHLT VENDOR_DEFINED DMIC geometry') Signed-off-by: Pierre-Louis Bossart <[email protected]> Reviewed-by: Guennadi Liakhovetski <[email protected]> Reviewed-by: Rander Wang <[email protected]> Reviewed-by: Kai Vehmanen <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Takashi Iwai <[email protected]>
1 parent 3531ba2 commit a864e8f

File tree

2 files changed

+50
-9
lines changed

2 files changed

+50
-9
lines changed

include/sound/intel-nhlt.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,11 @@ struct nhlt_vendor_dmic_array_config {
112112
/* TODO add vendor mic config */
113113
} __packed;
114114

115+
enum {
116+
NHLT_CONFIG_TYPE_GENERIC = 0,
117+
NHLT_CONFIG_TYPE_MIC_ARRAY = 1
118+
};
119+
115120
enum {
116121
NHLT_MIC_ARRAY_2CH_SMALL = 0xa,
117122
NHLT_MIC_ARRAY_2CH_BIG = 0xb,

sound/hda/intel-nhlt.c

Lines changed: 45 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -31,18 +31,44 @@ int intel_nhlt_get_dmic_geo(struct device *dev, struct nhlt_acpi_table *nhlt)
3131
struct nhlt_endpoint *epnt;
3232
struct nhlt_dmic_array_config *cfg;
3333
struct nhlt_vendor_dmic_array_config *cfg_vendor;
34+
struct nhlt_fmt *fmt_configs;
3435
unsigned int dmic_geo = 0;
35-
u8 j;
36+
u16 max_ch = 0;
37+
u8 i, j;
3638

3739
if (!nhlt)
3840
return 0;
3941

40-
epnt = (struct nhlt_endpoint *)nhlt->desc;
42+
for (j = 0, epnt = nhlt->desc; j < nhlt->endpoint_count; j++,
43+
epnt = (struct nhlt_endpoint *)((u8 *)epnt + epnt->length)) {
4144

42-
for (j = 0; j < nhlt->endpoint_count; j++) {
43-
if (epnt->linktype == NHLT_LINK_DMIC) {
44-
cfg = (struct nhlt_dmic_array_config *)
45-
(epnt->config.caps);
45+
if (epnt->linktype != NHLT_LINK_DMIC)
46+
continue;
47+
48+
cfg = (struct nhlt_dmic_array_config *)(epnt->config.caps);
49+
fmt_configs = (struct nhlt_fmt *)(epnt->config.caps + epnt->config.size);
50+
51+
/* find max number of channels based on format_configuration */
52+
if (fmt_configs->fmt_count) {
53+
dev_dbg(dev, "%s: found %d format definitions\n",
54+
__func__, fmt_configs->fmt_count);
55+
56+
for (i = 0; i < fmt_configs->fmt_count; i++) {
57+
struct wav_fmt_ext *fmt_ext;
58+
59+
fmt_ext = &fmt_configs->fmt_config[i].fmt_ext;
60+
61+
if (fmt_ext->fmt.channels > max_ch)
62+
max_ch = fmt_ext->fmt.channels;
63+
}
64+
dev_dbg(dev, "%s: max channels found %d\n", __func__, max_ch);
65+
} else {
66+
dev_dbg(dev, "%s: No format information found\n", __func__);
67+
}
68+
69+
if (cfg->device_config.config_type != NHLT_CONFIG_TYPE_MIC_ARRAY) {
70+
dmic_geo = max_ch;
71+
} else {
4672
switch (cfg->array_type) {
4773
case NHLT_MIC_ARRAY_2CH_SMALL:
4874
case NHLT_MIC_ARRAY_2CH_BIG:
@@ -59,13 +85,23 @@ int intel_nhlt_get_dmic_geo(struct device *dev, struct nhlt_acpi_table *nhlt)
5985
dmic_geo = cfg_vendor->nb_mics;
6086
break;
6187
default:
62-
dev_warn(dev, "undefined DMIC array_type 0x%0x\n",
63-
cfg->array_type);
88+
dev_warn(dev, "%s: undefined DMIC array_type 0x%0x\n",
89+
__func__, cfg->array_type);
90+
}
91+
92+
if (dmic_geo > 0) {
93+
dev_dbg(dev, "%s: Array with %d dmics\n", __func__, dmic_geo);
94+
}
95+
if (max_ch > dmic_geo) {
96+
dev_dbg(dev, "%s: max channels %d exceed dmic number %d\n",
97+
__func__, max_ch, dmic_geo);
6498
}
6599
}
66-
epnt = (struct nhlt_endpoint *)((u8 *)epnt + epnt->length);
67100
}
68101

102+
dev_dbg(dev, "%s: dmic number %d max_ch %d\n",
103+
__func__, dmic_geo, max_ch);
104+
69105
return dmic_geo;
70106
}
71107
EXPORT_SYMBOL_GPL(intel_nhlt_get_dmic_geo);

0 commit comments

Comments
 (0)